Merge "Clarify the "Watchlist-details" message"
authorSiebrand <siebrand@kitano.nl>
Fri, 11 Apr 2014 06:09:39 +0000 (06:09 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Fri, 11 Apr 2014 06:09:39 +0000 (06:09 +0000)
1590 files changed:
.jshintignore
.jshintrc
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/CategoryViewer.php
includes/DefaultSettings.php
includes/EditPage.php
includes/Export.php
includes/FileDeleteForm.php
includes/GlobalFunctions.php
includes/Html.php
includes/HtmlFormatter.php
includes/Linker.php
includes/MimeMagic.php
includes/OutputPage.php
includes/SkinTemplate.php
includes/Status.php
includes/Title.php
includes/Wiki.php
includes/WikiPage.php
includes/ZhConversion.php
includes/api/ApiQueryDeletedrevs.php
includes/changes/EnhancedChangesList.php
includes/changes/RecentChange.php
includes/clientpool/RedisConnectionPool.php
includes/content/AbstractContent.php
includes/content/Content.php
includes/content/WikitextContent.php
includes/db/DatabaseMssql.php
includes/db/LBFactory.php
includes/deferred/LinksUpdate.php
includes/diff/DifferenceEngine.php
includes/filerepo/ForeignAPIRepo.php
includes/filerepo/file/LocalFile.php
includes/htmlform/HTMLSelectAndOtherField.php
includes/installer/DatabaseUpdater.php
includes/installer/MysqlInstaller.php
includes/installer/PostgresInstaller.php
includes/installer/WebInstaller.php
includes/installer/WebInstallerOutput.php
includes/installer/WebInstallerPage.php
includes/installer/i18n/en.json
includes/installer/i18n/qqq.json
includes/jobqueue/JobQueue.php
includes/jobqueue/JobQueueFederated.php
includes/jobqueue/JobQueueGroup.php
includes/jobqueue/jobs/AssembleUploadChunksJob.php
includes/jobqueue/jobs/HTMLCacheUpdateJob.php
includes/jobqueue/jobs/PublishStashedFileJob.php
includes/libs/MultiHttpClient.php
includes/logging/LogFormatter.php
includes/logging/LogPager.php
includes/media/Exif.php
includes/media/GIF.php
includes/parser/CoreParserFunctions.php
includes/parser/DateFormatter.php
includes/parser/Parser.php
includes/parser/ParserCache.php
includes/parser/ParserOptions.php
includes/poolcounter/PoolCounterRedis.php
includes/profiler/ProfilerSimple.php
includes/resourceloader/ResourceLoader.php
includes/resourceloader/ResourceLoaderStartUpModule.php
includes/search/SearchEngine.php
includes/site/SiteSQLStore.php
includes/specials/SpecialActiveusers.php
includes/specials/SpecialAllpages.php
includes/specials/SpecialBlock.php
includes/specials/SpecialEmailuser.php
includes/specials/SpecialListgrouprights.php
includes/specials/SpecialPrefixindex.php
includes/specials/SpecialSearch.php
includes/specials/SpecialUserrights.php
includes/specials/SpecialVersion.php
includes/upload/UploadStash.php
includes/utils/UIDGenerator.php
languages/ConverterRule.php [new file with mode: 0644]
languages/LanguageConverter.php
languages/classes/LanguageSr.php
languages/i18n/ace.json
languages/i18n/af.json
languages/i18n/aln.json
languages/i18n/am.json
languages/i18n/an.json
languages/i18n/anp.json
languages/i18n/ar.json
languages/i18n/arc.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/bbc-latn.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/bqi.json
languages/i18n/br.json
languages/i18n/brh.json
languages/i18n/bs.json
languages/i18n/bug.json
languages/i18n/bxr.json
languages/i18n/ca.json
languages/i18n/ce.json
languages/i18n/ckb.json
languages/i18n/crh-cyrl.json
languages/i18n/crh-latn.json
languages/i18n/cs.json
languages/i18n/cy.json
languages/i18n/da.json
languages/i18n/de.json
languages/i18n/diq.json
languages/i18n/dsb.json
languages/i18n/dz.json
languages/i18n/egl.json
languages/i18n/el.json
languages/i18n/eml.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/ff.json
languages/i18n/fi.json
languages/i18n/fit.json
languages/i18n/fo.json
languages/i18n/fr.json
languages/i18n/frc.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/gom-latn.json
languages/i18n/got.json
languages/i18n/gsw.json
languages/i18n/gu.json
languages/i18n/ha.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/ik.json
languages/i18n/ilo.json
languages/i18n/io.json
languages/i18n/is.json
languages/i18n/it.json
languages/i18n/ja.json
languages/i18n/jbo.json
languages/i18n/jut.json
languages/i18n/jv.json
languages/i18n/ka.json
languages/i18n/kaa.json
languages/i18n/kab.json
languages/i18n/kg.json
languages/i18n/kiu.json
languages/i18n/kk-arab.json
languages/i18n/kk-cyrl.json
languages/i18n/kk-latn.json
languages/i18n/kl.json
languages/i18n/ko.json
languages/i18n/koi.json
languages/i18n/krc.json
languages/i18n/kri.json
languages/i18n/ksh.json
languages/i18n/la.json
languages/i18n/lb.json
languages/i18n/lez.json
languages/i18n/li.json
languages/i18n/liv.json
languages/i18n/loz.json
languages/i18n/lt.json
languages/i18n/lv.json
languages/i18n/lzh.json
languages/i18n/lzz.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/mo.json
languages/i18n/mrj.json
languages/i18n/ms.json
languages/i18n/mt.json
languages/i18n/na.json
languages/i18n/nan.json
languages/i18n/nb.json
languages/i18n/nds-nl.json
languages/i18n/nds.json
languages/i18n/ne.json
languages/i18n/new.json
languages/i18n/niu.json
languages/i18n/nl.json
languages/i18n/nn.json
languages/i18n/nov.json
languages/i18n/nv.json
languages/i18n/oc.json
languages/i18n/or.json
languages/i18n/pag.json
languages/i18n/pap.json
languages/i18n/pdt.json
languages/i18n/pih.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/rgn.json
languages/i18n/rif.json
languages/i18n/rm.json
languages/i18n/rmy.json
languages/i18n/ro.json
languages/i18n/roa-tara.json
languages/i18n/ru.json
languages/i18n/rue.json
languages/i18n/rup.json
languages/i18n/ruq-cyrl.json
languages/i18n/ruq-latn.json
languages/i18n/sa.json
languages/i18n/sah.json
languages/i18n/scn.json
languages/i18n/sco.json
languages/i18n/sd.json
languages/i18n/sdc.json
languages/i18n/sg.json
languages/i18n/sh.json
languages/i18n/si.json
languages/i18n/sk.json
languages/i18n/sl.json
languages/i18n/sli.json
languages/i18n/sma.json
languages/i18n/so.json
languages/i18n/sq.json
languages/i18n/sr-ec.json
languages/i18n/sr-el.json
languages/i18n/ss.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/udm.json
languages/i18n/ug-arab.json
languages/i18n/uk.json
languages/i18n/uz.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/za.json
languages/i18n/zh-cn.json [deleted file]
languages/i18n/zh-hans.json
languages/i18n/zh-hant.json
languages/i18n/zu.json
languages/messages/MessagesAr.php
languages/messages/MessagesEn.php
languages/messages/MessagesOr.php
languages/messages/MessagesPl.php
languages/utils/CLDRPluralRuleConverter.php [new file with mode: 0644]
languages/utils/CLDRPluralRuleConverter_Expression.php [new file with mode: 0644]
languages/utils/CLDRPluralRuleConverter_Fragment.php [new file with mode: 0644]
languages/utils/CLDRPluralRuleConverter_Operator.php [new file with mode: 0644]
languages/utils/CLDRPluralRuleError.php [new file with mode: 0644]
languages/utils/CLDRPluralRuleEvaluator.php
languages/utils/CLDRPluralRuleEvaluator_Range.php [new file with mode: 0644]
maintenance/jsduck/config.json
maintenance/language/messages.inc
maintenance/language/zhtable/tradphrases.manual
maintenance/resetUserTokens.php
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/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/IEFixes.js
skins/common/commonElements.css
skins/common/images/button_math.png [deleted file]
skins/common/shared.css
skins/vector/components/common.less
skins/vector/components/externalLinks.less
skins/vector/variables.less
tests/frontend/package.json
tests/phpunit/includes/GlobalFunctions/GlobalTest.php
tests/phpunit/includes/RevisionTest.php
tests/phpunit/includes/TitleTest.php
tests/phpunit/includes/api/RandomImageGenerator.php
tests/phpunit/includes/content/ContentHandlerTest.php
tests/phpunit/includes/jobqueue/JobQueueTest.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/phpunit/structure/ResourcesTest.php
tests/qunit/QUnitTestResources.php
tests/qunit/data/testrunner.js
tests/qunit/suites/resources/mediawiki.api/mediawiki.api.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.Title.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.Uri.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.jqueryMsg.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.test.js
tests/qunit/suites/resources/startup.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 9d6c4d2..4eec7a0 100644 (file)
--- a/.jshintrc
+++ b/.jshintrc
@@ -3,6 +3,7 @@
 
        // Enforcing
        "eqeqeq": true,
+       "es3": true,
        "latedef": true,
        "noarg": true,
        "nonew": true,
index d833018..947a0d6 100644 (file)
@@ -11,7 +11,9 @@ production.
 === Configuration changes in 1.23 ===
 * When $wgJobRunRate is higher that zero, jobs are now executed via an
   asynchronous HTTP request to a MediaWiki entry point. This may require
-  increasing the number of server worker threads.
+  increasing the number of server worker threads. $wgRunJobsAsync has been
+  added to disable this feature if needed, falling back to executing the job
+  on the same process but making the execution synchronously.
 * $wgDebugLogGroups values may be set to an associative array with a
   'destination' key specifying the log destination. The array may also contain
   a 'sample' key with a positive integer value N indicating that the log group
@@ -54,6 +56,7 @@ production.
 * $wgLicenseTerms has been removed as it was unused.
 * $wgProfileOnly is now deprecated; set the log file in
   $wgDebugLogGroups['profileoutput'] to replace it.
+* $wgMaxBacklinksInvalidate was removed; use $wgJobBackoffThrottling instead
 
 === New features in 1.23 ===
 * ResourceLoader can utilize the Web Storage API to cache modules client-side.
@@ -136,6 +139,9 @@ production.
   installer has been updated to use it.
 * Changes to content typography (fonts, line-height, etc.). See
   https://www.mediawiki.org/wiki/Typography_refresh for further information.
+* The Vector skin's visual treatment of external links has been simplified to a
+  single icon (from nine). This should not affect local rules unless they were
+  re-using these icons, which have now been deleted.
 * ResourceLoader: mw.loader.using() now implements a Promise interface.
 * Add new hook ChangesListInitRows accessed via ChangesList::initChangesListRows.
   If called by the ChangesList consumer this gives extensions a chance to batch
@@ -328,6 +334,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 52b292f..6675860 100644 (file)
@@ -1121,17 +1121,17 @@ $wgAutoloadLocalClasses = array(
        'ZipDirectoryReaderError' => 'includes/utils/ZipDirectoryReader.php',
 
        # languages
-       'ConverterRule' => 'languages/LanguageConverter.php',
+       'ConverterRule' => 'languages/ConverterRule.php',
        'FakeConverter' => 'languages/Language.php',
        'Language' => 'languages/Language.php',
        'LanguageConverter' => 'languages/LanguageConverter.php',
-       'CLDRPluralRuleConverter' => 'languages/utils/CLDRPluralRuleEvaluator.php',
-       'CLDRPluralRuleConverter_Expression' => 'languages/utils/CLDRPluralRuleEvaluator.php',
-       'CLDRPluralRuleConverter_Fragment' => 'languages/utils/CLDRPluralRuleEvaluator.php',
-       'CLDRPluralRuleConverter_Operator' => 'languages/utils/CLDRPluralRuleEvaluator.php',
+       'CLDRPluralRuleConverter' => 'languages/utils/CLDRPluralRuleConverter.php',
+       'CLDRPluralRuleConverter_Expression' => 'languages/utils/CLDRPluralRuleConverter_Expression.php',
+       'CLDRPluralRuleConverter_Fragment' => 'languages/utils/CLDRPluralRuleConverter_Fragment.php',
+       'CLDRPluralRuleConverter_Operator' => 'languages/utils/CLDRPluralRuleConverter_Operator.php',
        'CLDRPluralRuleEvaluator' => 'languages/utils/CLDRPluralRuleEvaluator.php',
-       'CLDRPluralRuleEvaluator_Range' => 'languages/utils/CLDRPluralRuleEvaluator.php',
-       'CLDRPluralRuleError' => 'languages/utils/CLDRPluralRuleEvaluator.php',
+       'CLDRPluralRuleEvaluator_Range' => 'languages/utils/CLDRPluralRuleEvaluator_Range.php',
+       'CLDRPluralRuleError' => 'languages/utils/CLDRPluralRuleError.php',
 
        # maintenance
        'BackupDumper' => 'maintenance/backup.inc',
index 74ece4c..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
index 183c5f2..7f213c3 100644 (file)
@@ -449,7 +449,7 @@ class CategoryViewer extends ContextSource {
         * of the output.
         *
         * @param string $type 'page', 'subcat', or 'file'
-        * @return String: HTML output, possibly empty if there are no other pages
+        * @return string HTML output, possibly empty if there are no other pages
         */
        private function getSectionPagingLinks( $type ) {
                if ( isset( $this->until[$type] ) && $this->until[$type] !== null ) {
@@ -628,8 +628,8 @@ class CategoryViewer extends ContextSource {
         * Takes a title, and adds the fragment identifier that
         * corresponds to the correct segment of the category.
         *
-        * @param Title $title: The title (usually $this->title)
-        * @param string $section: Which section
+        * @param Title $title The title (usually $this->title)
+        * @param string $section Which section
         * @throws MWException
         * @return Title
         */
@@ -661,7 +661,7 @@ class CategoryViewer extends ContextSource {
         * @param int $rescnt The number of items returned by our database query.
         * @param int $dbcnt The number of items according to the category table.
         * @param string $type 'subcat', 'article', or 'file'
-        * @return string: A message giving the number of items, to output to HTML.
+        * @return string A message giving the number of items, to output to HTML.
         */
        private function getCountMessage( $rescnt, $dbcnt, $type ) {
                // There are three cases:
index bb5d26d..8b8d75c 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/",
 );
 
@@ -5637,6 +5637,10 @@ $wgRC2UDPOmitBots = false;
  *   * 'formatter' -- the class name (implementing RCFeedFormatter) which will
  *     produce the text to send.
  *   * 'omit_bots' -- whether the bot edits should be in the feed
+ *   * 'omit_anon' -- whether anonymous edits should be in the feed
+ *   * 'omit_user' -- whether edits by registered users should be in the feed
+ *   * 'omit_minor' -- whether minor edits should be in the feed
+ *   * 'omit_patrolled' -- whether patrolled edits should be in the feed
  *  The IRC-specific options are:
  *   * 'add_interwiki_prefix' -- whether the titles should be prefixed with
  *     the first entry in the $wgLocalInterwikis array (or the value of
@@ -6028,7 +6032,7 @@ $wgExtensionMessagesFiles = array();
  */
 $wgMessagesDirs = array(
        'core' => "$IP/languages/i18n",
-       'oojs-ui' => "$IP/resources/oojs-ui/i18n",
+       'oojs-ui' => "$IP/resources/lib/oojs-ui/i18n",
 );
 
 /**
@@ -6207,6 +6211,7 @@ $wgJobTypesExcludedFromDefaultQueue = array( 'AssembleUploadChunks', 'PublishSta
  * on each job runner process. The meaning of "work items" varies per job,
  * but typically would be something like "pages to update". A single job
  * may have a variable number of work items, as is the case with batch jobs.
+ * This is used by runJobs.php and not jobs run via $wgJobRunRate.
  * These settings should be global to all wikis.
  */
 $wgJobBackoffThrottling = array();
@@ -6917,6 +6922,14 @@ $wgHTTPConnectTimeout = 5e0;
  */
 $wgJobRunRate = 1;
 
+/**
+ * When $wgJobRunRate > 0, try to run jobs asynchronously, spawning a new process
+ * to handle the job execution, instead of blocking the request until the job
+ * execution finishes.
+ * @since 1.23
+ */
+$wgRunJobsAsync = true;
+
 /**
  * Number of rows to update per job
  */
@@ -6927,15 +6940,6 @@ $wgUpdateRowsPerJob = 500;
  */
 $wgUpdateRowsPerQuery = 100;
 
-/**
- * Do not purge all the pages that use a page when it is edited
- * if there are more than this many such pages. This is used to
- * avoid invalidating a large portion of the squid/parser cache.
- *
- * This setting should factor in any squid/parser cache expiry settings.
- */
-$wgMaxBacklinksInvalidate = false;
-
 /** @} */ # End job queue }
 
 /************************************************************************//**
index f57fc60..61995f2 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 );
        }
 
        /**
@@ -1341,8 +1344,8 @@ class EditPage {
         * Run hooks that can filter edits just before they get saved.
         *
         * @param Content $content the Content to filter.
-        * @param Status  $status for reporting the outcome to the caller
-        * @param User    $user the user performing the edit
+        * @param Status $status For reporting the outcome to the caller
+        * @param User $user The user performing the edit
         *
         * @return bool
         */
@@ -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
                        ) {
@@ -2603,11 +2606,11 @@ class EditPage {
        }
 
        /**
-        * @param $isSubjectPreview Boolean: true if this is the section subject/title
-        *                          up top, or false if this is the comment summary
-        *                          down below the textarea
+        * @param bool $isSubjectPreview true if this is the section subject/title
+        *   up top, or false if this is the comment summary
+        *   down below the textarea
         * @param string $summary The text of the summary to display
-        * @return String
+        * @return string
         */
        protected function showSummaryInput( $isSubjectPreview, $summary = "" ) {
                global $wgOut, $wgContLang;
@@ -2629,11 +2632,11 @@ class EditPage {
        }
 
        /**
-        * @param $isSubjectPreview Boolean: true if this is the section subject/title
-        *                          up top, or false if this is the comment summary
-        *                          down below the textarea
+        * @param bool $isSubjectPreview true if this is the section subject/title
+        *   up top, or false if this is the comment summary
+        *   down below the textarea
         * @param string $summary the text of the summary to display
-        * @return String
+        * @return string
         */
        protected function getSummaryPreview( $isSubjectPreview, $summary = "" ) {
                // avoid spaces in preview, gets always trimmed on save
@@ -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 4c0eb30..2844a06 100644 (file)
@@ -73,15 +73,14 @@ class WikiExporter {
         * make additional queries to pull source data while the
         * main query is still running.
         *
-        * @param $db DatabaseBase
-        * @param $history Mixed: one of WikiExporter::FULL, WikiExporter::CURRENT,
-        *                 WikiExporter::RANGE or WikiExporter::STABLE,
-        *                 or an associative array:
-        *                   offset: non-inclusive offset at which to start the query
-        *                   limit: maximum number of rows to return
-        *                   dir: "asc" or "desc" timestamp order
-        * @param int $buffer one of WikiExporter::BUFFER or WikiExporter::STREAM
-        * @param int $text one of WikiExporter::TEXT or WikiExporter::STUB
+        * @param DatabaseBase $db
+        * @param int|array $history One of WikiExporter::FULL, WikiExporter::CURRENT,
+        *   WikiExporter::RANGE or WikiExporter::STABLE, or an associative array:
+        *   - offset: non-inclusive offset at which to start the query
+        *   - limit: maximum number of rows to return
+        *   - dir: "asc" or "desc" timestamp order
+        * @param int $buffer One of WikiExporter::BUFFER or WikiExporter::STREAM
+        * @param int $text One of WikiExporter::TEXT or WikiExporter::STUB
         */
        function __construct( $db, $history = WikiExporter::CURRENT,
                        $buffer = WikiExporter::BUFFER, $text = WikiExporter::TEXT ) {
@@ -127,8 +126,8 @@ class WikiExporter {
         * Dumps a series of page and revision records for those pages
         * in the database falling within the page_id range given.
         * @param int $start inclusive lower limit (this id is included)
-        * @param $end   Int: Exclusive upper limit (this id is not included)
-        *                   If 0, no upper limit.
+        * @param int $end Exclusive upper limit (this id is not included)
+        *   If 0, no upper limit.
         */
        public function pagesByRange( $start, $end ) {
                $condition = 'page_id >= ' . intval( $start );
@@ -142,8 +141,8 @@ class WikiExporter {
         * Dumps a series of page and revision records for those pages
         * in the database with revisions falling within the rev_id range given.
         * @param int $start inclusive lower limit (this id is included)
-        * @param $end   Int: Exclusive upper limit (this id is not included)
-        *                   If 0, no upper limit.
+        * @param int $end Exclusive upper limit (this id is not included)
+        *   If 0, no upper limit.
         */
        public function revsByRange( $start, $end ) {
                $condition = 'rev_id >= ' . intval( $start );
index 65d82b8..444d26f 100644 (file)
@@ -48,7 +48,7 @@ class FileDeleteForm {
        /**
         * Constructor
         *
-        * @param $file File object we're deleting
+        * @param File $file File object we're deleting
         */
        public function __construct( $file ) {
                $this->title = $file->getTitle();
@@ -132,12 +132,12 @@ class FileDeleteForm {
        /**
         * Really delete the file
         *
-        * @param $title Title object
-        * @param File $file: file object
-        * @param string $oldimage archive name
-        * @param string $reason reason of the deletion
-        * @param $suppress Boolean: whether to mark all deleted versions as restricted
-        * @param $user User object performing the request
+        * @param Title $title
+        * @param File $file
+        * @param string $oldimage Archive name
+        * @param string $reason Reason of the deletion
+        * @param bool $suppress Whether to mark all deleted versions as restricted
+        * @param User $user User object performing the request
         * @throws MWException
         * @return bool|Status
         */
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 c4fc29a..b1d4f00 100644 (file)
@@ -635,10 +635,10 @@ class Html {
         * Convenience function to produce an "<input>" element.  This supports the
         * new HTML5 input types and attributes.
         *
-        * @param $name    string name attribute
-        * @param $value   mixed  value attribute
-        * @param $type    string type attribute
-        * @param array $attribs  Associative array of miscellaneous extra
+        * @param string $name Name attribute
+        * @param array $value Value attribute
+        * @param string $type Type attribute
+        * @param array $attribs Associative array of miscellaneous extra
         *   attributes, passed to Html::element()
         * @return string Raw HTML
         */
@@ -653,9 +653,9 @@ class Html {
        /**
         * Convenience function to produce an input element with type=hidden
         *
-        * @param $name    string name attribute
-        * @param $value   string value attribute
-        * @param array $attribs  Associative array of miscellaneous extra
+        * @param string $name Name attribute
+        * @param string $value Value attribute
+        * @param array $attribs Associative array of miscellaneous extra
         *   attributes, passed to Html::element()
         * @return string Raw HTML
         */
@@ -669,9 +669,9 @@ class Html {
         * This supports leaving out the cols= and rows= which Xml requires and are
         * required by HTML4/XHTML but not required by HTML5.
         *
-        * @param $name    string name attribute
-        * @param $value   string value attribute
-        * @param array $attribs  Associative array of miscellaneous extra
+        * @param string $name Name attribute
+        * @param string $value Value attribute
+        * @param array $attribs Associative array of miscellaneous extra
         *   attributes, passed to Html::element()
         * @return string Raw HTML
         */
@@ -693,7 +693,7 @@ class Html {
        /**
         * Build a drop-down box for selecting a namespace
         *
-        * @param $params array:
+        * @param array $params Params to set.
         * - selected: [optional] Id of namespace which should be pre-selected
         * - all: [optional] Value of item for "all namespaces". If null or unset, no "<option>" is generated to select all namespaces
         * - label: text for label to add before the field
@@ -794,9 +794,9 @@ class Html {
         * Constructs the opening html-tag with necessary doctypes depending on
         * global variables.
         *
-        * @param array $attribs  Associative array of miscellaneous extra
+        * @param array $attribs Associative array of miscellaneous extra
         *   attributes, passed to Html::element() of html tag.
-        * @return string  Raw HTML
+        * @return string Raw HTML
         */
        public static function htmlHeader( $attribs = array() ) {
                $ret = '';
@@ -840,8 +840,8 @@ class Html {
        /**
         * Determines if the given mime type is xml.
         *
-        * @param $mimetype    string MimeType
-        * @return Boolean
+        * @param string $mimetype MimeType
+        * @return bool
         */
        public static function isXmlMimeType( $mimetype ) {
                # http://www.whatwg.org/html/infrastructure.html#xml-mime-type
index c06fbbc..a72fd59 100644 (file)
@@ -34,7 +34,7 @@ class HtmlFormatter {
        /**
         * Constructor
         *
-        * @param string $html: Text to process
+        * @param string $html Text to process
         */
        public function __construct( $html ) {
                $this->html = $html;
@@ -51,15 +51,15 @@ class HtmlFormatter {
 
        /**
         * Override this in descendant class to modify HTML after it has been converted from DOM tree
-        * @param string $html: HTML to process
-        * @return string: Processed HTML
+        * @param string $html HTML to process
+        * @return string Processed HTML
         */
        protected function onHtmlReady( $html ) {
                return $html;
        }
 
        /**
-        * @return DOMDocument: DOM to manipulate
+        * @return DOMDocument DOM to manipulate
         */
        public function getDoc() {
                if ( !$this->doc ) {
@@ -101,7 +101,7 @@ class HtmlFormatter {
         *   .<class>
         *   #<id>
         *
-        * @param Array|string $selectors: Selector(s) of stuff to remove
+        * @param array|string $selectors Selector(s) of stuff to remove
         */
        public function remove( $selectors ) {
                $this->itemsToRemove = array_merge( $this->itemsToRemove, (array)$selectors );
@@ -114,7 +114,7 @@ class HtmlFormatter {
         * Note this interface may fail in surprising unexpected ways due to usage of regexes,
         * so should not be relied on for HTML markup security measures.
         *
-        * @param Array|string $elements: Name(s) of tag(s) to flatten
+        * @param array|string $elements Name(s) of tag(s) to flatten
         */
        public function flatten( $elements ) {
                $this->elementsToFlatten = array_merge( $this->elementsToFlatten, (array)$elements );
@@ -247,8 +247,8 @@ class HtmlFormatter {
        /**
         * Performs final transformations and returns resulting HTML
         *
-        * @param DOMElement|string|null $element: ID of element to get HTML from or false to get it from the whole tree
-        * @return string: Processed HTML
+        * @param DOMElement|string|null $element ID of element to get HTML from or false to get it from the whole tree
+        * @return string Processed HTML
         */
        public function getText( $element = null ) {
                wfProfileIn( __METHOD__ );
@@ -294,10 +294,10 @@ class HtmlFormatter {
        }
 
        /**
-        * @param $selector: CSS selector to parse
-        * @param $type
-        * @param $rawName
-        * @return bool: Whether the selector was successfully recognised
+        * @param string $selector CSS selector to parse
+        * @param string $type
+        * @param string $rawName
+        * @return bool Whether the selector was successfully recognised
         */
        protected function parseSelector( $selector, &$type, &$rawName ) {
                if ( strpos( $selector, '.' ) === 0 ) {
index 094a304..534ad4d 100644 (file)
@@ -93,9 +93,9 @@ class Linker {
         * link, given the Title object for the page we want to link to.
         *
         * @param $nt Title
-        * @param string $unused unused
-        * @param string $class the contents of the class attribute, default none
-        * @param $title Mixed: optional (unescaped) string to use in the title
+        * @param string $unused Unused
+        * @param string $class The contents of the class attribute, default none
+        * @param string|bool $title Optional (unescaped) string to use in the title
         *   attribute; if false, default to the name of the page we're linking to
         * @return string
         */
@@ -130,9 +130,9 @@ class Linker {
        /**
         * Return the CSS colour of a known link
         *
-        * @param $t Title object
-        * @param $threshold Integer: user defined threshold
-        * @return String: CSS class
+        * @param Title $t
+        * @param int $threshold User defined threshold
+        * @return string CSS class
         */
        public static function getLinkColour( $t, $threshold ) {
                $colour = '';
@@ -162,21 +162,21 @@ class Linker {
         *
         * @since 1.18 Method exists since 1.16 as non-static, made static in 1.18.
         *
-        * @param $target        Title  Can currently only be a Title, but this may
+        * @param Title $target Can currently only be a Title, but this may
         *   change to support Images, literal URLs, etc.
-        * @param $html          string The HTML contents of the <a> element, i.e.,
+        * @param string $html The HTML contents of the <a> element, i.e.,
         *   the link text.  This is raw HTML and will not be escaped.  If null,
         *   defaults to the prefixed text of the Title; or if the Title is just a
         *   fragment, the contents of the fragment.
-        * @param array $customAttribs  A key => value array of extra HTML attributes,
+        * @param array $customAttribs A key => value array of extra HTML attributes,
         *   such as title and class.  (href is ignored.)  Classes will be
         *   merged with the default classes, while other attributes will replace
         *   default attributes.  All passed attribute values will be HTML-escaped.
         *   A false attribute value means to suppress that attribute.
-        * @param $query         array  The query string to append to the URL
+        * @param array $query The query string to append to the URL
         *   you're linking to, in key => value array form.  Query keys and values
         *   will be URL-encoded.
-        * @param string|array $options  String or array of strings:
+        * @param string|array $options String or array of strings:
         *     'known': Page is known to exist, so don't check if it does.
         *     'broken': Page is known not to exist, so don't check if it does.
         *     'noclasses': Don't add any classes automatically (includes "new",
@@ -528,13 +528,13 @@ class Linker {
         *          link-target     Value for the target attribute, only with link-url
         *          no-link         Boolean, suppress description link
         *
-        * @param array $handlerParams associative array of media handler parameters, to be passed
+        * @param array $handlerParams Associative array of media handler parameters, to be passed
         *       to transform(). Typical keys are "width" and "page".
-        * @param string $time timestamp of the file, set as false for current
-        * @param string $query query params for desc url
-        * @param $widthOption: Used by the parser to remember the user preference thumbnailsize
+        * @param string $time Timestamp of the file, set as false for current
+        * @param string $query Query params for desc url
+        * @param int|null $widthOption Used by the parser to remember the user preference thumbnailsize
         * @since 1.20
-        * @return String: HTML for an image, with links, wrappers, etc.
+        * @return string HTML for an image, with links, wrappers, etc.
         */
        public static function makeImageLink( /*Parser*/ $parser, Title $title, $file, $frameParams = array(),
                $handlerParams = array(), $time = false, $query = "", $widthOption = null
@@ -902,13 +902,13 @@ class Linker {
        /**
         * Make a "broken" link to an image
         *
-        * @param $title Title object
+        * @param Title $title
         * @param string $label link label (plain text)
         * @param string $query query string
-        * @param $unused1 Unused parameter kept for b/c
-        * @param $unused2 Unused parameter kept for b/c
-        * @param $time Boolean: a file of a certain timestamp was requested
-        * @return String
+        * @param string $unused1 Unused parameter kept for b/c
+        * @param string $unused2 Unused parameter kept for b/c
+        * @param bool $time a file of a certain timestamp was requested
+        * @return string
         */
        public static function makeBrokenImageLinkObj( $title, $label = '', $query = '', $unused1 = '', $unused2 = '', $time = false ) {
                global $wgEnableUploads, $wgUploadMissingFileUrl, $wgUploadNavigationUrl;
@@ -945,9 +945,9 @@ class Linker {
        /**
         * Get the URL to upload a certain file
         *
-        * @param $destFile Title object of the file to upload
-        * @param string $query urlencoded query string to prepend
-        * @return String: urlencoded URL
+        * @param Title $destFile Title object of the file to upload
+        * @param string $query Urlencoded query string to prepend
+        * @return string Urlencoded URL
         */
        protected static function getUploadUrl( $destFile, $query = '' ) {
                global $wgUploadMissingFileUrl, $wgUploadNavigationUrl;
@@ -969,10 +969,10 @@ class Linker {
        /**
         * Create a direct link to a given uploaded file.
         *
-        * @param $title Title object.
-        * @param string $html pre-sanitized HTML
+        * @param Title $title
+        * @param string $html Pre-sanitized HTML
         * @param string $time MW timestamp of file creation time
-        * @return String: HTML
+        * @return string HTML
         */
        public static function makeMediaLinkObj( $title, $html = '', $time = false ) {
                $img = wfFindFile( $title, array( 'time' => $time ) );
@@ -983,10 +983,10 @@ class Linker {
         * Create a direct link to a given uploaded file.
         * This will make a broken link if $file is false.
         *
-        * @param $title Title object.
-        * @param $file File|bool mixed File object or false
-        * @param string $html pre-sanitized HTML
-        * @return String: HTML
+        * @param Title $title
+        * @param File|bool $file File object or false
+        * @param string $html Pre-sanitized HTML
+        * @return string HTML
         *
         * @todo Handle invalid or missing images better.
         */
@@ -1024,11 +1024,11 @@ class Linker {
        /**
         * Make an external link
         * @param string $url URL to link to
-        * @param string $text text of link
-        * @param $escape Boolean: do we escape the link text?
-        * @param string $linktype type of external link. Gets added to the classes
-        * @param array $attribs of extra attributes to <a>
-        * @param $title Title|null Title object used for title specific link attributes
+        * @param string $text Text of link
+        * @param bool $escape Do we escape the link text?
+        * @param string $linktype Type of external link. Gets added to the classes
+        * @param array $attribs Array of extra attributes to <a>
+        * @param Title|null $title Title object used for title specific link attributes
         * @return string
         */
        public static function makeExternalLink( $url, $text, $escape = true, $linktype = '', $attribs = array(), $title = null ) {
@@ -1063,10 +1063,10 @@ class Linker {
 
        /**
         * Make user link (or user contributions for unregistered users)
-        * @param $userId   Integer: user id in database.
-        * @param string $userName user name in database.
-        * @param string $altUserName text to display instead of the user name (optional)
-        * @return String: HTML fragment
+        * @param int $userId User id in database.
+        * @param string $userName User name in database.
+        * @param string $altUserName Text to display instead of the user name (optional)
+        * @return string HTML fragment
         * @since 1.19 Method exists for a long time. $altUserName was added in 1.19.
         */
        public static function userLink( $userId, $userName, $altUserName = false ) {
@@ -1089,13 +1089,13 @@ class Linker {
        /**
         * Generate standard user tool links (talk, contributions, block link, etc.)
         *
-        * @param $userId Integer: user identifier
-        * @param string $userText user name or IP address
-        * @param $redContribsWhenNoEdits Boolean: should the contributions link be
-        *        red if the user has no edits?
-        * @param $flags Integer: customisation flags (e.g. Linker::TOOL_LINKS_NOBLOCK and Linker::TOOL_LINKS_EMAIL)
-        * @param $edits Integer: user edit count (optional, for performance)
-        * @return String: HTML fragment
+        * @param int $userId User identifier
+        * @param string $userText User name or IP address
+        * @param bool $redContribsWhenNoEdits Should the contributions link be
+        *   red if the user has no edits?
+        * @param int $flags Customisation flags (e.g. Linker::TOOL_LINKS_NOBLOCK and Linker::TOOL_LINKS_EMAIL)
+        * @param int $edits User edit count (optional, for performance)
+        * @return string HTML fragment
         */
        public static function userToolLinks(
                $userId, $userText, $redContribsWhenNoEdits = false, $flags = 0, $edits = null
@@ -1147,19 +1147,19 @@ class Linker {
 
        /**
         * Alias for userToolLinks( $userId, $userText, true );
-        * @param $userId Integer: user identifier
-        * @param string $userText user name or IP address
-        * @param $edits Integer: user edit count (optional, for performance)
-        * @return String
+        * @param int $userId User identifier
+        * @param string $userText User name or IP address
+        * @param int $edits User edit count (optional, for performance)
+        * @return string
         */
        public static function userToolLinksRedContribs( $userId, $userText, $edits = null ) {
                return self::userToolLinks( $userId, $userText, true, 0, $edits );
        }
 
        /**
-        * @param $userId Integer: user id in database.
-        * @param string $userText user name in database.
-        * @return String: HTML fragment with user talk link
+        * @param int $userId User id in database.
+        * @param string $userText User name in database.
+        * @return string HTML fragment with user talk link
         */
        public static function userTalkLink( $userId, $userText ) {
                $userTalkPage = Title::makeTitle( NS_USER_TALK, $userText );
@@ -1168,9 +1168,9 @@ class Linker {
        }
 
        /**
-        * @param $userId Integer: userid
-        * @param string $userText user name in database.
-        * @return String: HTML fragment with block link
+        * @param int $userId Userid
+        * @param string $userText User name in database.
+        * @return string HTML fragment with block link
         */
        public static function blockLink( $userId, $userText ) {
                $blockPage = SpecialPage::getTitleFor( 'Block', $userText );
@@ -1179,9 +1179,9 @@ class Linker {
        }
 
        /**
-        * @param $userId Integer: userid
-        * @param string $userText user name in database.
-        * @return String: HTML fragment with e-mail user link
+        * @param int $userId Userid
+        * @param string $userText User name in database.
+        * @return string HTML fragment with e-mail user link
         */
        public static function emailLink( $userId, $userText ) {
                $emailPage = SpecialPage::getTitleFor( 'Emailuser', $userText );
@@ -1191,9 +1191,9 @@ class Linker {
 
        /**
         * Generate a user link if the current user is allowed to view it
-        * @param $rev Revision object.
-        * @param $isPublic Boolean: show only if all users can see it
-        * @return String: HTML fragment
+        * @param Revision $rev
+        * @param bool $isPublic Show only if all users can see it
+        * @return String HTML fragment
         */
        public static function revUserLink( $rev, $isPublic = false ) {
                if ( $rev->isDeleted( Revision::DELETED_USER ) && $isPublic ) {
@@ -1212,8 +1212,8 @@ class Linker {
 
        /**
         * Generate a user tool link cluster if the current user is allowed to view it
-        * @param $rev Revision object.
-        * @param $isPublic Boolean: show only if all users can see it
+        * @param Revision $rev
+        * @param bool $isPublic Show only if all users can see it
         * @return string HTML
         */
        public static function revUserTools( $rev, $isPublic = false ) {
@@ -1246,9 +1246,9 @@ class Linker {
         * Since you can't set a default parameter for a reference, I've turned it
         * temporarily to a value pass. Should be adjusted further. --brion
         *
-        * @param $comment String
-        * @param $title Mixed: Title object (to generate link to the section in autocomment) or null
-        * @param $local Boolean: whether section links should refer to local page
+        * @param string $comment
+        * @param Title|null $title Title object (to generate link to the section in autocomment) or null
+        * @param bool $local Whether section links should refer to local page
         * @return mixed|String
         */
        public static function formatComment( $comment, $title = null, $local = false ) {
@@ -1281,10 +1281,10 @@ class Linker {
         * add a separator where needed and format the comment itself with CSS
         * Called by Linker::formatComment.
         *
-        * @param string $comment comment text
-        * @param $title Title|null An optional title object used to links to sections
-        * @param $local Boolean: whether section links should refer to local page
-        * @return String: formatted comment
+        * @param string $comment Comment text
+        * @param Title|null $title An optional title object used to links to sections
+        * @param bool $local Whether section links should refer to local page
+        * @return string Formatted comment
         */
        private static function formatAutocomments( $comment, $title = null, $local = false ) {
                // Bah!
@@ -1365,10 +1365,10 @@ class Linker {
         * is ignored
         *
         * @todo FIXME: Doesn't handle sub-links as in image thumb texts like the main parser
-        * @param string $comment text to format links in
-        * @param $title Title|null An optional title object used to links to sections
-        * @param $local Boolean: whether section links should refer to local page
-        * @return String
+        * @param string $comment Text to format links in
+        * @param Title|null $title An optional title object used to links to sections
+        * @param bool $local Whether section links should refer to local page
+        * @return string
         */
        public static function formatLinksInComment( $comment, $title = null, $local = false ) {
                self::$commentContextTitle = $title;
@@ -1547,9 +1547,9 @@ class Linker {
         * Wrap a comment in standard punctuation and formatting if
         * it's non-empty, otherwise return empty string.
         *
-        * @param $comment String
-        * @param $title Mixed: Title object (to generate link to section in autocomment) or null
-        * @param $local Boolean: whether section links should refer to local page
+        * @param string $comment
+        * @param Title|null $title Title object (to generate link to section in autocomment) or null
+        * @param bool $local Whether section links should refer to local page
         *
         * @return string
         */
@@ -1570,10 +1570,10 @@ class Linker {
         * Wrap and format the given revision's comment block, if the current
         * user is allowed to view it.
         *
-        * @param $rev Revision object
-        * @param $local Boolean: whether section links should refer to local page
-        * @param $isPublic Boolean: show only if all users can see it
-        * @return String: HTML fragment
+        * @param Revision $rev
+        * @param bool $local Whether section links should refer to local page
+        * @param bool $isPublic Show only if all users can see it
+        * @return string HTML fragment
         */
        public static function revComment( Revision $rev, $local = false, $isPublic = false ) {
                if ( $rev->getRawComment() == "" ) {
@@ -1654,9 +1654,9 @@ class Linker {
        /**
         * Wraps the TOC in a table and provides the hide/collapse javascript.
         *
-        * @param string $toc html of the Table Of Contents
-        * @param $lang String|Language|false: Language for the toc title, defaults to user language
-        * @return String: full html of the TOC
+        * @param string $toc Html of the Table Of Contents
+        * @param string|Language|false $lang Language for the toc title, defaults to user language
+        * @return string Full html of the TOC
         */
        public static function tocList( $toc, $lang = false ) {
                $lang = wfGetLangObj( $lang );
@@ -1673,7 +1673,7 @@ class Linker {
         * Currently unused.
         *
         * @param array $tree Return value of ParserOutput::getSections()
-        * @return String: HTML fragment
+        * @return string HTML fragment
         */
        public static function generateTOC( $tree ) {
                $toc = '';
@@ -1700,17 +1700,17 @@ class Linker {
        /**
         * Create a headline for content
         *
-        * @param $level Integer: the level of the headline (1-6)
-        * @param string $attribs any attributes for the headline, starting with
-        *                 a space and ending with '>'
-        *                 This *must* be at least '>' for no attribs
+        * @param int $level The level of the headline (1-6)
+        * @param string $attribs Any attributes for the headline, starting with
+        *   a space and ending with '>'
+        *   This *must* be at least '>' for no attribs
         * @param string $anchor the anchor to give the headline (the bit after the #)
         * @param string $html html for the text of the header
         * @param string $link HTML to add for the section edit link
-        * @param $legacyAnchor Mixed: a second, optional anchor to give for
+        * @param bool|string $legacyAnchor a second, optional anchor to give for
         *   backward compatibility (false to omit)
         *
-        * @return String: HTML headline
+        * @return string HTML headline
         */
        public static function makeHeadline( $level, $attribs, $anchor, $html, $link, $legacyAnchor = false ) {
                $ret = "<h$level$attribs"
@@ -1853,10 +1853,10 @@ class Linker {
        /**
         * Build a raw rollback link, useful for collections of "tool" links
         *
-        * @param $rev Revision object
-        * @param $context IContextSource context to use or null for the main context.
-        * @param $editCount integer Number of edits that would be reverted
-        * @return String: HTML fragment
+        * @param Revision $rev
+        * @param IContextSource|null $context Context to use or null for the main context.
+        * @param int $editCount Number of edits that would be reverted
+        * @return string HTML fragment
         */
        public static function buildRollbackLink( $rev, IContextSource $context = null, $editCount = false ) {
                global $wgShowRollbackEditCount, $wgMiserMode;
@@ -1931,7 +1931,7 @@ class Linker {
         * @param bool $preview Whether this is for a preview
         * @param bool $section Whether this is for a section edit
         * @param Title|Message|string|null $more An escaped link for "More..." of the templates
-        * @return String: HTML output
+        * @return string HTML output
         */
        public static function formatTemplates( $templates, $preview = false, $section = false, $more = null ) {
                global $wgLang;
@@ -2022,9 +2022,9 @@ class Linker {
        /**
         * Returns HTML for the "hidden categories on this page" list.
         *
-        * @param array $hiddencats of hidden categories from Article::getHiddenCategories
-        * or similar
-        * @return String: HTML output
+        * @param array $hiddencats Array of hidden categories from Article::getHiddenCategories
+        *   or similar
+        * @return String HTML output
         */
        public static function formatHiddenCategories( $hiddencats ) {
                wfProfileIn( __METHOD__ );
@@ -2063,10 +2063,10 @@ class Linker {
         * isn't always, because sometimes the accesskey needs to go on a different
         * element than the id, for reverse-compatibility, etc.)
         *
-        * @param string $name id of the element, minus prefixes.
-        * @param $options Mixed: null or the string 'withaccess' to add an access-
+        * @param string $name Id of the element, minus prefixes.
+        * @param string|null $options null or the string 'withaccess' to add an access-
         *   key hint
-        * @return String: contents of the title attribute (which you must HTML-
+        * @return string Contents of the title attribute (which you must HTML-
         *   escape), or false for no title attribute
         */
        public static function titleAttrib( $name, $options = null ) {
@@ -2110,8 +2110,8 @@ class Linker {
         * the id but isn't always, because sometimes the accesskey needs to go on
         * a different element than the id, for reverse-compatibility, etc.)
         *
-        * @param string $name id of the element, minus prefixes.
-        * @return String: contents of the accesskey attribute (which you must HTML-
+        * @param string $name Id of the element, minus prefixes.
+        * @return string Contents of the accesskey attribute (which you must HTML-
         *   escape), or false for no accesskey attribute
         */
        public static function accesskey( $name ) {
@@ -2186,11 +2186,11 @@ class Linker {
        /**
         * Creates a (show/hide) link for deleting revisions/log entries
         *
-        * @param array $query query parameters to be passed to link()
-        * @param $restricted Boolean: set to true to use a "<strong>" instead of a "<span>"
-        * @param $delete Boolean: set to true to use (show/hide) rather than (show)
+        * @param array $query Query parameters to be passed to link()
+        * @param bool $restricted Set to true to use a "<strong>" instead of a "<span>"
+        * @param bool $delete Set to true to use (show/hide) rather than (show)
         *
-        * @return String: HTML "<a>" link to Special:Revisiondelete, wrapped in a
+        * @return string HTML "<a>" link to Special:Revisiondelete, wrapped in a
         * span to allow for customization of appearance with CSS
         */
        public static function revDeleteLink( $query = array(), $restricted = false, $delete = true ) {
@@ -2205,7 +2205,7 @@ class Linker {
        /**
         * Creates a dead (show/hide) link for deleting revisions/log entries
         *
-        * @param $delete Boolean: set to true to use (show/hide) rather than (show)
+        * @param bool $delete Set to true to use (show/hide) rather than (show)
         *
         * @return string HTML text wrapped in a span to allow for customization
         * of appearance with CSS
@@ -2226,13 +2226,12 @@ class Linker {
         * call this lots of times, pre-fill the link cache with a LinkBatch, otherwise each
         * call to this will result in a DB query.
         *
-        * @param $nt     Title: the title object to make the link from, e.g. from
-        *                      Title::newFromText.
-        * @param $text  String: link text
+        * @param Title $nt The title object to make the link from, e.g. from Title::newFromText.
+        * @param string $text Link text
         * @param string $query optional query part
         * @param string $trail optional trail. Alphabetic characters at the start of this string will
-        *                      be included in the link text. Other characters will be appended after
-        *                      the end of the link.
+        *   be included in the link text. Other characters will be appended after
+        *   the end of the link.
         * @param string $prefix optional prefix. As trail, only before instead of after.
         * @return string
         */
@@ -2259,14 +2258,14 @@ class Linker {
         * it doesn't have to do a database query. It's also valid for interwiki titles and special
         * pages.
         *
-        * @param $title  Title object of target page
-        * @param $text   String: text to replace the title
-        * @param $query  String: link target
-        * @param $trail  String: text after link
-        * @param string $prefix text before link text
-        * @param string $aprops extra attributes to the a-element
-        * @param $style  String: style to apply - if empty, use getInternalLinkAttributesObj instead
-        * @return string the a-element
+        * @param Title $title Title object of target page
+        * @param string $text Text to replace the title
+        * @param string $query Link target
+        * @param string $trail Text after link
+        * @param string $prefix Text before link text
+        * @param string $aprops Extra attributes to the a-element
+        * @param string $style Style to apply - if empty, use getInternalLinkAttributesObj instead
+        * @return string The a-element
         */
        static function makeKnownLinkObj(
                $title, $text = '', $query = '', $trail = '', $prefix = '', $aprops = '', $style = ''
index e3b8577..b5c0c7d 100644 (file)
@@ -536,9 +536,9 @@ class MimeMagic {
         * based formats like OPC/ODF files).
         *
         * @param string $file the file to check
-        * @param $ext Mixed: the file extension, or true (default) to extract it from the filename.
-        *             Set it to false to ignore the extension. DEPRECATED! Set to false, use
-        *             improveTypeFromExtension($mime, $ext) later to improve mime type.
+        * @param string|bool $ext The file extension, or true (default) to extract it from the filename.
+        *   Set it to false to ignore the extension. DEPRECATED! Set to false, use
+        *   improveTypeFromExtension($mime, $ext) later to improve mime type.
         *
         * @return string the mime type of $file
         */
@@ -744,11 +744,11 @@ class MimeMagic {
         * header data.  Currently works for OpenDocument and OpenXML types...
         * If can't tell, returns 'application/zip'.
         *
-        * @param string $header some reasonably-sized chunk of file header
-        * @param $tail   String: the tail of the file
-        * @param $ext Mixed: the file extension, or true to extract it from the filename.
-        *             Set it to false (default) to ignore the extension. DEPRECATED! Set to false,
-        *             use improveTypeFromExtension($mime, $ext) later to improve mime type.
+        * @param string $header Some reasonably-sized chunk of file header
+        * @param string|null $tail The tail of the file
+        * @param string|bool $ext The file extension, or true to extract it from the filename.
+        *   Set it to false (default) to ignore the extension. DEPRECATED! Set to false,
+        *   use improveTypeFromExtension($mime, $ext) later to improve mime type.
         *
         * @return string
         */
@@ -850,10 +850,10 @@ class MimeMagic {
         * mime type if the file is an image. If no mime type can be determined,
         * this function returns 'unknown/unknown'.
         *
-        * @param string $file the file to check
-        * @param $ext Mixed: the file extension, or true (default) to extract it from the filename.
-        *             Set it to false to ignore the extension. DEPRECATED! Set to false, use
-        *             improveTypeFromExtension($mime, $ext) later to improve mime type.
+        * @param string $file The file to check
+        * @param string|bool $ext The file extension, or true (default) to extract it from the filename.
+        *   Set it to false to ignore the extension. DEPRECATED! Set to false, use
+        *   improveTypeFromExtension($mime, $ext) later to improve mime type.
         *
         * @return string the mime type of $file
         */
index f469732..9b641c3 100644 (file)
@@ -252,17 +252,17 @@ class OutputPage extends ContextSource {
        private $mProperties = array();
 
        /**
-        * @var string|null: ResourceLoader target for load.php links. If null, will be omitted
+        * @var string|null ResourceLoader target for load.php links. If null, will be omitted
         */
        private $mTarget = null;
 
        /**
-        * @var bool: Whether parser output should contain table of contents
+        * @var bool Whether parser output should contain table of contents
         */
        private $mEnableTOC = true;
 
        /**
-        * @var bool: Whether parser output should contain section edit links
+        * @var bool Whether parser output should contain section edit links
         */
        private $mEnableSectionEditLinks = true;
 
@@ -481,7 +481,7 @@ class OutputPage extends ContextSource {
         * through this function will be loaded by the resource loader when the
         * page loads.
         *
-        * @param $modules Mixed: module name (string) or array of module names
+        * @param string|array $modules Module name (string) or array of module names
         */
        public function addModules( $modules ) {
                $this->mModules = array_merge( $this->mModules, (array)$modules );
@@ -504,7 +504,7 @@ class OutputPage extends ContextSource {
         * scripts added through this function will be loaded by the resource loader when
         * the page loads.
         *
-        * @param $modules Mixed: module name (string) or array of module names
+        * @param string|array $modules Module name (string) or array of module names
         */
        public function addModuleScripts( $modules ) {
                $this->mModuleScripts = array_merge( $this->mModuleScripts, (array)$modules );
@@ -529,7 +529,7 @@ class OutputPage extends ContextSource {
         * tags, rather than as a combined Javascript and CSS package. Thus, they will
         * load when JavaScript is disabled (unless CSS also happens to be disabled).
         *
-        * @param $modules Mixed: module name (string) or array of module names
+        * @param string|array $modules Module name (string) or array of module names
         */
        public function addModuleStyles( $modules ) {
                $this->mModuleStyles = array_merge( $this->mModuleStyles, (array)$modules );
@@ -552,14 +552,14 @@ class OutputPage extends ContextSource {
         * Module messages added through this function will be loaded by the resource
         * loader when the page loads.
         *
-        * @param $modules Mixed: module name (string) or array of module names
+        * @param string|array $modules Module name (string) or array of module names
         */
        public function addModuleMessages( $modules ) {
                $this->mModuleMessages = array_merge( $this->mModuleMessages, (array)$modules );
        }
 
        /**
-        * @return null|string: ResourceLoader target
+        * @return null|string ResourceLoader target
         */
        public function getTarget() {
                return $this->mTarget;
@@ -630,7 +630,7 @@ class OutputPage extends ContextSource {
         * without any skin, sidebar, etc.
         * Used e.g. when calling with "action=render".
         *
-        * @param $only Boolean: whether to output only the body of the article
+        * @param bool $only Whether to output only the body of the article
         */
        public function setArticleBodyOnly( $only ) {
                $this->mArticleBodyOnly = $only;
@@ -660,8 +660,8 @@ class OutputPage extends ContextSource {
         * Get an additional output property
         * @since 1.21
         *
-        * @param $name
-        * @return mixed: Property value or null if not found
+        * @param string $name
+        * @return mixed Property value or null if not found
         */
        public function getProperty( $name ) {
                if ( isset( $this->mProperties[$name] ) ) {
@@ -678,9 +678,9 @@ class OutputPage extends ContextSource {
         *
         * Side effect: sets mLastModified for Last-Modified header
         *
-        * @param $timestamp string
+        * @param string $timestamp
         *
-        * @return Boolean: true if cache-ok headers was sent.
+        * @return bool True if cache-ok headers was sent.
         */
        public function checkLastModified( $timestamp ) {
                global $wgCachePages, $wgCacheEpoch, $wgUseSquid, $wgSquidMaxage;
@@ -1036,7 +1036,7 @@ class OutputPage extends ContextSource {
         * for the new version
         * @see addFeedLink()
         *
-        * @param $show Boolean: true: add default feeds, false: remove all feeds
+        * @param bool $show true: add default feeds, false: remove all feeds
         */
        public function setSyndicated( $show = true ) {
                if ( $show ) {
@@ -1372,7 +1372,7 @@ class OutputPage extends ContextSource {
        /**
         * Get the body HTML
         *
-        * @return String: HTML
+        * @return string HTML
         */
        public function getHTML() {
                return $this->mBodytext;
@@ -1397,8 +1397,8 @@ class OutputPage extends ContextSource {
         * Set the revision ID which will be seen by the wiki text parser
         * for things such as embedded {{REVISIONID}} variable use.
         *
-        * @param $revid Mixed: an positive integer, or null
-        * @return Mixed: previous value
+        * @param int|null $revid An positive integer, or null
+        * @return mixed Previous value
         */
        public function setRevisionId( $revid ) {
                $val = is_null( $revid ) ? null : intval( $revid );
@@ -1418,8 +1418,8 @@ class OutputPage extends ContextSource {
         * Set the timestamp of the revision which will be displayed. This is used
         * to avoid a extra DB call in Skin::lastModified().
         *
-        * @param $timestamp Mixed: string, or null
-        * @return Mixed: previous value
+        * @param string|null $timestamp
+        * @return mixed Previous value
         */
        public function setRevisionTimestamp( $timestamp ) {
                return wfSetVar( $this->mRevisionTimestamp, $timestamp );
@@ -1438,8 +1438,8 @@ class OutputPage extends ContextSource {
        /**
         * Set the displayed file version
         *
-        * @param $file File|bool
-        * @return Mixed: previous value
+        * @param File|bool $file
+        * @return mixed Previous value
         */
        public function setFileVersion( $file ) {
                $val = null;
@@ -1482,9 +1482,9 @@ class OutputPage extends ContextSource {
         * Convert wikitext to HTML and add it to the buffer
         * Default assumes that the current page title will be used.
         *
-        * @param $text String
-        * @param $linestart Boolean: is this the start of a line?
-        * @param $interface Boolean: is this text in the user interface language?
+        * @param string $text
+        * @param bool $linestart Is this the start of a line?
+        * @param bool $interface Is this text in the user interface language?
         */
        public function addWikiText( $text, $linestart = true, $interface = true ) {
                $title = $this->getTitle(); // Work around E_STRICT
@@ -1497,9 +1497,9 @@ class OutputPage extends ContextSource {
        /**
         * Add wikitext with a custom Title object
         *
-        * @param string $text wikitext
-        * @param $title Title object
-        * @param $linestart Boolean: is this the start of a line?
+        * @param string $text Wikitext
+        * @param Title $title
+        * @param bool $linestart Is this the start of a line?
         */
        public function addWikiTextWithTitle( $text, &$title, $linestart = true ) {
                $this->addWikiTextTitle( $text, $title, $linestart );
@@ -1508,9 +1508,9 @@ class OutputPage extends ContextSource {
        /**
         * Add wikitext with a custom Title object and tidy enabled.
         *
-        * @param string $text wikitext
-        * @param $title Title object
-        * @param $linestart Boolean: is this the start of a line?
+        * @param string $text Wikitext
+        * @param Title $title
+        * @param bool $linestart Is this the start of a line?
         */
        function addWikiTextTitleTidy( $text, &$title, $linestart = true ) {
                $this->addWikiTextTitle( $text, $title, $linestart, true );
@@ -1519,8 +1519,8 @@ class OutputPage extends ContextSource {
        /**
         * Add wikitext with tidy enabled
         *
-        * @param string $text wikitext
-        * @param $linestart Boolean: is this the start of a line?
+        * @param string $text Wikitext
+        * @param bool $linestart Is this the start of a line?
         */
        public function addWikiTextTidy( $text, $linestart = true ) {
                $title = $this->getTitle();
@@ -1530,12 +1530,12 @@ class OutputPage extends ContextSource {
        /**
         * Add wikitext with a custom Title object
         *
-        * @param string $text wikitext
-        * @param $title Title object
-        * @param $linestart Boolean: is this the start of a line?
-        * @param $tidy Boolean: whether to use tidy
-        * @param $interface Boolean: whether it is an interface message
-        *                                                              (for example disables conversion)
+        * @param string $text Wikitext
+        * @param Title $title
+        * @param bool $linestart Is this the start of a line?
+        * @param bool $tidy Whether to use tidy
+        * @param bool $interface Whether it is an interface message
+        *   (for example disables conversion)
         */
        public function addWikiTextTitle( $text, Title $title, $linestart, $tidy = false, $interface = false ) {
                global $wgParser;
@@ -1640,16 +1640,14 @@ class OutputPage extends ContextSource {
        /**
         * Parse wikitext and return the HTML.
         *
-        * @param $text String
-        * @param $linestart Boolean: is this the start of a line?
-        * @param $interface Boolean: use interface language ($wgLang instead of
-        *                   $wgContLang) while parsing language sensitive magic
-        *                   words like GRAMMAR and PLURAL. This also disables
-        *                   LanguageConverter.
-        * @param $language  Language object: target language object, will override
-        *                   $interface
+        * @param String $text
+        * @param bool $linestart Is this the start of a line?
+        * @param bool $interface Use interface language ($wgLang instead of
+        *   $wgContLang) while parsing language sensitive magic words like GRAMMAR and PLURAL.
+        *   This also disables LanguageConverter.
+        * @param Language $language Target language object, will override $interface
         * @throws MWException
-        * @return String: HTML
+        * @return string HTML
         */
        public function parse( $text, $linestart = true, $interface = false, $language = null ) {
                global $wgParser;
@@ -1684,12 +1682,12 @@ class OutputPage extends ContextSource {
        /**
         * Parse wikitext, strip paragraphs, and return the HTML.
         *
-        * @param $text String
-        * @param $linestart Boolean: is this the start of a line?
-        * @param $interface Boolean: use interface language ($wgLang instead of
-        *                   $wgContLang) while parsing language sensitive magic
-        *                   words like GRAMMAR and PLURAL
-        * @return String: HTML
+        * @param string $text
+        * @param bool $linestart Is this the start of a line?
+        * @param bool $interface Use interface language ($wgLang instead of
+        *   $wgContLang) while parsing language sensitive magic
+        *   words like GRAMMAR and PLURAL
+        * @return string HTML
         */
        public function parseInline( $text, $linestart = true, $interface = false ) {
                $parsed = $this->parse( $text, $linestart, $interface );
@@ -1705,7 +1703,7 @@ class OutputPage extends ContextSource {
        /**
         * Set the value of the "s-maxage" part of the "Cache-control" HTTP header
         *
-        * @param $maxage Integer: maximum cache time on the Squid, in seconds.
+        * @param int $maxage Maximum cache time on the Squid, in seconds.
         */
        public function setSquidMaxage( $maxage ) {
                $this->mSquidMaxage = $maxage;
@@ -1969,9 +1967,8 @@ class OutputPage extends ContextSource {
        /**
         * Get the message associated with the HTTP response code $code
         *
-        * @param $code Integer: status code
-        * @return String or null: message or null if $code is not in the list of
-        *         messages
+        * @param int $code Status code
+        * @return string|null Message or null if $code is not in the list of messages
         *
         * @deprecated since 1.18 Use HttpStatus::getMessage() instead.
         */
@@ -2147,9 +2144,9 @@ class OutputPage extends ContextSource {
         * showErrorPage( 'titlemsg', $messageObject );
         * showErrorPage( $titleMessageObject, $messageObject );
         *
-        * @param $title Mixed: message key (string) for page title, or a Message object
-        * @param $msg Mixed: message key (string) for page text, or a Message object
-        * @param array $params message parameters; ignored if $msg is a Message object
+        * @param string|Message $title Message key (string) for page title, or a Message object
+        * @param string|Message $msg Message key (string) for page text, or a Message object
+        * @param array $params Message parameters; ignored if $msg is a Message object
         */
        public function showErrorPage( $title, $msg, $params = array() ) {
                if ( !$title instanceof Message ) {
@@ -2246,7 +2243,7 @@ class OutputPage extends ContextSource {
         * Display an error page indicating that a given version of MediaWiki is
         * required to use it
         *
-        * @param $version Mixed: the version of MediaWiki needed to use the page
+        * @param mixed $version The version of MediaWiki needed to use the page
         */
        public function versionRequired( $version ) {
                $this->prepareErrorPage( $this->msg( 'versionrequired', $version ) );
@@ -2277,9 +2274,9 @@ class OutputPage extends ContextSource {
        /**
         * Format a list of error messages
         *
-        * @param array $errors of arrays returned by Title::getUserPermissionsErrors
-        * @param string $action action that was denied or null if unknown
-        * @return String: the wikitext error-messages, formatted into a list.
+        * @param array $errors Array of arrays returned by Title::getUserPermissionsErrors
+        * @param string $action Action that was denied or null if unknown
+        * @return string The wikitext error-messages, formatted into a list.
         */
        public function formatPermissionsErrorMessage( $errors, $action = null ) {
                if ( $action == null ) {
@@ -2326,10 +2323,10 @@ class OutputPage extends ContextSource {
         *
         * @todo Needs to be split into multiple functions.
         *
-        * @param $source    String: source code to show (or null).
-        * @param $protected Boolean: is this a permissions error?
-        * @param $reasons   Array: list of reasons for this error, as returned by Title::getUserPermissionsErrors().
-        * @param $action    String: action that was denied or null if unknown
+        * @param string $source Source code to show (or null).
+        * @param bool $protected Is this a permissions error?
+        * @param array $reasons List of reasons for this error, as returned by Title::getUserPermissionsErrors().
+        * @param string $action Action that was denied or null if unknown
         * @throws ReadOnlyError
         */
        public function readOnlyPage( $source = null, $protected = false, $reasons = array(), $action = null ) {
@@ -2403,7 +2400,7 @@ $templates
         * then the warning is a bit more obvious. If the lag is
         * lower than $wgSlaveLagWarning, then no warning is shown.
         *
-        * @param $lag Integer: slave lag
+        * @param int $lag Slave lag
         */
        public function showLagWarning( $lag ) {
                global $wgSlaveLagWarning, $wgSlaveLagCritical;
@@ -2490,9 +2487,9 @@ $templates
        }
 
        /**
-        * @param $sk Skin The given Skin
-        * @param $includeStyle Boolean: unused
-        * @return String: The doctype, opening "<html>", and head element.
+        * @param Skin $sk The given Skin
+        * @param bool $includeStyle Unused
+        * @return string The doctype, opening "<html>", and head element.
         */
        public function headElement( Skin $sk, $includeStyle = true ) {
                global $wgContLang, $wgMimeType;
@@ -2816,7 +2813,7 @@ $templates
         * JS stuff to put in the "<head>". This is the startup module, config
         * vars and modules marked with position 'top'
         *
-        * @return String: HTML fragment
+        * @return string HTML fragment
         */
        function getHeadScripts() {
                global $wgResourceLoaderExperimentalAsyncLoading;
@@ -3348,10 +3345,10 @@ $templates
        /**
         * Generate a "<link rel/>" for a feed.
         *
-        * @param string $type feed type
+        * @param string $type Feed type
         * @param string $url URL to the feed
-        * @param string $text value of the "title" attribute
-        * @return String: HTML fragment
+        * @param string $text Value of the "title" attribute
+        * @return string HTML fragment
         */
        private function feedLink( $type, $url, $text ) {
                return Html::element( 'link', array(
@@ -3389,7 +3386,7 @@ $templates
 
        /**
         * Adds inline CSS styles
-        * @param $style_css Mixed: inline CSS
+        * @param mixed $style_css Inline CSS
         * @param string $flip Set to 'flip' to flip the CSS if needed
         */
        public function addInlineStyle( $style_css, $flip = 'noflip' ) {
@@ -3510,9 +3507,8 @@ $templates
         * Generate \<link\> tags for stylesheets
         *
         * @param string $style URL to the file
-        * @param array $options option, can contain 'condition', 'dir', 'media'
-        *                 keys
-        * @return String: HTML fragment
+        * @param array $options Option, can contain 'condition', 'dir', 'media' keys
+        * @return string HTML fragment
         */
        protected function styleLink( $style, $options ) {
                if ( isset( $options['dir'] ) ) {
@@ -3551,8 +3547,8 @@ $templates
        /**
         * Transform "media" attribute based on request parameters
         *
-        * @param string $media current value of the "media" attribute
-        * @return String: modified value of the "media" attribute, or null to skip
+        * @param string $media Current value of the "media" attribute
+        * @return string Modified value of the "media" attribute, or null to skip
         * this stylesheet
         */
        public static function transformCssMedia( $media ) {
@@ -3667,8 +3663,8 @@ $templates
         * Include jQuery core. Use this to avoid loading it multiple times
         * before we get a usable script loader.
         *
-        * @param array $modules list of jQuery modules which should be loaded
-        * @return Array: the list of modules which were not loaded.
+        * @param array $modules List of jQuery modules which should be loaded
+        * @return array The list of modules which were not loaded.
         * @since 1.16
         * @deprecated since 1.17
         */
index 5073913..f359a1c 100644 (file)
@@ -944,8 +944,11 @@ class SkinTemplate extends Skin {
                        $content_navigation['namespaces'][$talkId]['context'] = 'talk';
 
                        if ( $userCanRead ) {
+                               $isForeignFile = $title->inNamespace( NS_FILE ) && $this->canUseWikiPage() &&
+                                       $this->getWikiPage() instanceof WikiFilePage && !$this->getWikiPage()->isLocal();
+
                                // Adds view view link
-                               if ( $title->exists() ) {
+                               if ( $title->exists() || $isForeignFile ) {
                                        $content_navigation['views']['view'] = $this->tabAction(
                                                $isTalk ? $talkPage : $subjectPage,
                                                array( "$skname-view-view", 'view' ),
@@ -955,6 +958,19 @@ class SkinTemplate extends Skin {
                                        $content_navigation['views']['view']['redundant'] = true;
                                }
 
+                               // If it is a non-local file, show a link to the file in its own repository
+                               if ( $isForeignFile ) {
+                                       $file = $this->getWikiPage()->getFile();
+                                       $content_navigation['views']['view-foreign'] = array(
+                                               'class' => '',
+                                               'text' => wfMessageFallback( "$skname-view-foreign", 'view-foreign' )->
+                                                       setContext( $this->getContext() )->
+                                                       params( $file->getRepo()->getDisplayName() )->text(),
+                                               'href' => $file->getDescriptionUrl(),
+                                               'primary' => false,
+                                       );
+                               }
+
                                wfProfileIn( __METHOD__ . '-edit' );
 
                                // Checks if user can edit the current page if it exists or create it otherwise
@@ -969,13 +985,16 @@ class SkinTemplate extends Skin {
                                                && ( ( $isTalk && $this->isRevisionCurrent() ) || $out->showNewSectionLink() );
                                        $section = $request->getVal( 'section' );
 
-                                       $msgKey = $title->exists() || ( $title->getNamespace() == NS_MEDIAWIKI && $title->getDefaultMessageText() !== false ) ?
-                                               'edit' : 'create';
+                                       if ( $title->exists() || ( $title->getNamespace() == NS_MEDIAWIKI && $title->getDefaultMessageText() !== false ) ) {
+                                               $msgKey = $isForeignFile ? 'edit-local' : 'edit';
+                                       } else {
+                                               $msgKey = $isForeignFile ? 'create-local' : 'create';
+                                       }
                                        $content_navigation['views']['edit'] = array(
                                                'class' => ( $isEditing && ( $section !== 'new' || !$showNewSection ) ? 'selected' : '' ) . $isTalkClass,
                                                'text' => wfMessageFallback( "$skname-view-$msgKey", $msgKey )->setContext( $this->getContext() )->text(),
                                                'href' => $title->getLocalURL( $this->editUrlOptions() ),
-                                               'primary' => true, // don't collapse this in vector
+                                               'primary' => !$isForeignFile, // don't collapse this in vector
                                        );
 
                                        // section link
index 795fd45..3573f4a 100644 (file)
@@ -41,7 +41,7 @@ class Status {
        /** @var bool */
        public $ok = true;
 
-       /** @var mixed  */
+       /** @var mixed */
        public $value;
 
        /** Counters for batch operations */
@@ -52,7 +52,7 @@ class Status {
        public $failCount = 0;
 
        /** Array to indicate which items of the batch operations were successful */
-       /** @var array  */
+       /** @var array */
        public $success = array();
 
        /** @var array */
@@ -90,8 +90,8 @@ class Status {
        /**
         * Change operation result
         *
-        * @param $ok Boolean: whether the operation completed
-        * @param $value Mixed
+        * @param bool $ok Whether the operation completed
+        * @param mixed $value
         */
        public function setResult( $ok, $value = null ) {
                $this->ok = $ok;
@@ -326,8 +326,8 @@ class Status {
        /**
         * Merge another status object into this one
         *
-        * @param $other Status Other Status object
-        * @param $overwriteValue Boolean: whether to override the "value" member
+        * @param Status $other Other Status object
+        * @param bool $overwriteValue Whether to override the "value" member
         */
        public function merge( $other, $overwriteValue = false ) {
                $this->errors = array_merge( $this->errors, $other->errors );
@@ -427,8 +427,8 @@ class Status {
         * Note, due to the lack of tools for comparing Message objects, this
         * function will not work when using a Message object as the search parameter.
         *
-        * @param $source Message|String: Message key or object to search for
-        * @param $dest Message|String: Replacement message key or object
+        * @param Message|string $source Message key or object to search for
+        * @param Message|string $dest Replacement message key or object
         * @return bool Return true if the replacement was done, false otherwise.
         */
        public function replaceMessage( $source, $dest ) {
index 995deeb..31e5868 100644 (file)
@@ -4341,9 +4341,10 @@ class Title {
         *
         * @param int|Revision $old Old revision or rev ID (first before range)
         * @param int|Revision $new New revision or rev ID (first after range)
+        * @param int|null $max Limit of Revisions to count, will be incremented to detect truncations
         * @return Int Number of revisions between these revisions.
         */
-       public function countRevisionsBetween( $old, $new ) {
+       public function countRevisionsBetween( $old, $new, $max = null ) {
                if ( !( $old instanceof Revision ) ) {
                        $old = Revision::newFromTitle( $this, (int)$old );
                }
@@ -4354,14 +4355,21 @@ class Title {
                        return 0; // nothing to compare
                }
                $dbr = wfGetDB( DB_SLAVE );
-               return (int)$dbr->selectField( 'revision', 'count(*)',
-                       array(
-                               'rev_page' => $this->getArticleID(),
-                               'rev_timestamp > ' . $dbr->addQuotes( $dbr->timestamp( $old->getTimestamp() ) ),
-                               'rev_timestamp < ' . $dbr->addQuotes( $dbr->timestamp( $new->getTimestamp() ) )
-                       ),
-                       __METHOD__
+               $conds = array(
+                       'rev_page' => $this->getArticleID(),
+                       'rev_timestamp > ' . $dbr->addQuotes( $dbr->timestamp( $old->getTimestamp() ) ),
+                       'rev_timestamp < ' . $dbr->addQuotes( $dbr->timestamp( $new->getTimestamp() ) )
                );
+               if ( $max !== null ) {
+                       $res = $dbr->select( 'revision', '1',
+                               $conds,
+                               __METHOD__,
+                               array( 'LIMIT' => $max + 1 ) // extra to detect truncation
+                       );
+                       return $res->numRows();
+               } else {
+                       return (int)$dbr->selectField( 'revision', 'count(*)', $conds, __METHOD__ );
+               }
        }
 
        /**
@@ -4916,7 +4924,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 6cf718c..fbafba8 100644 (file)
@@ -624,7 +624,7 @@ class MediaWiki {
         * the socket once it's done.
         */
        protected function triggerJobs() {
-               global $wgJobRunRate, $wgServer;
+               global $wgJobRunRate, $wgServer, $wgRunJobsAsync;
 
                if ( $wgJobRunRate <= 0 || wfReadOnly() ) {
                        return;
@@ -644,6 +644,17 @@ class MediaWiki {
                        $n = intval( $wgJobRunRate );
                }
 
+               if ( !$wgRunJobsAsync ) {
+                       // If running jobs asynchronously has been disabled, run the job here
+                       // while the user waits
+                       SpecialRunJobs::executeJobs( $n );
+                       return;
+               }
+
+               if ( !JobQueueGroup::singleton()->queuesHaveJobs( JobQueueGroup::TYPE_DEFAULT ) ) {
+                       return; // do not send request if there are probably no jobs
+               }
+
                $query = array( 'title' => 'Special:RunJobs',
                        'tasks' => 'jobs', 'maxjobs' => $n, 'sigexpiry' => time() + 5 );
                $query['signature'] = SpecialRunJobs::getQuerySignature( $query );
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 3067b1a..651b114 100644 (file)
@@ -3198,8 +3198,8 @@ $zh2Hant = array(
 '不干她' => '不干她',
 '不干它' => '不干它',
 '不干我' => '不干我',
-'不干扰' => '不干擾',
 '不干擾' => '不干擾',
+'不干扰' => '不干擾',
 '不干涉' => '不干涉',
 '不干牠' => '不干牠',
 '不干犯' => '不干犯',
@@ -3220,12 +3220,13 @@ $zh2Hant = array(
 '不负所托' => '不負所托',
 '不通吊庆' => '不通弔慶',
 '不丑' => '不醜',
-'不采聲' => '不采聲',
 '不采声' => '不采聲',
+'不采聲' => '不采聲',
 '不锈钢' => '不鏽鋼',
 '不食干腊' => '不食乾腊',
 '不斗' => '不鬥',
 '丑三' => '丑三',
+'丑婆子' => '丑婆子',
 '丑年' => '丑年',
 '丑日' => '丑日',
 '丑旦' => '丑旦',
@@ -3263,21 +3264,23 @@ $zh2Hant = array(
 '中签' => '中籤',
 '中美发表' => '中美發表',
 '中药' => '中藥',
+'中西合并' => '中西合併',
 '中风后' => '中風後',
-'丰仪' => '丰儀',
 '丰儀' => '丰儀',
+'丰仪' => '丰儀',
 '丰南' => '丰南',
 '丰台' => '丰台',
 '丰姿' => '丰姿',
 '丰容' => '丰容',
+'丰度' => '丰度',
 '丰情' => '丰情',
 '丰标' => '丰標',
-'丰标不凡' => '丰標不凡',
 '丰標不凡' => '丰標不凡',
+'丰标不凡' => '丰標不凡',
 '丰神' => '丰神',
 '丰茸' => '丰茸',
 '丰采' => '丰采',
-'丰é\9fµ' => '丰é\9fµ',
+'丰é\9fµ' => '丰é\9f»',
 '丰韻' => '丰韻',
 '丸药' => '丸藥',
 '丹药' => '丹藥',
@@ -3309,17 +3312,15 @@ $zh2Hant = array(
 '九扎' => '九紮',
 '九只' => '九隻',
 '九余' => '九餘',
-'九龍表行' => '九龍表行',
 '九龙表行' => '九龍表行',
+'九龍表行' => '九龍表行',
 '也克制' => '也剋制',
 '也斗了胆' => '也斗了膽',
-'干上' => '乾上',
 '干干' => '乾乾',
 '干干儿的' => '乾乾兒的',
 '干干净净' => '乾乾淨淨',
-'干了' => '乾了',
 '干井' => '乾井',
-'干个' => '乾個',
+'干个够' => '乾個夠',
 '干儿' => '乾兒',
 '干冰' => '乾冰',
 '干冷' => '乾冷',
@@ -3356,12 +3357,10 @@ $zh2Hant = array(
 '干巴' => '乾巴',
 '干式' => '乾式',
 '干弟' => '乾弟',
-'干得' => '乾得',
 '干急' => '乾急',
 '干性' => '乾性',
 '干打雷' => '乾打雷',
 '干折' => '乾折',
-'干掉' => '乾掉',
 '干撂台' => '乾撂台',
 '干撇下' => '乾撇下',
 '干擦' => '乾擦',
@@ -3447,8 +3446,8 @@ $zh2Hant = array(
 '干衣' => '乾衣',
 '干裂' => '乾裂',
 '干亲' => '乾親',
-'乾象曆' => '乾象曆',
 '乾象历' => '乾象曆',
+'乾象曆' => '乾象曆',
 '干贝' => '乾貝',
 '干货' => '乾貨',
 '干躁' => '乾躁',
@@ -3497,8 +3496,8 @@ $zh2Hant = array(
 '二缶钟惑' => '二缶鐘惑',
 '二老板' => '二老板',
 '二虎相斗' => '二虎相鬥',
-'二里頭' => '二里頭',
 '二里头' => '二里頭',
+'二里頭' => '二里頭',
 '二只' => '二隻',
 '二余' => '二餘',
 '于丹' => '于丹',
@@ -3510,10 +3509,10 @@ $zh2Hant = array(
 '于伟国' => '于偉國',
 '于偉國' => '于偉國',
 '于光新' => '于光新',
-'于光远' => '于光遠',
 '于光遠' => '于光遠',
-'äº\8eå\85\8b\85°å¤\9aå\8e¿' => 'äº\8eå\85\8b\98­å¤\9a縣',
+'äº\8eå\85\89è¿\9c' => 'äº\8eå\85\89é\81 ',
 '于克-蘭多縣' => '于克-蘭多縣',
+'于克-兰多县' => '于克-蘭多縣',
 '于克勒' => '于克勒',
 '于再清' => '于再清',
 '于冕' => '于冕',
@@ -3530,8 +3529,8 @@ $zh2Hant = array(
 '于吉' => '于吉',
 '于和伟' => '于和偉',
 '于品海' => '于品海',
-'于國楨' => '于國楨',
 '于国桢' => '于國楨',
+'于國楨' => '于國楨',
 '于国治' => '于國治',
 '于國治' => '于國治',
 '于坚' => '于堅',
@@ -3540,15 +3539,15 @@ $zh2Hant = array(
 '于大宝' => '于大寶',
 '于天仁' => '于天仁',
 '于天龙' => '于天龍',
-'于奇庫杜克' => '于奇庫杜克',
 '于奇库杜克' => '于奇庫杜克',
+'于奇庫杜克' => '于奇庫杜克',
 '于姓' => '于姓',
 '于娜' => '于娜',
 '于娟' => '于娟',
 '于子千' => '于子千',
 '于孔兼' => '于孔兼',
-'于学忠' => '于學忠',
 '于學忠' => '于學忠',
+'于学忠' => '于學忠',
 '于家堡' => '于家堡',
 '于寘' => '于寘',
 '于小伟' => '于小偉',
@@ -3559,16 +3558,16 @@ $zh2Hant = array(
 '于山' => '于山',
 '于山国' => '于山國',
 '于山國' => '于山國',
-'于帅' => '于帥',
 '于帥' => '于帥',
+'于帅' => '于帥',
 '于幼軍' => '于幼軍',
 '于幼军' => '于幼軍',
 '于康震' => '于康震',
-'于广洲' => '于廣洲',
 '于廣洲' => '于廣洲',
+'于广洲' => '于廣洲',
 '于式枚' => '于式枚',
-'于从濂' => '于從濂',
 '于從濂' => '于從濂',
+'于从濂' => '于從濂',
 '于德海' => '于德海',
 '于志宁' => '于志寧',
 '于志寧' => '于志寧',
@@ -3576,8 +3575,8 @@ $zh2Hant = array(
 '于思' => '于思',
 '于慎行' => '于慎行',
 '于慧' => '于慧',
-'于成龍' => '于成龍',
 '于成龙' => '于成龍',
+'于成龍' => '于成龍',
 '于振' => '于振',
 '于振武' => '于振武',
 '于敏' => '于敏',
@@ -3588,13 +3587,13 @@ $zh2Hant = array(
 '于斯納爾斯貝里' => '于斯納爾斯貝里',
 '于斯达尔' => '于斯達爾',
 '于斯達爾' => '于斯達爾',
-'于明濤' => '于明濤',
 '于明涛' => '于明濤',
+'于明濤' => '于明濤',
 '于是之' => '于是之',
 '于晨楠' => '于晨楠',
 '于晴' => '于晴',
-'于会泳' => '于會泳',
 '于會泳' => '于會泳',
+'于会泳' => '于會泳',
 '于根伟' => '于根偉',
 '于根偉' => '于根偉',
 '于格' => '于格',
@@ -3602,8 +3601,8 @@ $zh2Hant = array(
 '于枫' => '于楓',
 '于荣光' => '于榮光',
 '于樂' => '于樂',
-'于樹潔' => '于樹潔',
 '于树洁' => '于樹潔',
+'于樹潔' => '于樹潔',
 '于欣' => '于欣',
 '于欣源' => '于欣源',
 '于正升' => '于正昇',
@@ -3620,10 +3619,10 @@ $zh2Hant = array(
 '于浩威' => '于浩威',
 '于海' => '于海',
 '于海洋' => '于海洋',
-'于湘蘭' => '于湘蘭',
 '于湘兰' => '于湘蘭',
-'äº\8eæ±\89è¶\85' => 'äº\8eæ¼¢è¶\85',
+'äº\8eæ¹\98è\98­' => 'äº\8eæ¹\98è\98­',
 '于漢超' => '于漢超',
+'于汉超' => '于漢超',
 '于澄' => '于澄',
 '于泽尔' => '于澤爾',
 '于澤爾' => '于澤爾',
@@ -3632,8 +3631,8 @@ $zh2Hant = array(
 '于熙珍' => '于熙珍',
 '于爾岑' => '于爾岑',
 '于尔岑' => '于爾岑',
-'于尔根' => '于爾根',
 '于爾根' => '于爾根',
+'于尔根' => '于爾根',
 '于尔里克' => '于爾里克',
 '于爾里克' => '于爾里克',
 '于特森' => '于特森',
@@ -3646,8 +3645,8 @@ $zh2Hant = array(
 '于美人' => '于美人',
 '于耘婕' => '于耘婕',
 '于若木' => '于若木',
-'于荫霖' => '于蔭霖',
 '于蔭霖' => '于蔭霖',
+'于荫霖' => '于蔭霖',
 '于衡' => '于衡',
 '于西翰' => '于西翰',
 '于謙' => '于謙',
@@ -3655,20 +3654,20 @@ $zh2Hant = array(
 '于谨' => '于謹',
 '于貝爾' => '于貝爾',
 '于贝尔' => '于貝爾',
-'于贈' => '于贈',
 '于赠' => '于贈',
+'于贈' => '于贈',
 '于越' => '于越',
 '于军' => '于軍',
 '于軍' => '于軍',
 '于道泉' => '于道泉',
-'于遠偉' => '于遠偉',
 '于远伟' => '于遠偉',
-'äº\8eé\83½å\8e¿' => 'äº\8eé\83½ç¸£',
+'äº\8eé\81 å\81\89' => 'äº\8eé\81 å\81\89',
 '于都縣' => '于都縣',
+'于都县' => '于都縣',
 '于里察' => '于里察',
 '于阗' => '于闐',
-'于双戈' => '于雙戈',
 '于雙戈' => '于雙戈',
+'于双戈' => '于雙戈',
 '于云鹤' => '于雲鶴',
 '于震' => '于震',
 '于震寰' => '于震寰',
@@ -3681,17 +3680,17 @@ $zh2Hant = array(
 '于风政' => '于風政',
 '于風政' => '于風政',
 '于飞' => '于飛',
-'于飛島' => '于飛島',
 '于飞岛' => '于飛島',
+'于飛島' => '于飛島',
 '于余曲折' => '于餘曲折',
 '于鬯' => '于鬯',
 '于魁智' => '于魁智',
-'于鳳桐' => '于鳳桐',
 '于凤桐' => '于鳳桐',
+'于鳳桐' => '于鳳桐',
 '于凤至' => '于鳳至',
 '于鳳至' => '于鳳至',
-'于默奧' => '于默奧',
 '于默奥' => '于默奧',
+'于默奧' => '于默奧',
 '云乎' => '云乎',
 '云云' => '云云',
 '云何' => '云何',
@@ -3771,8 +3770,8 @@ $zh2Hant = array(
 '件钟' => '件鐘',
 '任何表演' => '任何表演',
 '任何表示' => '任何表示',
-'任何表达' => '任何表達',
 '任何表達' => '任何表達',
+'任何表达' => '任何表達',
 '任何表' => '任何錶',
 '任何钟' => '任何鐘',
 '任何钟表' => '任何鐘錶',
@@ -3984,8 +3983,8 @@ $zh2Hant = array(
 '占过' => '佔過',
 '占道' => '佔道',
 '占零' => '佔零',
-'占领' => '佔領',
 '占領' => '佔領',
+'占领' => '佔領',
 '占头' => '佔頭',
 '占头筹' => '佔頭籌',
 '占饭' => '佔飯',
@@ -4055,8 +4054,8 @@ $zh2Hant = array(
 '占y' => '佔y',
 '占z' => '佔z',
 '何杰' => '何杰',
-'余三勝' => '余三勝',
 '余三胜' => '余三勝',
+'余三勝' => '余三勝',
 '余光中' => '余光中',
 '余光生' => '余光生',
 '余力為' => '余力為',
@@ -4084,7 +4083,7 @@ $zh2Hant = array(
 '并到' => '併到',
 '并合' => '併合',
 '并名' => '併名',
-'并吞' => '併吞',
+'并吞下' => '併吞下',
 '并拢' => '併攏',
 '并案' => '併案',
 '并流' => '併流',
@@ -4246,8 +4245,8 @@ $zh2Hant = array(
 '凶横' => '兇橫',
 '凶殘' => '兇殘',
 '凶残' => '兇殘',
-'凶杀' => '兇殺',
 '凶殺' => '兇殺',
+'凶杀' => '兇殺',
 '凶犯' => '兇犯',
 '凶狠' => '兇狠',
 '凶猛' => '兇猛',
@@ -4264,8 +4263,8 @@ $zh2Hant = array(
 '党太尉' => '党太尉',
 '党怀英' => '党懷英',
 '党进' => '党進',
-'党项' => '党項',
 '党項' => '党項',
+'党项' => '党項',
 '内制' => '內製',
 '内面包' => '內面包',
 '内面包的' => '內面包的',
@@ -4353,8 +4352,8 @@ $zh2Hant = array(
 '准不准我' => '准不准我',
 '准不准许' => '准不准許',
 '准不准谁' => '准不准誰',
-'准保护' => '准保護',
 '准保護' => '准保護',
+'准保护' => '准保護',
 '准保释' => '准保釋',
 '准保釋' => '准保釋',
 '凌蒙初' => '凌濛初',
@@ -4410,8 +4409,8 @@ $zh2Hant = array(
 '划子' => '划子',
 '划得来' => '划得來',
 '划拳' => '划拳',
-'划槳' => '划槳',
 '划桨' => '划槳',
+'划槳' => '划槳',
 '划水' => '划水',
 '划算' => '划算',
 '划船' => '划船',
@@ -4438,6 +4437,7 @@ $zh2Hant = array(
 '利于' => '利於',
 '利欲熏心' => '利欲熏心',
 '刮来刮去' => '刮來刮去',
+'刮着' => '刮著',
 '刮起来' => '刮起來',
 '刮风下雪倒便宜' => '刮風下雪倒便宜',
 '刮胡' => '刮鬍',
@@ -4485,8 +4485,8 @@ $zh2Hant = array(
 '划入' => '劃入',
 '划为' => '劃為',
 '剧药' => '劇藥',
-'劉佳怜' => '劉佳怜',
 '刘佳怜' => '劉佳怜',
+'劉佳怜' => '劉佳怜',
 '刘克庄' => '劉克莊',
 '刘芸后' => '劉芸后',
 '力克制' => '力剋制',
@@ -4542,12 +4542,12 @@ $zh2Hant = array(
 '十出' => '十齣',
 '千个' => '千個',
 '千只可' => '千只可',
-'千只够' => '千只夠',
 '千只夠' => '千只夠',
+'千只够' => '千只夠',
 '千只怕' => '千只怕',
 '千只能' => '千只能',
-'千只足夠' => '千只足夠',
 '千只足够' => '千只足夠',
+'千只足夠' => '千只足夠',
 '千周后' => '千周後',
 '千多只' => '千多隻',
 '千天后' => '千天後',
@@ -4625,8 +4625,8 @@ $zh2Hant = array(
 '口里' => '口裡',
 '口试' => '口試',
 '口钟' => '口鐘',
-'古書云' => '古書云',
 '古书云' => '古書云',
+'古書云' => '古書云',
 '古柯咸' => '古柯鹹',
 '古柯碱' => '古柯鹼',
 '古朴' => '古樸',
@@ -4647,10 +4647,10 @@ $zh2Hant = array(
 '只要功夫深,铁杵磨成锈花针' => '只要功夫深,鐵杵磨成鏽花針',
 '只身上已' => '只身上已',
 '只身上有' => '只身上有',
-'只身上没' => '只身上沒',
 '只身上沒' => '只身上沒',
-'å\8fªèº«ä¸\8aæ\97 ' => 'å\8fªèº«ä¸\8aç\84¡',
+'å\8fªèº«ä¸\8a没' => 'å\8fªèº«ä¸\8aæ²\92',
 '只身上無' => '只身上無',
+'只身上无' => '只身上無',
 '只身上的' => '只身上的',
 '只身世' => '只身世',
 '只身份' => '只身份',
@@ -4665,8 +4665,8 @@ $zh2Hant = array(
 '只身旁' => '只身旁',
 '只身材' => '只身材',
 '只身段' => '只身段',
-'只身為' => '只身為',
 '只身为' => '只身為',
+'只身為' => '只身為',
 '只身边' => '只身邊',
 '只身邊' => '只身邊',
 '只身首' => '只身首',
@@ -4712,8 +4712,8 @@ $zh2Hant = array(
 '各辟' => '各闢',
 '各类钟' => '各類鐘',
 '合伙人' => '合伙人',
-'合并' => '合併',
 '合伙' => '合夥',
+'合并' => '合并',
 '合府上' => '合府上',
 '合采' => '合採',
 '合历' => '合曆',
@@ -4751,10 +4751,10 @@ $zh2Hant = array(
 '后丰' => '后豐',
 '后豐' => '后豐',
 '后里' => '后里',
-'后髮FK型星' => '后髮FK型星',
 '后发FK型星' => '后髮FK型星',
-'后发座' => '后髮座',
+'后髮FK型星' => '后髮FK型星',
 '后髮座' => '后髮座',
+'后发座' => '后髮座',
 '后发星系团' => '后髮星系團',
 '后髮星系團' => '后髮星系團',
 '吐哺捉发' => '吐哺捉髮',
@@ -4771,8 +4771,8 @@ $zh2Hant = array(
 '吹发' => '吹髮',
 '吹胡' => '吹鬍',
 '吾为之范我驰驱' => '吾爲之範我馳驅',
-'呂后' => '呂后',
 '吕后' => '呂后',
+'呂后' => '呂后',
 '呆呆傻傻' => '呆呆傻傻',
 '呆呆挣挣' => '呆呆掙掙',
 '呆呆獸' => '呆呆獸',
@@ -4788,8 +4788,8 @@ $zh2Hant = array(
 '周后' => '周后',
 '周四' => '周四',
 '周历' => '周曆',
-'周杰倫' => '周杰倫',
 '周杰伦' => '周杰倫',
+'周杰倫' => '周杰倫',
 '周历史' => '周歷史',
 '周庄王' => '周莊王',
 '周游' => '周遊',
@@ -4883,6 +4883,7 @@ $zh2Hant = array(
 '回历史' => '回歷史',
 '回丝' => '回絲',
 '回着' => '回著',
+'回荡' => '回蕩',
 '回游' => '回遊',
 '回阳荡气' => '回陽蕩氣',
 '因于' => '因於',
@@ -4944,9 +4945,9 @@ $zh2Hant = array(
 '埋头寻钟' => '埋頭尋鐘',
 '埋头寻钟表' => '埋頭尋鐘錶',
 '城里' => '城裡',
-'埔里社抚垦局' => '埔裏社撫墾局',
-'埔裏社撫墾局' => '埔裏社撫墾局',
 '埔裡社撫墾局' => '埔裏社撫墾局',
+'埔裏社撫墾局' => '埔裏社撫墾局',
+'埔里社抚垦局' => '埔裏社撫墾局',
 '基干' => '基幹',
 '基于' => '基於',
 '基准' => '基準',
@@ -4973,8 +4974,8 @@ $zh2Hant = array(
 '壶里' => '壺裡',
 '壸范' => '壼範',
 '寿面' => '壽麵',
-'夏于喬' => '夏于喬',
 '夏于乔' => '夏于喬',
+'夏于喬' => '夏于喬',
 '夏天里' => '夏天裡',
 '夏日里' => '夏日裡',
 '夏历' => '夏曆',
@@ -5014,6 +5015,7 @@ $zh2Hant = array(
 '伙同' => '夥同',
 '伙众' => '夥眾',
 '伙计' => '夥計',
+'大丑' => '大丑',
 '大伙儿' => '大伙兒',
 '大只可' => '大只可',
 '大只在' => '大只在',
@@ -5048,7 +5050,6 @@ $zh2Hant = array(
 '大言非夸' => '大言非夸',
 '大赞' => '大讚',
 '大周折' => '大週摺',
-'大丑' => '大醜',
 '大金发苔' => '大金髮苔',
 '大钟' => '大鐘',
 '大只' => '大隻',
@@ -5208,8 +5209,8 @@ $zh2Hant = array(
 '宽松' => '寬鬆',
 '寮采' => '寮寀',
 '宝山庄' => '寶山庄',
-'宝历' => '寶曆',
 '寶曆' => '寶曆',
+'宝历' => '寶曆',
 '宝历史' => '寶歷史',
 '宝庄' => '寶莊',
 '宝里宝气' => '寶裡寶氣',
@@ -5364,20 +5365,23 @@ $zh2Hant = array(
 '年谷' => '年穀',
 '年里' => '年裡',
 '并力' => '并力',
+'并吞' => '并吞',
 '并州' => '并州',
 '并日而食' => '并日而食',
 '并迭' => '并迭',
 '幸免于难' => '幸免於難',
 '幸于' => '幸於',
 '幸运胡' => '幸運鬍',
+'干上' => '幹上',
 '干下去' => '幹下去',
 '干不了' => '幹不了',
 '干不成' => '幹不成',
+'干了' => '幹了',
 '干事' => '幹事',
 '干些' => '幹些',
 '干人' => '幹人',
 '干什么' => '幹什麼',
-'干个够' => '幹個夠',
+'干个' => '幹個',
 '干劲' => '幹勁',
 '干劲冲天' => '幹勁沖天',
 '干吏' => '幹吏',
@@ -5389,9 +5393,10 @@ $zh2Hant = array(
 '干完' => '幹完',
 '干家' => '幹家',
 '干将' => '幹將',
-'干得了' => '幹得了',
+'干得' => '幹得',
 '干性油' => '幹性油',
 '干才' => '幹才',
+'干掉' => '幹掉',
 '干探' => '幹探',
 '干校' => '幹校',
 '干活' => '幹活',
@@ -5404,8 +5409,8 @@ $zh2Hant = array(
 '干略' => '幹略',
 '干当' => '幹當',
 '干的停当' => '幹的停當',
-'干細胞' => '幹細胞',
 '干细胞' => '幹細胞',
+'干細胞' => '幹細胞',
 '干线' => '幹線',
 '干练' => '幹練',
 '干缺' => '幹缺',
@@ -5437,8 +5442,8 @@ $zh2Hant = array(
 '府干政' => '府干政',
 '府干涉' => '府干涉',
 '府干犯' => '府干犯',
-'府干预' => '府干預',
 '府干預' => '府干預',
+'府干预' => '府干預',
 '府干' => '府幹',
 '座钟' => '座鐘',
 '康庄大道' => '康庄大道',
@@ -5746,8 +5751,8 @@ $zh2Hant = array(
 '忠人之托' => '忠人之托',
 '忠仆' => '忠僕',
 '忠于' => '忠於',
+'快干' => '快乾',
 '快克制' => '快剋制',
-'快干' => '快幹',
 '快快当当' => '快快當當',
 '快冲' => '快衝',
 '怎么' => '怎麼',
@@ -5855,8 +5860,8 @@ $zh2Hant = array(
 '所占算' => '所占算',
 '所托' => '所託',
 '扁拟谷盗虫' => '扁擬穀盜蟲',
-'手冢治虫' => '手塚治虫',
 '手塚治虫' => '手塚治虫',
+'手冢治虫' => '手塚治虫',
 '手折' => '手摺',
 '手表态' => '手表態',
 '手表明' => '手表明',
@@ -5867,8 +5872,8 @@ $zh2Hant = array(
 '手表达' => '手表達',
 '手表露' => '手表露',
 '手表面' => '手表面',
-'手里' => '手裏',
 '手里剑' => '手裏劍',
+'手里' => '手裡',
 '手表' => '手錶',
 '手松' => '手鬆',
 '才克制' => '才剋制',
@@ -6313,9 +6318,9 @@ $zh2Hant = array(
 '于国' => '於國',
 '于坏' => '於坏',
 '于垂' => '於垂',
-'於夫羅' => '於夫羅',
 '于夫罗' => '於夫羅',
 '於夫罗' => '於夫羅',
+'於夫羅' => '於夫羅',
 '于她' => '於她',
 '于好' => '於好',
 '于始' => '於始',
@@ -6493,8 +6498,8 @@ $zh2Hant = array(
 '会上签订' => '會上簽訂',
 '会占' => '會佔',
 '会占卜' => '會占卜',
-'會干擾' => '會干擾',
 '会干扰' => '會干擾',
+'會干擾' => '會干擾',
 '会干' => '會幹',
 '会吊' => '會弔',
 '会里' => '會裡',
@@ -6631,8 +6636,8 @@ $zh2Hant = array(
 '棺材里' => '棺材裡',
 '植发' => '植髮',
 '椰枣干' => '椰棗乾',
-'杨雅筑' => '楊雅筑',
 '楊雅筑' => '楊雅筑',
+'杨雅筑' => '楊雅筑',
 '楚庄问鼎' => '楚莊問鼎',
 '楚庄王' => '楚莊王',
 '楚庄绝缨' => '楚莊絕纓',
@@ -6657,8 +6662,8 @@ $zh2Hant = array(
 '模范14棒' => '模范14棒',
 '模范21棒' => '模范21棒',
 '模范七棒' => '模范七棒',
-'模范三軍' => '模范三軍',
 '模范三军' => '模范三軍',
+'模范三軍' => '模范三軍',
 '模范棒棒堂' => '模范棒棒堂',
 '模制' => '模製',
 '样范' => '樣範',
@@ -6818,8 +6823,8 @@ $zh2Hant = array(
 '洒濯' => '洒濯',
 '洒然' => '洒然',
 '洒脱' => '洒脫',
-'洗练' => '洗鍊',
 '洗炼' => '洗鍊',
+'洗练' => '洗鍊',
 '洗发' => '洗髮',
 '洛钟东应' => '洛鐘東應',
 '泄欲' => '洩慾',
@@ -6856,18 +6861,18 @@ $zh2Hant = array(
 '涂序瑄' => '涂序瑄',
 '涂敏恒' => '涂敏恆',
 '涂敏恆' => '涂敏恆',
-'涂泽民' => '涂澤民',
 '涂澤民' => '涂澤民',
+'涂泽民' => '涂澤民',
 '涂绍煃' => '涂紹煃',
 '涂羽卿' => '涂羽卿',
-'涂谨申' => '涂謹申',
 '涂謹申' => '涂謹申',
+'涂谨申' => '涂謹申',
 '涂逢年' => '涂逢年',
 '涂醒哲' => '涂醒哲',
 '涂長望' => '涂長望',
 '涂长望' => '涂長望',
-'涂鴻欽' => '涂鴻欽',
 '涂鸿钦' => '涂鴻欽',
+'涂鴻欽' => '涂鴻欽',
 '消炎药' => '消炎藥',
 '消肿药' => '消腫藥',
 '液晶表' => '液晶錶',
@@ -6898,7 +6903,6 @@ $zh2Hant = array(
 '渠冲' => '渠衝',
 '测试' => '測試',
 '港制' => '港製',
-'游荡' => '游蕩',
 '游离' => '游離',
 '浑朴' => '渾樸',
 '浑个' => '渾箇',
@@ -6999,6 +7003,7 @@ $zh2Hant = array(
 '蒙汜' => '濛汜',
 '蒙蒙细雨' => '濛濛細雨',
 '蒙雾' => '濛霧',
+'蒙松雨' => '濛鬆雨',
 '蒙鸿' => '濛鴻',
 '滨田里佳子' => '濱田里佳子',
 '泻药' => '瀉藥',
@@ -7239,8 +7244,8 @@ $zh2Hant = array(
 '发签' => '發籤',
 '发庄' => '發莊',
 '发着' => '發著',
-'發表' => '發表',
 '发表' => '發表',
+'發表' => '發表',
 '发松' => '發鬆',
 '发面' => '發麵',
 '白干' => '白乾',
@@ -7258,8 +7263,8 @@ $zh2Hant = array(
 '白霉' => '白黴',
 '百个' => '百個',
 '百只可' => '百只可',
-'百只够' => '百只夠',
 '百只夠' => '百只夠',
+'百只够' => '百只夠',
 '百只怕' => '百只怕',
 '百只足够' => '百只足夠',
 '百只足夠' => '百只足夠',
@@ -7356,7 +7361,6 @@ $zh2Hant = array(
 '瞳蒙' => '瞳矇',
 '蒙事' => '矇事',
 '蒙昧无知' => '矇昧無知',
-'蒙松雨' => '矇松雨',
 '蒙混' => '矇混',
 '蒙瞍' => '矇瞍',
 '蒙眬' => '矇矓',
@@ -7542,15 +7546,15 @@ $zh2Hant = array(
 '筑前' => '筑前',
 '筑北' => '筑北',
 '筑州' => '筑州',
-'筑后' => '筑後',
 '筑後' => '筑後',
+'筑后' => '筑後',
 '筑波' => '筑波',
 '筑紫' => '筑紫',
 '筑肥' => '筑肥',
 '筑西' => '筑西',
 '筑邦' => '筑邦',
-'筑阳' => '筑陽',
 '筑陽' => '筑陽',
+'筑阳' => '筑陽',
 '答复' => '答覆',
 '答覆' => '答覆',
 '筵几' => '筵几',
@@ -7574,6 +7578,7 @@ $zh2Hant = array(
 '管人吊脚儿事' => '管人弔腳兒事',
 '管制法' => '管制法',
 '管干' => '管幹',
+'箱里' => '箱裡',
 '节欲' => '節慾',
 '节余' => '節餘',
 '范例' => '範例',
@@ -7692,8 +7697,8 @@ $zh2Hant = array(
 '丝发' => '絲髮',
 '绑扎' => '綁紮',
 '綑扎' => '綑紮',
-'經有云' => '經有云',
 '经有云' => '經有云',
+'經有云' => '經有云',
 '绿发' => '綠髮',
 '绸缎庄' => '綢緞莊',
 '维系' => '維繫',
@@ -7951,8 +7956,8 @@ $zh2Hant = array(
 '舰只' => '艦隻',
 '良药' => '良藥',
 '色欲' => '色慾',
-'艳后' => '艷后',
 '艷后' => '艷后',
+'艳后' => '艷后',
 '艸木丰丰' => '艸木丰丰',
 '芍药' => '芍藥',
 '芒果干' => '芒果乾',
@@ -7977,16 +7982,16 @@ $zh2Hant = array(
 '茂都淀' => '茂都澱',
 '范文同' => '范文同',
 '范文正公' => '范文正公',
-'范文澜' => '范文瀾',
 '范文瀾' => '范文瀾',
+'范文澜' => '范文瀾',
 '范文照' => '范文照',
 '范文程' => '范文程',
 '范文芳' => '范文芳',
 '范文藤' => '范文藤',
 '范文虎' => '范文虎',
 '范登堡' => '范登堡',
-'范賢惠' => '范賢惠',
 '范贤惠' => '范賢惠',
+'范賢惠' => '范賢惠',
 '茶几' => '茶几',
 '茶庄' => '茶莊',
 '茶余' => '茶餘',
@@ -8031,8 +8036,8 @@ $zh2Hant = array(
 '华严钟' => '華嚴鐘',
 '华发' => '華髮',
 '菸碱' => '菸鹼',
-'万一只' => '萬一只',
 '萬一只' => '萬一只',
+'万一只' => '萬一只',
 '万个' => '萬個',
 '万周后' => '萬周後',
 '万多只' => '萬多隻',
@@ -8534,8 +8539,8 @@ $zh2Hant = array(
 '诱奸' => '誘姦',
 '语云' => '語云',
 '语汇' => '語彙',
-'語有云' => '語有云',
 '语有云' => '語有云',
+'語有云' => '語有云',
 '诚征' => '誠徵',
 '诚朴' => '誠樸',
 '诬蔑' => '誣衊',
@@ -8596,7 +8601,6 @@ $zh2Hant = array(
 '豆腐干' => '豆腐乾',
 '竖着' => '豎著',
 '竖起脊梁' => '豎起脊梁',
-'丰度' => '豐度',
 '丰滨' => '豐濱',
 '丰滨乡' => '豐濱鄉',
 '象征' => '象徵',
@@ -8606,17 +8610,17 @@ $zh2Hant = array(
 '贵价' => '貴价',
 '贵干' => '貴幹',
 '贵征' => '貴徵',
-'买凶' => '買兇',
 '買凶' => '買兇',
+'买凶' => '買兇',
 '买断发' => '買斷發',
 '费占' => '費佔',
 '贻范' => '貽範',
 '资金占用' => '資金占用',
-'賈后' => '賈后',
 '贾后' => '賈后',
+'賈后' => '賈后',
 '赏赞' => '賞讚',
-'賢后' => '賢后',
 '贤后' => '賢后',
+'賢后' => '賢后',
 '卖断发' => '賣斷發',
 '卖呆' => '賣獃',
 '质朴' => '質樸',
@@ -8664,10 +8668,10 @@ $zh2Hant = array(
 '较于' => '較於',
 '挽曲' => '輓曲',
 '挽歌' => '輓歌',
-'挽联' => '輓聯',
 '挽聯' => '輓聯',
-'æ\8c½è¯\8d' => 'è¼\93è©\9e',
+'æ\8c½è\81\94' => 'è¼\93è\81¯',
 '挽詞' => '輓詞',
+'挽词' => '輓詞',
 '挽诗' => '輓詩',
 '挽詩' => '輓詩',
 '轻于' => '輕於',
@@ -8710,7 +8714,6 @@ $zh2Hant = array(
 '回绕' => '迴繞',
 '回翔' => '迴翔',
 '回肠' => '迴腸',
-'回荡' => '迴蕩',
 '回诵' => '迴誦',
 '回路' => '迴路',
 '回转' => '迴轉',
@@ -8801,6 +8804,7 @@ $zh2Hant = array(
 '游河' => '遊河',
 '游猎' => '遊獵',
 '游玩' => '遊玩',
+'游荡' => '遊盪',
 '游目骋怀' => '遊目騁懷',
 '游程' => '遊程',
 '游丝' => '遊絲',
@@ -8872,10 +8876,10 @@ $zh2Hant = array(
 '部落发' => '部落發',
 '郭后' => '郭后',
 '都于' => '都於',
-'乡愿' => '鄉愿',
 '鄉愿' => '鄉愿',
-'郑凯云' => '鄭凱云',
+'乡愿' => '鄉愿',
 '鄭凱云' => '鄭凱云',
+'郑凯云' => '鄭凱云',
 '郑庄公' => '鄭莊公',
 '配制饲料' => '配制飼料',
 '配合着' => '配合著',
@@ -8909,7 +8913,6 @@ $zh2Hant = array(
 '丑女' => '醜女',
 '丑女效颦' => '醜女效顰',
 '丑奴儿' => '醜奴兒',
-'丑婆子' => '醜婆子',
 '丑妇' => '醜婦',
 '丑媳' => '醜媳',
 '丑媳妇' => '醜媳婦',
@@ -8951,8 +8954,8 @@ $zh2Hant = array(
 '酿制' => '釀製',
 '衅钟' => '釁鐘',
 '采石之役' => '采石之役',
-'采石之戰' => '采石之戰',
 '采石之战' => '采石之戰',
+'采石之戰' => '采石之戰',
 '采石磯' => '采石磯',
 '采石矶' => '采石磯',
 '釉药' => '釉藥',
@@ -9322,10 +9325,10 @@ $zh2Hant = array(
 '音声如钟' => '音聲如鐘',
 '韶山冲' => '韶山沖',
 '响钟' => '響鐘',
-'页面' => '頁面',
 '頁面' => '頁面',
-'顶å¤\9a' => 'é \82å¤\9a',
+'页é\9d¢' => 'é \81é\9d¢',
 '頂多' => '頂多',
+'顶多' => '頂多',
 '项庄' => '項莊',
 '顺于' => '順於',
 '顺钟向' => '順鐘向',
@@ -9347,8 +9350,8 @@ $zh2Hant = array(
 '颜范' => '顏範',
 '颠干倒坤' => '顛乾倒坤',
 '颠覆' => '顛覆',
-'顛顛仆仆' => '顛顛仆仆',
 '颠颠仆仆' => '顛顛仆仆',
+'顛顛仆仆' => '顛顛仆仆',
 '颤栗' => '顫慄',
 '显示表' => '顯示錶',
 '显示钟' => '顯示鐘',
@@ -9363,15 +9366,14 @@ $zh2Hant = array(
 '风范' => '風範',
 '风里' => '風裡',
 '风起云涌' => '風起雲湧',
-'風采' => '風采',
 '风采' => '風采',
+'風采' => '風采',
 '台风' => '颱風',
 '台风后' => '颱風後',
 '刮了' => '颳了',
 '刮倒' => '颳倒',
 '刮去' => '颳去',
 '刮得' => '颳得',
-'刮着' => '颳著',
 '刮走' => '颳走',
 '刮起' => '颳起',
 '刮雪' => '颳雪',
@@ -9538,16 +9540,16 @@ $zh2Hant = array(
 '香干' => '香乾',
 '香山庄' => '香山庄',
 '马干' => '馬乾',
-'馬占山' => '馬占山',
 '马占山' => '馬占山',
+'馬占山' => '馬占山',
 '马杆' => '馬杆',
-'马格里布' => '馬格里布',
 '馬格里布' => '馬格里布',
+'马格里布' => '馬格里布',
 '马表' => '馬錶',
 '驻扎' => '駐紮',
 '骀荡' => '駘蕩',
-'騰格里' => '騰格里',
 '腾格里' => '騰格里',
+'騰格里' => '騰格里',
 '腾冲' => '騰衝',
 '惊赞' => '驚讚',
 '惊钟' => '驚鐘',
@@ -9733,7 +9735,6 @@ $zh2Hant = array(
 '斗而铸锥' => '鬥而鑄錐',
 '斗脚' => '鬥腳',
 '斗舰' => '鬥艦',
-'斗艳' => '鬥艷',
 '斗茶' => '鬥茶',
 '斗草' => '鬥草',
 '斗叶儿' => '鬥葉兒',
@@ -9741,6 +9742,7 @@ $zh2Hant = array(
 '斗着' => '鬥著',
 '斗蟋蟀' => '鬥蟋蟀',
 '斗话' => '鬥話',
+'斗艳' => '鬥豔',
 '斗起' => '鬥起',
 '斗趣' => '鬥趣',
 '斗闲气' => '鬥閑氣',
@@ -9913,11 +9915,11 @@ $zh2Hant = array(
 '黄历' => '黃曆',
 '黄曲霉' => '黃曲霉',
 '黄历史' => '黃歷史',
-'黄诗杰' => '黃詩杰',
 '黃詩杰' => '黃詩杰',
+'黄诗杰' => '黃詩杰',
 '黄金表' => '黃金表',
-'黄钰筑' => '黃鈺筑',
 '黃鈺筑' => '黃鈺筑',
+'黄钰筑' => '黃鈺筑',
 '黄钟' => '黃鐘',
 '黄发' => '黃髮',
 '黄曲毒素' => '黃麴毒素',
@@ -13243,8 +13245,8 @@ $zh2Hans = array(
 '乘著述' => '乘著述',
 '乾一坛' => '乾一坛',
 '乾一壇' => '乾一坛',
-'乾一組' => '乾一组',
 '乾一组' => '乾一组',
+'乾一組' => '乾一组',
 '乾上乾下' => '乾上乾下',
 '乾為天' => '乾为天',
 '乾為陽' => '乾为阳',
@@ -13264,10 +13266,10 @@ $zh2Hans = array(
 '乾岡' => '乾冈',
 '乾劉' => '乾刘',
 '乾刘' => '乾刘',
-'乾刚' => '乾刚',
 '乾剛' => '乾刚',
-'ä¹¾å\8a¡' => 'ä¹¾å\8a¡',
+'ä¹¾å\88\9a' => 'ä¹¾å\88\9a',
 '乾務' => '乾务',
+'乾务' => '乾务',
 '乾化' => '乾化',
 '乾卦' => '乾卦',
 '乾县' => '乾县',
@@ -13319,12 +13321,12 @@ $zh2Hans = array(
 '乾景' => '乾景',
 '乾晷' => '乾晷',
 '乾曜' => '乾曜',
-'乾構' => '乾构',
 '乾构' => '乾构',
-'ä¹¾æ\9e¢' => 'ä¹¾æ\9e¢',
+'ä¹¾æ§\8b' => 'ä¹¾æ\9e\84',
 '乾樞' => '乾枢',
-'ä¹¾æ£\9f' => 'ä¹¾æ \8b',
+'ä¹¾æ\9e¢' => 'ä¹¾æ\9e¢',
 '乾栋' => '乾栋',
+'乾棟' => '乾栋',
 '乾步' => '乾步',
 '乾氏' => '乾氏',
 '乾沓和' => '乾沓和',
@@ -13334,8 +13336,8 @@ $zh2Hans = array(
 '乾清宮' => '乾清宫',
 '乾清宫' => '乾清宫',
 '乾渥' => '乾渥',
-'乾灵' => '乾灵',
 '乾靈' => '乾灵',
+'乾灵' => '乾灵',
 '乾男' => '乾男',
 '乾皋' => '乾皋',
 '乾盛世' => '乾盛世',
@@ -13354,19 +13356,19 @@ $zh2Hans = array(
 '乾红' => '乾红',
 '乾綱' => '乾纲',
 '乾纲' => '乾纲',
-'乾紐' => '乾纽',
 '乾纽' => '乾纽',
+'乾紐' => '乾纽',
 '乾絡' => '乾络',
 '乾络' => '乾络',
 '乾統' => '乾统',
 '乾统' => '乾统',
 '乾維' => '乾维',
 '乾维' => '乾维',
-'乾罗' => '乾罗',
 '乾羅' => '乾罗',
+'乾罗' => '乾罗',
 '乾花' => '乾花',
-'乾荫' => '乾荫',
 '乾蔭' => '乾荫',
+'乾荫' => '乾荫',
 '乾行' => '乾行',
 '乾衡' => '乾衡',
 '乾覆' => '乾覆',
@@ -13375,19 +13377,19 @@ $zh2Hans = array(
 '乾象历' => '乾象历',
 '乾贞' => '乾贞',
 '乾貞' => '乾贞',
-'乾贶' => '乾贶',
 '乾貺' => '乾贶',
+'乾贶' => '乾贶',
 '乾车' => '乾车',
 '乾車' => '乾车',
-'乾轴' => '乾轴',
 '乾軸' => '乾轴',
+'乾轴' => '乾轴',
 '乾通' => '乾通',
 '乾造' => '乾造',
 '乾道' => '乾道',
 '乾鑒' => '乾鉴',
 '乾鉴' => '乾鉴',
-'乾鈞' => '乾钧',
 '乾钧' => '乾钧',
+'乾鈞' => '乾钧',
 '乾闼' => '乾闼',
 '乾闥' => '乾闼',
 '乾陀' => '乾陀',
@@ -13396,8 +13398,8 @@ $zh2Hans = array(
 '乾音' => '乾音',
 '乾顾' => '乾顾',
 '乾顧' => '乾顾',
-'乾風' => '乾风',
 '乾风' => '乾风',
+'乾風' => '乾风',
 '乾首' => '乾首',
 '乾馬' => '乾马',
 '乾马' => '乾马',
@@ -13405,8 +13407,8 @@ $zh2Hans = array(
 '乾鹄' => '乾鹄',
 '乾鵲' => '乾鹊',
 '乾鹊' => '乾鹊',
-'乾龙' => '乾龙',
 '乾龍' => '乾龙',
+'乾龙' => '乾龙',
 '乾,健也' => '乾,健也',
 '乾,天也' => '乾,天也',
 '爭著' => '争着',
@@ -13419,14 +13421,14 @@ $zh2Hans = array(
 '爭著述' => '争著述',
 '五箇山' => '五箇山',
 '亮著' => '亮着',
-'亮著書' => '亮著书',
 '亮著书' => '亮著书',
+'亮著書' => '亮著书',
 '亮著作' => '亮著作',
 '亮著名' => '亮著名',
 '亮著錄' => '亮著录',
 '亮著录' => '亮著录',
-'亮著稱' => '亮著称',
 '亮著称' => '亮著称',
+'亮著稱' => '亮著称',
 '亮著者' => '亮著者',
 '亮著述' => '亮著述',
 '仗著' => '仗着',
@@ -13441,12 +13443,12 @@ $zh2Hans = array(
 '仗著者' => '仗著者',
 '仗著述' => '仗著述',
 '代表著' => '代表着',
-'代表著书' => '代表著书',
 '代表著書' => '代表著书',
+'代表著书' => '代表著书',
 '代表著作' => '代表著作',
 '代表著名' => '代表著名',
-'代表著录' => '代表著录',
 '代表著錄' => '代表著录',
+'代表著录' => '代表著录',
 '代表著称' => '代表著称',
 '代表著稱' => '代表著称',
 '代表著者' => '代表著者',
@@ -13470,13 +13472,13 @@ $zh2Hans = array(
 '伴著名' => '伴著名',
 '伴著录' => '伴著录',
 '伴著錄' => '伴著录',
-'伴著称' => '伴著称',
 '伴著稱' => '伴著称',
+'伴著称' => '伴著称',
 '伴著者' => '伴著者',
 '伴著述' => '伴著述',
 '低著' => '低着',
-'低著书' => '低著书',
 '低著書' => '低著书',
+'低著书' => '低著书',
 '低著作' => '低著作',
 '低著名' => '低著名',
 '低著录' => '低著录',
@@ -13492,8 +13494,8 @@ $zh2Hans = array(
 '住著名' => '住著名',
 '住著錄' => '住著录',
 '住著录' => '住著录',
-'住著稱' => '住著称',
 '住著称' => '住著称',
+'住著稱' => '住著称',
 '住著者' => '住著者',
 '住著述' => '住著述',
 '佛頭著糞' => '佛头著粪',
@@ -13514,8 +13516,8 @@ $zh2Hans = array(
 '保障著名' => '保障著名',
 '保障著錄' => '保障著录',
 '保障著录' => '保障著录',
-'保障著称' => '保障著称',
 '保障著稱' => '保障著称',
+'保障著称' => '保障著称',
 '保障著者' => '保障著者',
 '保障著述' => '保障著述',
 '信著' => '信着',
@@ -13525,8 +13527,8 @@ $zh2Hans = array(
 '信著名' => '信著名',
 '信著录' => '信著录',
 '信著錄' => '信著录',
-'信著稱' => '信著称',
 '信著称' => '信著称',
+'信著稱' => '信著称',
 '信著者' => '信著者',
 '信著述' => '信著述',
 '修鍊' => '修炼',
@@ -13536,10 +13538,10 @@ $zh2Hans = array(
 '候著书' => '候著书',
 '候著作' => '候著作',
 '候著名' => '候著名',
-'候著錄' => '候著录',
 '候著录' => '候著录',
-'候著称' => '候著称',
+'候著錄' => '候著录',
 '候著稱' => '候著称',
+'候著称' => '候著称',
 '候著者' => '候著者',
 '候著述' => '候著述',
 '藉助' => '借助',
@@ -13549,28 +13551,28 @@ $zh2Hans = array(
 '藉機' => '借机',
 '藉此' => '借此',
 '藉由' => '借由',
-'藉著' => '借着',
 '借著' => '借着',
 '藉着' => '借着',
+'藉著' => '借着',
 '藉端' => '借端',
-'借著书' => '借著书',
 '借著書' => '借著书',
+'借著书' => '借著书',
 '借著作' => '借著作',
 '借著名' => '借著名',
 '借著录' => '借著录',
 '借著錄' => '借著录',
-'借著稱' => '借著称',
 '借著称' => '借著称',
+'借著稱' => '借著称',
 '借著者' => '借著者',
 '借著述' => '借著述',
 '藉詞' => '借词',
 '做著' => '做着',
-'做著书' => '做著书',
 '做著書' => '做著书',
+'做著书' => '做著书',
 '做著作' => '做著作',
 '做著名' => '做著名',
-'做著录' => '做著录',
 '做著錄' => '做著录',
+'做著录' => '做著录',
 '做著稱' => '做著称',
 '做著称' => '做著称',
 '做著者' => '做著者',
@@ -13582,8 +13584,8 @@ $zh2Hans = array(
 '偷著名' => '偷著名',
 '偷著錄' => '偷著录',
 '偷著录' => '偷著录',
-'偷著称' => '偷著称',
 '偷著稱' => '偷著称',
+'偷著称' => '偷著称',
 '偷著者' => '偷著者',
 '偷著述' => '偷著述',
 '傢俬' => '傢俬',
@@ -13608,25 +13610,25 @@ $zh2Hans = array(
 '關著者' => '关著者',
 '關著述' => '关著述',
 '冀著' => '冀着',
-'冀著书' => '冀著书',
 '冀著書' => '冀著书',
+'冀著书' => '冀著书',
 '冀著作' => '冀著作',
 '冀著名' => '冀著名',
-'冀著录' => '冀著录',
 '冀著錄' => '冀著录',
+'冀著录' => '冀著录',
 '冀著稱' => '冀著称',
 '冀著称' => '冀著称',
 '冀著者' => '冀著者',
 '冀著述' => '冀著述',
 '冒著' => '冒着',
-'冒著書' => '冒著书',
 '冒著书' => '冒著书',
+'冒著書' => '冒著书',
 '冒著作' => '冒著作',
 '冒著名' => '冒著名',
 '冒著录' => '冒著录',
 '冒著錄' => '冒著录',
-'冒著称' => '冒著称',
 '冒著稱' => '冒著称',
+'冒著称' => '冒著称',
 '冒著者' => '冒著者',
 '冒著述' => '冒著述',
 '寫著' => '写着',
@@ -13651,10 +13653,10 @@ $zh2Hans = array(
 '制著書' => '制著书',
 '制著作' => '制著作',
 '制著名' => '制著名',
-'制著录' => '制著录',
 '制著錄' => '制著录',
-'制著稱' => '制著称',
+'制著录' => '制著录',
 '制著称' => '制著称',
+'制著稱' => '制著称',
 '制著者' => '制著者',
 '制著述' => '制著述',
 '刻著' => '刻着',
@@ -13685,14 +13687,14 @@ $zh2Hans = array(
 '動著者' => '动著者',
 '動著述' => '动著述',
 '努力著' => '努力着',
-'努力著书' => '努力著书',
 '努力著書' => '努力著书',
+'努力著书' => '努力著书',
 '努力著作' => '努力著作',
 '努力著名' => '努力著名',
-'努力著录' => '努力著录',
 '努力著錄' => '努力著录',
-'努力著稱' => '努力著称',
+'努力著录' => '努力著录',
 '努力著称' => '努力著称',
+'努力著稱' => '努力著称',
 '努力著者' => '努力著者',
 '努力著述' => '努力著述',
 '努著' => '努着',
@@ -13708,14 +13710,14 @@ $zh2Hans = array(
 '努著述' => '努著述',
 '卓著' => '卓著',
 '印著' => '印着',
-'印著書' => '印著书',
 '印著书' => '印著书',
+'印著書' => '印著书',
 '印著作' => '印著作',
 '印著名' => '印著名',
-'印著錄' => '印著录',
 '印著录' => '印著录',
-'印著稱' => '印著称',
+'印著錄' => '印著录',
 '印著称' => '印著称',
+'印著稱' => '印著称',
 '印著者' => '印著者',
 '印著述' => '印著述',
 '卷舌' => '卷舌',
@@ -13729,12 +13731,12 @@ $zh2Hans = array(
 '壓著述' => '压著述',
 '原著' => '原著',
 '去著' => '去着',
-'去著書' => '去著书',
 '去著书' => '去著书',
+'去著書' => '去著书',
 '去著作' => '去著作',
 '去著名' => '去著名',
-'去著錄' => '去著录',
 '去著录' => '去著录',
+'去著錄' => '去著录',
 '去著稱' => '去著称',
 '去著称' => '去著称',
 '去著者' => '去著者',
@@ -13742,12 +13744,12 @@ $zh2Hans = array(
 '反反覆覆' => '反反复复',
 '反覆' => '反复',
 '受著' => '受着',
-'受著书' => '受著书',
 '受著書' => '受著书',
+'受著书' => '受著书',
 '受著作' => '受著作',
 '受著名' => '受著名',
-'受著录' => '受著录',
 '受著錄' => '受著录',
+'受著录' => '受著录',
 '受著稱' => '受著称',
 '受著称' => '受著称',
 '受著者' => '受著者',
@@ -13761,12 +13763,12 @@ $zh2Hans = array(
 '變著者' => '变著者',
 '變著述' => '变著述',
 '叫著' => '叫着',
-'叫著書' => '叫著书',
 '叫著书' => '叫著书',
+'叫著書' => '叫著书',
 '叫著作' => '叫著作',
 '叫著名' => '叫著名',
-'叫著錄' => '叫著录',
 '叫著录' => '叫著录',
+'叫著錄' => '叫著录',
 '叫著称' => '叫著称',
 '叫著稱' => '叫著称',
 '叫著者' => '叫著者',
@@ -13791,8 +13793,8 @@ $zh2Hans = array(
 '向著者' => '向著者',
 '向著述' => '向著述',
 '含著' => '含着',
-'含著书' => '含著书',
 '含著書' => '含著书',
+'含著书' => '含著书',
 '含著作' => '含著作',
 '含著名' => '含著名',
 '含著錄' => '含著录',
@@ -13811,8 +13813,8 @@ $zh2Hans = array(
 '聽著稱' => '听著称',
 '聽著者' => '听著者',
 '聽著述' => '听著述',
-'吳其濬' => '吴其濬',
 '吴其濬' => '吴其濬',
+'吳其濬' => '吴其濬',
 '吹著' => '吹着',
 '吹著書' => '吹著书',
 '吹著书' => '吹著书',
@@ -13826,12 +13828,12 @@ $zh2Hans = array(
 '吹著述' => '吹著述',
 '周易乾' => '周易乾',
 '味著' => '味着',
-'味著書' => '味著书',
 '味著书' => '味著书',
+'味著書' => '味著书',
 '味著作' => '味著作',
 '味著名' => '味著名',
-'味著錄' => '味著录',
 '味著录' => '味著录',
+'味著錄' => '味著录',
 '味著称' => '味著称',
 '味著稱' => '味著称',
 '味著者' => '味著者',
@@ -13847,12 +13849,12 @@ $zh2Hans = array(
 '響著述' => '响著述',
 '哪吒' => '哪吒',
 '哭著' => '哭着',
-'哭著书' => '哭著书',
 '哭著書' => '哭著书',
+'哭著书' => '哭著书',
 '哭著作' => '哭著作',
 '哭著名' => '哭著名',
-'哭著录' => '哭著录',
 '哭著錄' => '哭著录',
+'哭著录' => '哭著录',
 '哭著稱' => '哭著称',
 '哭著称' => '哭著称',
 '哭著者' => '哭著者',
@@ -13864,17 +13866,17 @@ $zh2Hans = array(
 '唱著名' => '唱著名',
 '唱著录' => '唱著录',
 '唱著錄' => '唱著录',
-'唱著稱' => '唱著称',
 '唱著称' => '唱著称',
+'唱著稱' => '唱著称',
 '唱著者' => '唱著者',
 '唱著述' => '唱著述',
 '喝著' => '喝着',
-'喝著書' => '喝著书',
 '喝著书' => '喝著书',
+'喝著書' => '喝著书',
 '喝著作' => '喝著作',
 '喝著名' => '喝著名',
-'喝著錄' => '喝著录',
 '喝著录' => '喝著录',
+'喝著錄' => '喝著录',
 '喝著稱' => '喝著称',
 '喝著称' => '喝著称',
 '喝著者' => '喝著者',
@@ -13883,12 +13885,12 @@ $zh2Hans = array(
 '嗅得著' => '嗅得着',
 '嗅著' => '嗅着',
 '嚷著' => '嚷着',
-'嚷著书' => '嚷著书',
 '嚷著書' => '嚷著书',
+'嚷著书' => '嚷著书',
 '嚷著作' => '嚷著作',
 '嚷著名' => '嚷著名',
-'嚷著录' => '嚷著录',
 '嚷著錄' => '嚷著录',
+'嚷著录' => '嚷著录',
 '嚷著称' => '嚷著称',
 '嚷著稱' => '嚷著称',
 '嚷著者' => '嚷著者',
@@ -13897,19 +13899,19 @@ $zh2Hans = array(
 '因著' => '因着',
 '因著〈' => '因著〈',
 '因著《' => '因著《',
-'因著书' => '因著书',
 '因著書' => '因著书',
+'因著书' => '因著书',
 '因著作' => '因著作',
 '因著名' => '因著名',
-'因著录' => '因著录',
 '因著錄' => '因著录',
-'因著称' => '因著称',
+'因著录' => '因著录',
 '因著稱' => '因著称',
+'因著称' => '因著称',
 '因著者' => '因著者',
 '因著述' => '因著述',
 '困著' => '困着',
-'困著书' => '困著书',
 '困著書' => '困著书',
+'困著书' => '困著书',
 '困著作' => '困著作',
 '困著名' => '困著名',
 '困著錄' => '困著录',
@@ -13928,8 +13930,8 @@ $zh2Hans = array(
 '圍著述' => '围著述',
 '土著' => '土著',
 '在著' => '在着',
-'在著书' => '在著书',
 '在著書' => '在著书',
+'在著书' => '在著书',
 '在著作' => '在著作',
 '在著名' => '在著名',
 '在著錄' => '在著录',
@@ -13939,12 +13941,12 @@ $zh2Hans = array(
 '在著者' => '在著者',
 '在著述' => '在著述',
 '坐著' => '坐着',
-'坐著書' => '坐著书',
 '坐著书' => '坐著书',
+'坐著書' => '坐著书',
 '坐著作' => '坐著作',
 '坐著名' => '坐著名',
-'坐著錄' => '坐著录',
 '坐著录' => '坐著录',
+'坐著錄' => '坐著录',
 '坐著称' => '坐著称',
 '坐著稱' => '坐著称',
 '坐著者' => '坐著者',
@@ -13960,8 +13962,8 @@ $zh2Hans = array(
 '備著述' => '备著述',
 '覆查' => '复查',
 '覆核' => '复核',
-'天道為乾' => '天道为乾',
 '天道为乾' => '天道为乾',
+'天道為乾' => '天道为乾',
 '太閤' => '太阁',
 '夾著' => '夹着',
 '夾著書' => '夹著书',
@@ -13976,8 +13978,8 @@ $zh2Hans = array(
 '字乾生' => '字乾生',
 '存摺' => '存摺',
 '孤著' => '孤着',
-'孤著書' => '孤著书',
 '孤著书' => '孤著书',
+'孤著書' => '孤著书',
 '孤著作' => '孤著作',
 '孤著名' => '孤著名',
 '孤著錄' => '孤著录',
@@ -13995,8 +13997,8 @@ $zh2Hans = array(
 '學著者' => '学著者',
 '學著述' => '学著述',
 '守著' => '守着',
-'守著书' => '守著书',
 '守著書' => '守著书',
+'守著书' => '守著书',
 '守著作' => '守著作',
 '守著名' => '守著名',
 '守著录' => '守著录',
@@ -14036,12 +14038,12 @@ $zh2Hans = array(
 '將軍抽車' => '将军抽車',
 '尼乾陀' => '尼乾陀',
 '展著' => '展着',
-'展著书' => '展著书',
 '展著書' => '展著书',
+'展著书' => '展著书',
 '展著作' => '展著作',
 '展著名' => '展著名',
-'展著录' => '展著录',
 '展著錄' => '展著录',
+'展著录' => '展著录',
 '展著稱' => '展著称',
 '展著称' => '展著称',
 '展著者' => '展著者',
@@ -14068,50 +14070,50 @@ $zh2Hans = array(
 '乾乾脆脆' => '干干脆脆',
 '乾泉水' => '干泉水',
 '幹著' => '干着',
-'幺二三' => '幺二三',
 '么二三' => '幺二三',
-'幺元' => '幺元',
+'幺二三' => '幺二三',
 '么元' => '幺元',
+'幺元' => '幺元',
 '幺鳳' => '幺凤',
 '么鳳' => '幺凤',
-'幺半群' => '幺半群',
 '么半群' => '幺半群',
-'幺å\8e®' => '幺å\8e®',
+'幺å\8d\8a群' => '幺å\8d\8a群',
 '幺廝' => '幺厮',
+'幺厮' => '幺厮',
 '幺叔' => '幺叔',
 '么叔' => '幺叔',
-'幺媽' => '幺妈',
 '么媽' => '幺妈',
+'幺媽' => '幺妈',
 '么妹' => '幺妹',
 '幺妹' => '幺妹',
 '么姓' => '幺姓',
 '幺姓' => '幺姓',
-'幺姨' => '幺姨',
 '么姨' => '幺姨',
+'幺姨' => '幺姨',
+'么娘' => '幺娘',
+'么孃' => '幺娘',
 '幺娘' => '幺娘',
 '幺孃' => '幺娘',
-'么孃' => '幺娘',
-'么娘' => '幺娘',
 '幺小' => '幺小',
 '么小' => '幺小',
-'么氏' => '幺氏',
 '幺氏' => '幺氏',
-'幺爸' => '幺爸',
+'么氏' => '幺氏',
 '么爸' => '幺爸',
-'么爹' => '幺爹',
+'幺爸' => '幺爸',
 '幺爹' => '幺爹',
-'幺篇' => '幺篇',
+'么爹' => '幺爹',
 '么篇' => '幺篇',
+'幺篇' => '幺篇',
 '么舅' => '幺舅',
 '幺舅' => '幺舅',
 '么蛾子' => '幺蛾子',
 '幺蛾子' => '幺蛾子',
-'幺謙' => '幺谦',
 '么謙' => '幺谦',
+'幺謙' => '幺谦',
 '幺麽' => '幺麽',
 '么麼' => '幺麽',
-'么麼小丑' => '幺麽小丑',
 '幺麽小丑' => '幺麽小丑',
+'么麼小丑' => '幺麽小丑',
 '庇護著' => '庇护着',
 '應著' => '应着',
 '應著書' => '应著书',
@@ -14123,12 +14125,12 @@ $zh2Hans = array(
 '應著述' => '应著述',
 '康乾' => '康乾',
 '康著' => '康着',
-'康著書' => '康著书',
 '康著书' => '康著书',
+'康著書' => '康著书',
 '康著作' => '康著作',
 '康著名' => '康著名',
-'康著錄' => '康著录',
 '康著录' => '康著录',
+'康著錄' => '康著录',
 '康著称' => '康著称',
 '康著稱' => '康著称',
 '康著者' => '康著者',
@@ -14141,8 +14143,8 @@ $zh2Hans = array(
 '開著稱' => '开著称',
 '開著者' => '开著者',
 '開著述' => '开著述',
-'张法乾' => '张法乾',
 '張法乾' => '张法乾',
+'张法乾' => '张法乾',
 '當著' => '当着',
 '當著書' => '当著书',
 '當著作' => '当著作',
@@ -14166,8 +14168,8 @@ $zh2Hans = array(
 '待著述' => '待著述',
 '後姓' => '後姓',
 '得著' => '得着',
-'得著书' => '得著书',
 '得著書' => '得著书',
+'得著书' => '得著书',
 '得著作' => '得著作',
 '得著名' => '得著名',
 '得著錄' => '得著录',
@@ -14177,12 +14179,12 @@ $zh2Hans = array(
 '得著者' => '得著者',
 '得著述' => '得著述',
 '循著' => '循着',
-'循著書' => '循著书',
 '循著书' => '循著书',
+'循著書' => '循著书',
 '循著作' => '循著作',
 '循著名' => '循著名',
-'循著錄' => '循著录',
 '循著录' => '循著录',
+'循著錄' => '循著录',
 '循著称' => '循著称',
 '循著稱' => '循著称',
 '循著者' => '循著者',
@@ -14194,13 +14196,13 @@ $zh2Hans = array(
 '心著名' => '心著名',
 '心著录' => '心著录',
 '心著錄' => '心著录',
-'心著称' => '心著称',
 '心著稱' => '心著称',
+'心著称' => '心著称',
 '心著者' => '心著者',
 '心著述' => '心著述',
 '忍著' => '忍着',
-'忍著書' => '忍著书',
 '忍著书' => '忍著书',
+'忍著書' => '忍著书',
 '忍著作' => '忍著作',
 '忍著名' => '忍著名',
 '忍著录' => '忍著录',
@@ -14210,23 +14212,23 @@ $zh2Hans = array(
 '忍著者' => '忍著者',
 '忍著述' => '忍著述',
 '志著' => '志着',
-'志著书' => '志著书',
 '志著書' => '志著书',
+'志著书' => '志著书',
 '志著作' => '志著作',
 '志著名' => '志著名',
-'志著录' => '志著录',
 '志著錄' => '志著录',
-'志著稱' => '志著称',
+'志著录' => '志著录',
 '志著称' => '志著称',
+'志著稱' => '志著称',
 '志著者' => '志著者',
 '志著述' => '志著述',
 '忙著' => '忙着',
-'忙著書' => '忙著书',
 '忙著书' => '忙著书',
+'忙著書' => '忙著书',
 '忙著作' => '忙著作',
 '忙著名' => '忙著名',
-'忙著錄' => '忙著录',
 '忙著录' => '忙著录',
+'忙著錄' => '忙著录',
 '忙著称' => '忙著称',
 '忙著稱' => '忙著称',
 '忙著者' => '忙著者',
@@ -14240,25 +14242,25 @@ $zh2Hans = array(
 '懷著者' => '怀著者',
 '懷著述' => '怀著述',
 '急著' => '急着',
-'急著書' => '急著书',
 '急著书' => '急著书',
+'急著書' => '急著书',
 '急著作' => '急著作',
 '急著名' => '急著名',
-'急著錄' => '急著录',
 '急著录' => '急著录',
+'急著錄' => '急著录',
 '急著称' => '急著称',
 '急著稱' => '急著称',
 '急著者' => '急著者',
 '急著述' => '急著述',
 '性著' => '性着',
-'性著書' => '性著书',
 '性著书' => '性著书',
+'性著書' => '性著书',
 '性著作' => '性著作',
 '性著名' => '性著名',
-'性著錄' => '性著录',
 '性著录' => '性著录',
-'性著稱' => '性著称',
+'性著錄' => '性著录',
 '性著称' => '性著称',
+'性著稱' => '性著称',
 '性著者' => '性著者',
 '性著述' => '性著述',
 '戀著' => '恋着',
@@ -14277,8 +14279,8 @@ $zh2Hans = array(
 '悠著名' => '悠著名',
 '悠著錄' => '悠著录',
 '悠著录' => '悠著录',
-'悠著稱' => '悠著称',
 '悠著称' => '悠著称',
+'悠著稱' => '悠著称',
 '悠著者' => '悠著者',
 '悠著述' => '悠著述',
 '慣著' => '惯着',
@@ -14290,14 +14292,14 @@ $zh2Hans = array(
 '慣著者' => '惯著者',
 '慣著述' => '惯著述',
 '想著' => '想着',
-'想著书' => '想著书',
 '想著書' => '想著书',
+'想著书' => '想著书',
 '想著作' => '想著作',
 '想著名' => '想著名',
-'想著录' => '想著录',
 '想著錄' => '想著录',
-'想著稱' => '想著称',
+'想著录' => '想著录',
 '想著称' => '想著称',
+'想著稱' => '想著称',
 '想著者' => '想著者',
 '想著述' => '想著述',
 '戰著' => '战着',
@@ -14309,12 +14311,12 @@ $zh2Hans = array(
 '戰著者' => '战著者',
 '戰著述' => '战著述',
 '戴著' => '戴着',
-'戴著书' => '戴著书',
 '戴著書' => '戴著书',
+'戴著书' => '戴著书',
 '戴著作' => '戴著作',
 '戴著名' => '戴著名',
-'戴著录' => '戴著录',
 '戴著錄' => '戴著录',
+'戴著录' => '戴著录',
 '戴著稱' => '戴著称',
 '戴著称' => '戴著称',
 '戴著者' => '戴著者',
@@ -14326,17 +14328,17 @@ $zh2Hans = array(
 '扎著名' => '扎著名',
 '扎著錄' => '扎著录',
 '扎著录' => '扎著录',
-'扎著稱' => '扎著称',
 '扎著称' => '扎著称',
+'扎著稱' => '扎著称',
 '扎著者' => '扎著者',
 '扎著述' => '扎著述',
 '打著' => '打着',
-'打著书' => '打著书',
 '打著書' => '打著书',
+'打著书' => '打著书',
 '打著作' => '打著作',
 '打著名' => '打著名',
-'打著录' => '打著录',
 '打著錄' => '打著录',
+'打著录' => '打著录',
 '打著称' => '打著称',
 '打著稱' => '打著称',
 '打著者' => '打著者',
@@ -14361,8 +14363,8 @@ $zh2Hans = array(
 '抓著名' => '抓著名',
 '抓著录' => '抓著录',
 '抓著錄' => '抓著录',
-'抓著稱' => '抓著称',
 '抓著称' => '抓著称',
+'抓著稱' => '抓著称',
 '抓著者' => '抓著者',
 '抓著述' => '抓著述',
 '護著' => '护着',
@@ -14378,17 +14380,17 @@ $zh2Hans = array(
 '披著書' => '披著书',
 '披著作' => '披著作',
 '披著名' => '披著名',
-'披著錄' => '披著录',
 '披著录' => '披著录',
-'披著称' => '披著称',
+'披著錄' => '披著录',
 '披著稱' => '披著称',
+'披著称' => '披著称',
 '披著者' => '披著者',
 '披著述' => '披著述',
 '抬著' => '抬着',
 '抬著作' => '抬著作',
 '抬著名' => '抬著名',
-'抬著錄' => '抬著录',
 '抬著录' => '抬著录',
+'抬著錄' => '抬著录',
 '抬著稱' => '抬著称',
 '抬著称' => '抬著称',
 '抬著者' => '抬著者',
@@ -14398,8 +14400,8 @@ $zh2Hans = array(
 '抱著名' => '抱著名',
 '抱著录' => '抱著录',
 '抱著錄' => '抱著录',
-'抱著称' => '抱著称',
 '抱著稱' => '抱著称',
+'抱著称' => '抱著称',
 '抱著者' => '抱著者',
 '抱著述' => '抱著述',
 '拉著' => '拉着',
@@ -14409,8 +14411,8 @@ $zh2Hans = array(
 '拉著名' => '拉著名',
 '拉著录' => '拉著录',
 '拉著錄' => '拉著录',
-'拉著稱' => '拉著称',
 '拉著称' => '拉著称',
+'拉著稱' => '拉著称',
 '拉著者' => '拉著者',
 '拉著述' => '拉著述',
 '拉鍊' => '拉链',
@@ -14439,8 +14441,8 @@ $zh2Hans = array(
 '拼著' => '拼着',
 '拼著作' => '拼著作',
 '拼著名' => '拼著名',
-'拼著錄' => '拼著录',
 '拼著录' => '拼著录',
+'拼著錄' => '拼著录',
 '拼著稱' => '拼著称',
 '拼著称' => '拼著称',
 '拼著者' => '拼著者',
@@ -14448,10 +14450,10 @@ $zh2Hans = array(
 '拿著' => '拿着',
 '拿著作' => '拿著作',
 '拿著名' => '拿著名',
-'拿著錄' => '拿著录',
 '拿著录' => '拿著录',
-'拿著稱' => '拿著称',
+'拿著錄' => '拿著录',
 '拿著称' => '拿著称',
+'拿著稱' => '拿著称',
 '拿著者' => '拿著者',
 '拿著述' => '拿著述',
 '持著' => '持着',
@@ -14468,8 +14470,8 @@ $zh2Hans = array(
 '挑著名' => '挑著名',
 '挑著錄' => '挑著录',
 '挑著录' => '挑著录',
-'挑著稱' => '挑著称',
 '挑著称' => '挑著称',
+'挑著稱' => '挑著称',
 '挑著者' => '挑著者',
 '挑著述' => '挑著述',
 '擋著' => '挡着',
@@ -14506,10 +14508,10 @@ $zh2Hans = array(
 '捆著' => '捆着',
 '捆著作' => '捆著作',
 '捆著名' => '捆著名',
-'捆著录' => '捆著录',
 '捆著錄' => '捆著录',
-'捆著稱' => '捆著称',
+'捆著录' => '捆著录',
 '捆著称' => '捆著称',
+'捆著稱' => '捆著称',
 '捆著者' => '捆著者',
 '捆著述' => '捆著述',
 '據著' => '据着',
@@ -14523,10 +14525,10 @@ $zh2Hans = array(
 '掖著' => '掖着',
 '掖著作' => '掖著作',
 '掖著名' => '掖著名',
-'掖著录' => '掖著录',
 '掖著錄' => '掖著录',
-'掖著称' => '掖著称',
+'掖著录' => '掖著录',
 '掖著稱' => '掖著称',
+'掖著称' => '掖著称',
 '掖著者' => '掖著者',
 '掖著述' => '掖著述',
 '接著' => '接着',
@@ -14539,14 +14541,14 @@ $zh2Hans = array(
 '接著者' => '接著者',
 '接著述' => '接著述',
 '揉著' => '揉着',
-'揉著書' => '揉著书',
 '揉著书' => '揉著书',
+'揉著書' => '揉著书',
 '揉著作' => '揉著作',
 '揉著名' => '揉著名',
-'揉著錄' => '揉著录',
 '揉著录' => '揉著录',
-'揉著稱' => '揉著称',
+'揉著錄' => '揉著录',
 '揉著称' => '揉著称',
+'揉著稱' => '揉著称',
 '揉著者' => '揉著者',
 '揉著述' => '揉著述',
 '提著' => '提着',
@@ -14574,14 +14576,14 @@ $zh2Hans = array(
 '擺著述' => '摆著述',
 '撰著' => '撰著',
 '撼著' => '撼着',
-'撼著书' => '撼著书',
 '撼著書' => '撼著书',
+'撼著书' => '撼著书',
 '撼著作' => '撼著作',
 '撼著名' => '撼著名',
-'撼著录' => '撼著录',
 '撼著錄' => '撼著录',
-'撼著稱' => '撼著称',
+'撼著录' => '撼著录',
 '撼著称' => '撼著称',
+'撼著稱' => '撼著称',
 '撼著者' => '撼著者',
 '撼著述' => '撼著述',
 '敞著' => '敞着',
@@ -14589,8 +14591,8 @@ $zh2Hans = array(
 '敞著名' => '敞著名',
 '敞著錄' => '敞著录',
 '敞著录' => '敞著录',
-'敞著称' => '敞著称',
 '敞著稱' => '敞著称',
+'敞著称' => '敞著称',
 '敞著者' => '敞著者',
 '敞著述' => '敞著述',
 '數著' => '数着',
@@ -14616,10 +14618,10 @@ $zh2Hans = array(
 '斥著书' => '斥著书',
 '斥著作' => '斥著作',
 '斥著名' => '斥著名',
-'斥著录' => '斥著录',
 '斥著錄' => '斥著录',
-'斥著称' => '斥著称',
+'斥著录' => '斥著录',
 '斥著稱' => '斥著称',
+'斥著称' => '斥著称',
 '斥著者' => '斥著者',
 '斥著述' => '斥著述',
 '新著' => '新著',
@@ -14638,8 +14640,8 @@ $zh2Hans = array(
 '於志賀' => '於志贺',
 '於志贺' => '於志贺',
 '於戲' => '於戏',
-'於梨华' => '於梨华',
 '於梨華' => '於梨华',
+'於梨华' => '於梨华',
 '於氏' => '於氏',
 '於潛縣' => '於潜县',
 '於潜县' => '於潜县',
@@ -14647,34 +14649,34 @@ $zh2Hans = array(
 '於菟' => '於菟',
 '於賢德' => '於贤德',
 '於除鞬' => '於除鞬',
-'旋乾轉坤' => '旋乾转坤',
 '旋乾转坤' => '旋乾转坤',
+'旋乾轉坤' => '旋乾转坤',
 '曠若發矇' => '旷若发矇',
 '昂著' => '昂着',
 '昂著书' => '昂著书',
 '昂著書' => '昂著书',
 '昂著作' => '昂著作',
 '昂著名' => '昂著名',
-'昂著录' => '昂著录',
 '昂著錄' => '昂著录',
+'昂著录' => '昂著录',
 '昂著稱' => '昂著称',
 '昂著称' => '昂著称',
 '昂著者' => '昂著者',
 '昂著述' => '昂著述',
 '易·乾' => '易·乾',
-'易经·乾' => '易经·乾',
 '易經·乾' => '易经·乾',
+'易经·乾' => '易经·乾',
 '易經乾' => '易经乾',
 '易经乾' => '易经乾',
 '映著' => '映着',
-'映著书' => '映著书',
 '映著書' => '映著书',
+'映著书' => '映著书',
 '映著作' => '映著作',
 '映著名' => '映著名',
-'映著录' => '映著录',
 '映著錄' => '映著录',
-'映著称' => '映著称',
+'映著录' => '映著录',
 '映著稱' => '映著称',
+'映著称' => '映著称',
 '映著者' => '映著者',
 '映著述' => '映著述',
 '昭著' => '昭著',
@@ -14683,15 +14685,15 @@ $zh2Hans = array(
 '晃著' => '晃着',
 '晃著作' => '晃著作',
 '晃著名' => '晃著名',
-'晃著录' => '晃著录',
 '晃著錄' => '晃著录',
-'晃著稱' => '晃著称',
+'晃著录' => '晃著录',
 '晃著称' => '晃著称',
+'晃著稱' => '晃著称',
 '晃著者' => '晃著者',
 '晃著述' => '晃著述',
 '暗著' => '暗着',
-'暗著書' => '暗著书',
 '暗著书' => '暗著书',
+'暗著書' => '暗著书',
 '暗著作' => '暗著作',
 '暗著名' => '暗著名',
 '暗著錄' => '暗著录',
@@ -14705,17 +14707,17 @@ $zh2Hans = array(
 '有著书' => '有著书',
 '有著作' => '有著作',
 '有著名' => '有著名',
-'有著录' => '有著录',
 '有著錄' => '有著录',
-'有著稱' => '有著称',
+'有著录' => '有著录',
 '有著称' => '有著称',
+'有著稱' => '有著称',
 '有著者' => '有著者',
 '有著述' => '有著述',
 '望著' => '望着',
 '望著作' => '望著作',
 '望著名' => '望著名',
-'望著錄' => '望著录',
 '望著录' => '望著录',
+'望著錄' => '望著录',
 '望著稱' => '望著称',
 '望著称' => '望著称',
 '望著者' => '望著者',
@@ -14724,21 +14726,21 @@ $zh2Hans = array(
 '朝著' => '朝着',
 '朝著作' => '朝著作',
 '朝著名' => '朝著名',
-'朝著錄' => '朝著录',
 '朝著录' => '朝著录',
-'朝著称' => '朝著称',
+'朝著錄' => '朝著录',
 '朝著稱' => '朝著称',
+'朝著称' => '朝著称',
 '朝著者' => '朝著者',
 '朝著述' => '朝著述',
 '本著' => '本着',
-'本著書' => '本著书',
 '本著书' => '本著书',
+'本著書' => '本著书',
 '本著作' => '本著作',
 '本著名' => '本著名',
-'本著錄' => '本著录',
 '本著录' => '本著录',
-'本著称' => '本著称',
+'本著錄' => '本著录',
 '本著稱' => '本著称',
+'本著称' => '本著称',
 '本著者' => '本著者',
 '本著述' => '本著述',
 '朴於宇同' => '朴於宇同',
@@ -14759,8 +14761,8 @@ $zh2Hans = array(
 '雜著者' => '杂著者',
 '雜著述' => '杂著述',
 '李乾德' => '李乾德',
-'李乾顺' => '李乾顺',
 '李乾順' => '李乾顺',
+'李乾顺' => '李乾顺',
 '李澤鉅' => '李泽钜',
 '來著' => '来着',
 '來著書' => '来著书',
@@ -14776,8 +14778,8 @@ $zh2Hans = array(
 '枕著名' => '枕著名',
 '枕著錄' => '枕著录',
 '枕著录' => '枕著录',
-'枕著称' => '枕著称',
 '枕著稱' => '枕著称',
+'枕著称' => '枕著称',
 '枕著者' => '枕著者',
 '枕著述' => '枕著述',
 '柳詒徵' => '柳诒徵',
@@ -14849,17 +14851,17 @@ $zh2Hans = array(
 '活著名' => '活著名',
 '活著录' => '活著录',
 '活著錄' => '活著录',
-'活著称' => '活著称',
 '活著稱' => '活著称',
+'活著称' => '活著称',
 '活著者' => '活著者',
 '活著述' => '活著述',
 '流著' => '流着',
-'流著書' => '流著书',
 '流著书' => '流著书',
+'流著書' => '流著书',
 '流著作' => '流著作',
 '流著名' => '流著名',
-'流著錄' => '流著录',
 '流著录' => '流著录',
+'流著錄' => '流著录',
 '流著稱' => '流著称',
 '流著称' => '流著称',
 '流著者' => '流著者',
@@ -14872,8 +14874,8 @@ $zh2Hans = array(
 '浮著名' => '浮著名',
 '浮著录' => '浮著录',
 '浮著錄' => '浮著录',
-'浮著称' => '浮著称',
 '浮著稱' => '浮著称',
+'浮著称' => '浮著称',
 '浮著者' => '浮著者',
 '浮著述' => '浮著述',
 '潤著' => '润着',
@@ -14889,10 +14891,10 @@ $zh2Hans = array(
 '涵著書' => '涵著书',
 '涵著作' => '涵著作',
 '涵著名' => '涵著名',
-'涵著錄' => '涵著录',
 '涵著录' => '涵著录',
-'涵著称' => '涵著称',
+'涵著錄' => '涵著录',
 '涵著稱' => '涵著称',
+'涵著称' => '涵著称',
 '涵著者' => '涵著者',
 '涵著述' => '涵著述',
 '渴著' => '渴着',
@@ -14902,8 +14904,8 @@ $zh2Hans = array(
 '渴著名' => '渴著名',
 '渴著录' => '渴著录',
 '渴著錄' => '渴著录',
-'渴著稱' => '渴著称',
 '渴著称' => '渴著称',
+'渴著稱' => '渴著称',
 '渴著者' => '渴著者',
 '渴著述' => '渴著述',
 '溢著' => '溢着',
@@ -14924,8 +14926,8 @@ $zh2Hans = array(
 '演著名' => '演著名',
 '演著录' => '演著录',
 '演著錄' => '演著录',
-'演著称' => '演著称',
 '演著稱' => '演著称',
+'演著称' => '演著称',
 '演著者' => '演著者',
 '演著述' => '演著述',
 '漫著' => '漫着',
@@ -14933,8 +14935,8 @@ $zh2Hans = array(
 '漫著书' => '漫著书',
 '漫著作' => '漫著作',
 '漫著名' => '漫著名',
-'漫著錄' => '漫著录',
 '漫著录' => '漫著录',
+'漫著錄' => '漫著录',
 '漫著称' => '漫著称',
 '漫著稱' => '漫著称',
 '漫著者' => '漫著者',
@@ -14954,14 +14956,14 @@ $zh2Hans = array(
 '燒著者' => '烧著者',
 '燒著述' => '烧著述',
 '照著' => '照着',
-'照著書' => '照著书',
 '照著书' => '照著书',
+'照著書' => '照著书',
 '照著作' => '照著作',
 '照著名' => '照著名',
-'照著錄' => '照著录',
 '照著录' => '照著录',
-'照著稱' => '照著称',
+'照著錄' => '照著录',
 '照著称' => '照著称',
+'照著稱' => '照著称',
 '照著者' => '照著者',
 '照著述' => '照著述',
 '愛護著' => '爱护着',
@@ -14995,8 +14997,8 @@ $zh2Hans = array(
 '猜著書' => '猜着书',
 '猜著作' => '猜著作',
 '猜著名' => '猜著名',
-'猜著录' => '猜著录',
 '猜著錄' => '猜著录',
+'猜著录' => '猜著录',
 '猜著称' => '猜著称',
 '猜著稱' => '猜著称',
 '猜著者' => '猜著者',
@@ -15008,8 +15010,8 @@ $zh2Hans = array(
 '甜著书' => '甜著书',
 '甜著作' => '甜著作',
 '甜著名' => '甜著名',
-'甜著錄' => '甜著录',
 '甜著录' => '甜著录',
+'甜著錄' => '甜著录',
 '甜著稱' => '甜著称',
 '甜著称' => '甜著称',
 '甜著者' => '甜著者',
@@ -15027,12 +15029,12 @@ $zh2Hans = array(
 '用著稱' => '用著称',
 '用著者' => '用著者',
 '用著述' => '用著述',
-'男為乾' => '男为乾',
-'男爲乾' => '男为乾',
 '男为乾' => '男为乾',
+'男爲乾' => '男为乾',
+'男為乾' => '男为乾',
 '男性為乾' => '男性为乾',
-'男性为乾' => '男性为乾',
 '男性爲乾' => '男性为乾',
+'男性为乾' => '男性为乾',
 '留著' => '留着',
 '留著書' => '留着书',
 '留著作' => '留著作',
@@ -15064,12 +15066,12 @@ $zh2Hans = array(
 '皺著者' => '皱著者',
 '皺著述' => '皱著述',
 '盛著' => '盛着',
-'盛著書' => '盛著书',
 '盛著书' => '盛著书',
+'盛著書' => '盛著书',
 '盛著作' => '盛著作',
 '盛著名' => '盛著名',
-'盛著录' => '盛著录',
 '盛著錄' => '盛著录',
+'盛著录' => '盛著录',
 '盛著稱' => '盛著称',
 '盛著称' => '盛著称',
 '盛著者' => '盛著者',
@@ -15085,14 +15087,14 @@ $zh2Hans = array(
 '盯著者' => '盯著者',
 '盯著述' => '盯著述',
 '盾著' => '盾着',
-'盾著书' => '盾著书',
 '盾著書' => '盾著书',
+'盾著书' => '盾著书',
 '盾著作' => '盾著作',
 '盾著名' => '盾著名',
-'盾著录' => '盾著录',
 '盾著錄' => '盾著录',
-'盾著称' => '盾著称',
+'盾著录' => '盾著录',
 '盾著稱' => '盾著称',
+'盾著称' => '盾著称',
 '盾著者' => '盾著者',
 '盾著述' => '盾著述',
 '看不著' => '看不着',
@@ -15103,8 +15105,8 @@ $zh2Hans = array(
 '看著名' => '看著名',
 '看著录' => '看著录',
 '看著錄' => '看著录',
-'看著称' => '看著称',
 '看著稱' => '看著称',
+'看著称' => '看著称',
 '看著者' => '看著者',
 '看著述' => '看著述',
 '著業' => '着业',
@@ -15212,14 +15214,14 @@ $zh2Hans = array(
 '睡不著' => '睡不着',
 '睡得著' => '睡得着',
 '睡著' => '睡着',
-'睡著书' => '睡著书',
 '睡著書' => '睡著书',
+'睡著书' => '睡著书',
 '睡著作' => '睡著作',
 '睡著名' => '睡著名',
-'睡著录' => '睡著录',
 '睡著錄' => '睡著录',
-'睡著稱' => '睡著称',
+'睡著录' => '睡著录',
 '睡著称' => '睡著称',
+'睡著稱' => '睡著称',
 '睡著者' => '睡著者',
 '睡著述' => '睡著述',
 '睹微知著' => '睹微知著',
@@ -15247,8 +15249,8 @@ $zh2Hans = array(
 '瞪著书' => '瞪著书',
 '瞪著作' => '瞪著作',
 '瞪著名' => '瞪著名',
-'瞪著录' => '瞪著录',
 '瞪著錄' => '瞪著录',
+'瞪著录' => '瞪著录',
 '瞪著称' => '瞪著称',
 '瞪著稱' => '瞪著称',
 '瞪著者' => '瞪著者',
@@ -15261,10 +15263,10 @@ $zh2Hans = array(
 '福著書' => '福著书',
 '福著作' => '福著作',
 '福著名' => '福著名',
-'福著录' => '福著录',
 '福著錄' => '福著录',
-'福著称' => '福著称',
+'福著录' => '福著录',
 '福著稱' => '福著称',
+'福著称' => '福著称',
 '福著者' => '福著者',
 '福著述' => '福著述',
 '穀梁' => '穀梁',
@@ -15275,17 +15277,17 @@ $zh2Hans = array(
 '空著名' => '空著名',
 '空著录' => '空著录',
 '空著錄' => '空著录',
-'空著稱' => '空著称',
 '空著称' => '空著称',
+'空著稱' => '空著称',
 '空著者' => '空著者',
 '空著述' => '空著述',
 '穿著' => '穿着',
-'穿著書' => '穿著书',
 '穿著书' => '穿著书',
+'穿著書' => '穿著书',
 '穿著作' => '穿著作',
 '穿著名' => '穿著名',
-'穿著錄' => '穿著录',
 '穿著录' => '穿著录',
+'穿著錄' => '穿著录',
 '穿著称' => '穿著称',
 '穿著稱' => '穿著称',
 '穿著者' => '穿著者',
@@ -15299,14 +15301,14 @@ $zh2Hans = array(
 '豎著者' => '竖著者',
 '豎著述' => '竖著述',
 '站著' => '站着',
-'站著書' => '站著书',
 '站著书' => '站著书',
+'站著書' => '站著书',
 '站著作' => '站著作',
 '站著名' => '站著名',
-'站著录' => '站著录',
 '站著錄' => '站著录',
-'站著稱' => '站著称',
+'站著录' => '站著录',
 '站著称' => '站著称',
+'站著稱' => '站著称',
 '站著者' => '站著者',
 '站著述' => '站著述',
 '笑著' => '笑着',
@@ -15316,8 +15318,8 @@ $zh2Hans = array(
 '笑著名' => '笑著名',
 '笑著录' => '笑著录',
 '笑著錄' => '笑著录',
-'笑著稱' => '笑著称',
 '笑著称' => '笑著称',
+'笑著稱' => '笑著称',
 '笑著者' => '笑著者',
 '笑著述' => '笑著述',
 '答覆' => '答复',
@@ -15328,8 +15330,8 @@ $zh2Hans = array(
 '管著名' => '管著名',
 '管著录' => '管著录',
 '管著錄' => '管著录',
-'管著称' => '管著称',
 '管著稱' => '管著称',
+'管著称' => '管著称',
 '管著者' => '管著者',
 '管著述' => '管著述',
 '米澤瑠美' => '米泽瑠美',
@@ -15362,34 +15364,34 @@ $zh2Hans = array(
 '纏著者' => '缠著者',
 '纏著述' => '缠著述',
 '罩著' => '罩着',
-'罩著書' => '罩著书',
 '罩著书' => '罩著书',
+'罩著書' => '罩著书',
 '罩著作' => '罩著作',
 '罩著名' => '罩著名',
-'罩著录' => '罩著录',
 '罩著錄' => '罩著录',
-'罩著稱' => '罩著称',
+'罩著录' => '罩著录',
 '罩著称' => '罩著称',
+'罩著稱' => '罩著称',
 '罩著者' => '罩著者',
 '罩著述' => '罩著述',
 '美著' => '美着',
-'美著書' => '美著书',
 '美著书' => '美著书',
+'美著書' => '美著书',
 '美著作' => '美著作',
 '美著名' => '美著名',
-'美著錄' => '美著录',
 '美著录' => '美著录',
+'美著錄' => '美著录',
 '美著稱' => '美著称',
 '美著称' => '美著称',
 '美著者' => '美著者',
 '美著述' => '美著述',
 '耀著' => '耀着',
-'耀著书' => '耀著书',
 '耀著書' => '耀著书',
+'耀著书' => '耀著书',
 '耀著作' => '耀著作',
 '耀著名' => '耀著名',
-'耀著录' => '耀著录',
 '耀著錄' => '耀著录',
+'耀著录' => '耀著录',
 '耀著称' => '耀著称',
 '耀著稱' => '耀著称',
 '耀著者' => '耀著者',
@@ -15415,8 +15417,8 @@ $zh2Hans = array(
 '背著名' => '背著名',
 '背著录' => '背著录',
 '背著錄' => '背著录',
-'背著稱' => '背著称',
 '背著称' => '背著称',
+'背著稱' => '背著称',
 '背著者' => '背著者',
 '背著述' => '背著述',
 '膠著' => '胶着',
@@ -15436,18 +15438,18 @@ $zh2Hans = array(
 '藝著者' => '艺著者',
 '藝著述' => '艺著述',
 '苦著' => '苦着',
-'苦著書' => '苦著书',
 '苦著书' => '苦著书',
+'苦著書' => '苦著书',
 '苦著作' => '苦著作',
 '苦著名' => '苦著名',
-'苦著錄' => '苦著录',
 '苦著录' => '苦著录',
-'苦著称' => '苦著称',
+'苦著錄' => '苦著录',
 '苦著稱' => '苦著称',
+'苦著称' => '苦著称',
 '苦著者' => '苦著者',
 '苦著述' => '苦著述',
-'薴烯' => '苧烯',
 '苧烯' => '苧烯',
+'薴烯' => '苧烯',
 '獲著' => '获着',
 '獲著書' => '获著书',
 '獲著作' => '获著作',
@@ -15465,8 +15467,8 @@ $zh2Hans = array(
 '落著名' => '落著名',
 '落著录' => '落著录',
 '落著錄' => '落著录',
-'落著称' => '落著称',
 '落著稱' => '落著称',
+'落著称' => '落著称',
 '落著者' => '落著者',
 '落著述' => '落著述',
 '著書' => '著书',
@@ -15483,14 +15485,14 @@ $zh2Hans = array(
 '蒙汗葯' => '蒙汗药',
 '蒙著' => '蒙着',
 '蒙葯' => '蒙药',
-'蒙著书' => '蒙著书',
 '蒙著書' => '蒙著书',
+'蒙著书' => '蒙著书',
 '蒙著作' => '蒙著作',
 '蒙著名' => '蒙著名',
 '蒙著录' => '蒙著录',
 '蒙著錄' => '蒙著录',
-'蒙著称' => '蒙著称',
 '蒙著稱' => '蒙著称',
+'蒙著称' => '蒙著称',
 '蒙著者' => '蒙著者',
 '蒙著述' => '蒙著述',
 '藏著' => '藏着',
@@ -15500,19 +15502,19 @@ $zh2Hans = array(
 '藏著名' => '藏著名',
 '藏著錄' => '藏著录',
 '藏著录' => '藏著录',
-'藏著稱' => '藏著称',
 '藏著称' => '藏著称',
+'藏著稱' => '藏著称',
 '藏著者' => '藏著者',
 '藏著述' => '藏著述',
 '蘸著' => '蘸着',
-'蘸著书' => '蘸著书',
 '蘸著書' => '蘸著书',
+'蘸著书' => '蘸著书',
 '蘸著作' => '蘸著作',
 '蘸著名' => '蘸著名',
 '蘸著录' => '蘸著录',
 '蘸著錄' => '蘸著录',
-'蘸著称' => '蘸著称',
 '蘸著稱' => '蘸著称',
+'蘸著称' => '蘸著称',
 '蘸著者' => '蘸著者',
 '蘸著述' => '蘸著述',
 '行著' => '行着',
@@ -15520,19 +15522,19 @@ $zh2Hans = array(
 '行著書' => '行著书',
 '行著作' => '行著作',
 '行著名' => '行著名',
-'行著錄' => '行著录',
 '行著录' => '行著录',
-'行著称' => '行著称',
+'行著錄' => '行著录',
 '行著稱' => '行著称',
+'行著称' => '行著称',
 '行著者' => '行著者',
 '行著述' => '行著述',
 '衣著' => '衣着',
-'衣著書' => '衣著书',
 '衣著书' => '衣著书',
+'衣著書' => '衣著书',
 '衣著作' => '衣著作',
 '衣著名' => '衣著名',
-'衣著錄' => '衣著录',
 '衣著录' => '衣著录',
+'衣著錄' => '衣著录',
 '衣著稱' => '衣著称',
 '衣著称' => '衣著称',
 '衣著者' => '衣著者',
@@ -15546,14 +15548,14 @@ $zh2Hans = array(
 '裝著者' => '装著者',
 '裝著述' => '装著述',
 '裹著' => '裹着',
-'裹著书' => '裹著书',
 '裹著書' => '裹著书',
+'裹著书' => '裹著书',
 '裹著作' => '裹著作',
 '裹著名' => '裹著名',
 '裹著录' => '裹著录',
 '裹著錄' => '裹著录',
-'裹著稱' => '裹著称',
 '裹著称' => '裹著称',
+'裹著稱' => '裹著称',
 '裹著者' => '裹著者',
 '裹著述' => '裹著述',
 '覆蓋' => '覆蓋',
@@ -15602,8 +15604,8 @@ $zh2Hans = array(
 '豫著名' => '豫著名',
 '豫著录' => '豫著录',
 '豫著錄' => '豫著录',
-'豫著稱' => '豫著称',
 '豫著称' => '豫著称',
+'豫著稱' => '豫著称',
 '豫著者' => '豫著者',
 '豫著述' => '豫著述',
 '貞著' => '贞着',
@@ -15615,14 +15617,14 @@ $zh2Hans = array(
 '貞著者' => '贞著者',
 '貞著述' => '贞著述',
 '走著' => '走着',
-'走著书' => '走著书',
 '走著書' => '走著书',
+'走著书' => '走著书',
 '走著作' => '走著作',
 '走著名' => '走著名',
-'走著录' => '走著录',
 '走著錄' => '走著录',
-'走著称' => '走著称',
+'走著录' => '走著录',
 '走著稱' => '走著称',
+'走著称' => '走著称',
 '走著者' => '走著者',
 '走著述' => '走著述',
 '趕著' => '赶着',
@@ -15638,8 +15640,8 @@ $zh2Hans = array(
 '趴著书' => '趴著书',
 '趴著作' => '趴著作',
 '趴著名' => '趴著名',
-'趴著錄' => '趴著录',
 '趴著录' => '趴著录',
+'趴著錄' => '趴著录',
 '趴著称' => '趴著称',
 '趴著稱' => '趴著称',
 '趴著者' => '趴著者',
@@ -15657,8 +15659,8 @@ $zh2Hans = array(
 '跑著书' => '跑著书',
 '跑著作' => '跑著作',
 '跑著名' => '跑著名',
-'跑著錄' => '跑著录',
 '跑著录' => '跑著录',
+'跑著錄' => '跑著录',
 '跑著稱' => '跑著称',
 '跑著称' => '跑著称',
 '跑著者' => '跑著者',
@@ -15670,28 +15672,28 @@ $zh2Hans = array(
 '跟著名' => '跟著名',
 '跟著录' => '跟著录',
 '跟著錄' => '跟著录',
-'跟著稱' => '跟著称',
 '跟著称' => '跟著称',
+'跟著稱' => '跟著称',
 '跟著者' => '跟著者',
 '跟著述' => '跟著述',
 '跪著' => '跪着',
-'跪著书' => '跪著书',
 '跪著書' => '跪著书',
+'跪著书' => '跪著书',
 '跪著作' => '跪著作',
 '跪著名' => '跪著名',
-'跪著录' => '跪著录',
 '跪著錄' => '跪著录',
+'跪著录' => '跪著录',
 '跪著稱' => '跪著称',
 '跪著称' => '跪著称',
 '跪著者' => '跪著者',
 '跪著述' => '跪著述',
 '跳著' => '跳着',
-'跳著書' => '跳著书',
 '跳著书' => '跳著书',
+'跳著書' => '跳著书',
 '跳著作' => '跳著作',
 '跳著名' => '跳著名',
-'跳著錄' => '跳著录',
 '跳著录' => '跳著录',
+'跳著錄' => '跳著录',
 '跳著称' => '跳著称',
 '跳著稱' => '跳著称',
 '跳著者' => '跳著者',
@@ -15704,13 +15706,13 @@ $zh2Hans = array(
 '踏著名' => '踏著名',
 '踏著錄' => '踏著录',
 '踏著录' => '踏著录',
-'踏著稱' => '踏著称',
 '踏著称' => '踏著称',
+'踏著稱' => '踏著称',
 '踏著者' => '踏著者',
 '踏著述' => '踏著述',
 '踩著' => '踩着',
-'踩著書' => '踩著书',
 '踩著书' => '踩著书',
+'踩著書' => '踩著书',
 '踩著作' => '踩著作',
 '踩著名' => '踩著名',
 '踩著录' => '踩著录',
@@ -15720,12 +15722,12 @@ $zh2Hans = array(
 '踩著者' => '踩著者',
 '踩著述' => '踩著述',
 '身著' => '身着',
-'身著書' => '身著书',
 '身著书' => '身著书',
+'身著書' => '身著书',
 '身著作' => '身著作',
 '身著名' => '身著名',
-'身著錄' => '身著录',
 '身著录' => '身著录',
+'身著錄' => '身著录',
 '身著稱' => '身著称',
 '身著称' => '身著称',
 '身著者' => '身著者',
@@ -15737,8 +15739,8 @@ $zh2Hans = array(
 '躺著名' => '躺著名',
 '躺著錄' => '躺著录',
 '躺著录' => '躺著录',
-'躺著稱' => '躺著称',
 '躺著称' => '躺著称',
+'躺著稱' => '躺著称',
 '躺著者' => '躺著者',
 '躺著述' => '躺著述',
 '轉著' => '转着',
@@ -15787,34 +15789,34 @@ $zh2Hans = array(
 '連著述' => '连著述',
 '迫著' => '迫着',
 '追著' => '追着',
-'追著书' => '追著书',
 '追著書' => '追著书',
+'追著书' => '追著书',
 '追著作' => '追著作',
 '追著名' => '追著名',
-'追著录' => '追著录',
 '追著錄' => '追著录',
+'追著录' => '追著录',
 '追著称' => '追著称',
 '追著稱' => '追著称',
 '追著者' => '追著者',
 '追著述' => '追著述',
 '逆著' => '逆着',
-'逆著书' => '逆著书',
 '逆著書' => '逆著书',
+'逆著书' => '逆著书',
 '逆著作' => '逆著作',
 '逆著名' => '逆著名',
-'逆著录' => '逆著录',
 '逆著錄' => '逆著录',
-'逆著稱' => '逆著称',
+'逆著录' => '逆著录',
 '逆著称' => '逆著称',
+'逆著稱' => '逆著称',
 '逆著者' => '逆著者',
 '逆著述' => '逆著述',
 '逼著' => '逼着',
-'逼著书' => '逼著书',
 '逼著書' => '逼著书',
+'逼著书' => '逼著书',
 '逼著作' => '逼著作',
 '逼著名' => '逼著名',
-'逼著录' => '逼著录',
 '逼著錄' => '逼著录',
+'逼著录' => '逼著录',
 '逼著称' => '逼著称',
 '逼著稱' => '逼著称',
 '逼著者' => '逼著者',
@@ -15840,8 +15842,8 @@ $zh2Hans = array(
 '配著名' => '配著名',
 '配著錄' => '配著录',
 '配著录' => '配著录',
-'配著称' => '配著称',
 '配著稱' => '配著称',
+'配著称' => '配著称',
 '配著者' => '配著者',
 '配著述' => '配著述',
 '釀著' => '酿着',
@@ -15852,14 +15854,14 @@ $zh2Hans = array(
 '釀著稱' => '酿著称',
 '釀著者' => '酿著者',
 '釀著述' => '酿著述',
-'醯壶' => '醯壶',
 '醯壺' => '醯壶',
+'醯壶' => '醯壶',
 '醯醬' => '醯酱',
 '醯酱' => '醯酱',
 '醯醋' => '醯醋',
 '醯醢' => '醯醢',
-'醯雞' => '醯鸡',
 '醯鸡' => '醯鸡',
+'醯雞' => '醯鸡',
 '重覆' => '重复',
 '金鍊' => '金链',
 '鐵鍊' => '铁链',
@@ -15901,8 +15903,8 @@ $zh2Hans = array(
 '聞得著' => '闻得着',
 '聞著' => '闻着',
 '阳为乾' => '阳为乾',
-'陽為乾' => '阳为乾',
 '陽爲乾' => '阳为乾',
+'陽為乾' => '阳为乾',
 '阿部正瞭' => '阿部正瞭',
 '附著' => '附着',
 '附睪' => '附睾',
@@ -15910,36 +15912,36 @@ $zh2Hans = array(
 '附著書' => '附著书',
 '附著作' => '附著作',
 '附著名' => '附著名',
-'附著录' => '附著录',
 '附著錄' => '附著录',
+'附著录' => '附著录',
 '附著称' => '附著称',
 '附著稱' => '附著称',
 '附著者' => '附著者',
 '附著述' => '附著述',
-'陳乾生' => '陈乾生',
 '陈乾生' => '陈乾生',
-'陳公乾生' => '陈公乾生',
+'陳乾生' => '陈乾生',
 '陈公乾生' => '陈公乾生',
+'陳公乾生' => '陈公乾生',
 '陋著' => '陋着',
-'陋著书' => '陋著书',
 '陋著書' => '陋著书',
+'陋著书' => '陋著书',
 '陋著作' => '陋著作',
 '陋著名' => '陋著名',
-'陋著录' => '陋著录',
 '陋著錄' => '陋著录',
-'陋著稱' => '陋著称',
+'陋著录' => '陋著录',
 '陋著称' => '陋著称',
+'陋著稱' => '陋著称',
 '陋著者' => '陋著者',
 '陋著述' => '陋著述',
 '陪著' => '陪着',
-'陪著書' => '陪著书',
 '陪著书' => '陪著书',
+'陪著書' => '陪著书',
 '陪著作' => '陪著作',
 '陪著名' => '陪著名',
-'陪著錄' => '陪著录',
 '陪著录' => '陪著录',
-'陪著稱' => '陪著称',
+'陪著錄' => '陪著录',
 '陪著称' => '陪著称',
+'陪著稱' => '陪著称',
 '陪著者' => '陪著者',
 '陪著述' => '陪著述',
 '陳堵' => '陳堵',
@@ -15953,26 +15955,26 @@ $zh2Hans = array(
 '隨著者' => '随著者',
 '隨著述' => '随著述',
 '隔著' => '隔着',
-'隔著書' => '隔著书',
 '隔著书' => '隔著书',
+'隔著書' => '隔著书',
 '隔著作' => '隔著作',
 '隔著名' => '隔著名',
-'隔著錄' => '隔著录',
 '隔著录' => '隔著录',
+'隔著錄' => '隔著录',
 '隔著称' => '隔著称',
 '隔著稱' => '隔著称',
 '隔著者' => '隔著者',
 '隔著述' => '隔著述',
 '隱睪' => '隱睾',
 '雅著' => '雅着',
-'雅著書' => '雅著书',
 '雅著书' => '雅著书',
+'雅著書' => '雅著书',
 '雅著作' => '雅著作',
 '雅著名' => '雅著名',
-'雅著錄' => '雅著录',
 '雅著录' => '雅著录',
-'雅著稱' => '雅著称',
+'雅著錄' => '雅著录',
 '雅著称' => '雅著称',
+'雅著稱' => '雅著称',
 '雅著者' => '雅著者',
 '雅著述' => '雅著述',
 '雍乾' => '雍乾',
@@ -15981,8 +15983,8 @@ $zh2Hans = array(
 '靠著名' => '靠著名',
 '靠著錄' => '靠著录',
 '靠著录' => '靠著录',
-'靠著称' => '靠著称',
 '靠著稱' => '靠著称',
+'靠著称' => '靠著称',
 '靠著者' => '靠著者',
 '靠著述' => '靠著述',
 '頂著' => '顶着',
@@ -16063,8 +16065,8 @@ $zh2Hans = array(
 '高著者' => '高著者',
 '高著述' => '高著述',
 '髭著' => '髭着',
-'髭著書' => '髭著书',
 '髭著书' => '髭著书',
+'髭著書' => '髭著书',
 '髭著作' => '髭著作',
 '髭著名' => '髭著名',
 '髭著錄' => '髭著录',
@@ -16078,17 +16080,17 @@ $zh2Hans = array(
 '魏徵' => '魏徵',
 '魚乾乾' => '鱼干干',
 '麯崇裕' => '麯崇裕',
-'麴义' => '麴义',
 '麴義' => '麴义',
+'麴义' => '麴义',
 '麴英' => '麴英',
 '麽氏' => '麽氏',
-'麼麼' => '麽麽',
 '麽麽' => '麽麽',
+'麼麼' => '麽麽',
 '黄润乾' => '黄润乾',
 '黃潤乾' => '黄润乾',
 '黏著' => '黏着',
-'黏著書' => '黏著书',
 '黏著书' => '黏著书',
+'黏著書' => '黏著书',
 '黏著作' => '黏著作',
 '黏著名' => '黏著名',
 '黏著录' => '黏著录',
@@ -16104,23 +16106,23 @@ $zh2TW = array(
 '”' => '」',
 '‘' => '『',
 '’' => '』',
-'三极管' => '三極體',
 '三極管' => '三極體',
+'三极管' => '三極體',
 '世界裏' => '世界裡',
 '中文裏' => '中文裡',
 '串行' => '串列',
 '串列加速器' => '串列加速器',
 '以太网' => '乙太網',
 '奶酪' => '乳酪',
-'二极管' => '二極體',
 '二極管' => '二極體',
+'二极管' => '二極體',
 '交互式' => '互動式',
 '阿塞拜疆' => '亞塞拜然',
 '人工智能' => '人工智慧',
 '接口' => '介面',
 '服务器' => '伺服器',
-'字节' => '位元組',
 '字節' => '位元組',
+'字节' => '位元組',
 '作品裏' => '作品裡',
 '信道' => '信道',
 '优先级' => '優先順序',
@@ -16135,20 +16137,20 @@ $zh2TW = array(
 '冬日裏' => '冬日裡',
 '凉菜' => '冷盤',
 '冷菜' => '冷盤',
-'兇器' => '凶器',
 '凶器' => '凶器',
-'å\85\87å¾\92' => 'å\87¶å¾\92',
+'å\85\87å\99¨' => 'å\87¶å\99¨',
 '凶徒' => '凶徒',
+'兇徒' => '凶徒',
 '兇手' => '凶手',
 '凶手' => '凶手',
-'凶案' => '凶案',
 '兇案' => '凶案',
-'å\85\87æ®\98' => 'å\87¶æ®\98',
+'å\87¶æ¡\88' => 'å\87¶æ¡\88',
 '凶殘' => '凶殘',
+'兇殘' => '凶殘',
 '凶残' => '凶殘',
 '兇殺' => '凶殺',
-'凶殺' => '凶殺',
 '凶杀' => '凶殺',
+'凶殺' => '凶殺',
 '打印' => '列印',
 '列支敦士登' => '列支敦斯登',
 '剪彩' => '剪綵',
@@ -16158,10 +16160,10 @@ $zh2TW = array(
 '特立尼達和多巴哥' => '千里達托貝哥',
 '特立尼达和托巴哥' => '千里達托貝哥',
 '半角' => '半形',
-'卡塔尔' => '卡達',
 '卡塔爾' => '卡達',
-'打印机' => '印表機',
+'卡塔尔' => '卡達',
 '打印機' => '印表機',
+'打印机' => '印表機',
 '厄立特里亚' => '厄利垂亞',
 '厄立特里亞' => '厄利垂亞',
 '厄瓜多尔' => '厄瓜多',
@@ -16176,17 +16178,17 @@ $zh2TW = array(
 '哈萨克斯坦' => '哈薩克',
 '哥斯達黎加' => '哥斯大黎加',
 '哥斯达黎加' => '哥斯大黎加',
-'格鲁吉亚' => '喬治亞',
 '格魯吉亞' => '喬治亞',
-'佐治亞' => '喬治亞',
+'格鲁吉亚' => '喬治亞',
 '佐治亚' => '喬治亞',
+'佐治亞' => '喬治亞',
 '嘴裏' => '嘴裡',
 '土库曼斯坦' => '土庫曼',
 '薯仔' => '土豆',
 '土豆網' => '土豆網',
 '土豆网' => '土豆網',
-'坦桑尼亞' => '坦尚尼亞',
 '坦桑尼亚' => '坦尚尼亞',
+'坦桑尼亞' => '坦尚尼亞',
 '端口' => '埠',
 '塔吉克斯坦' => '塔吉克',
 '塞舌尔' => '塞席爾',
@@ -16201,63 +16203,63 @@ $zh2TW = array(
 '多明尼加國' => '多米尼克',
 '穿梭機' => '太空梭',
 '航天飞机' => '太空梭',
-'尼日利亞' => '奈及利亞',
 '尼日利亚' => '奈及利亞',
+'尼日利亞' => '奈及利亞',
 '字符' => '字元',
 '字号' => '字型大小',
 '字库' => '字型檔',
 '字符集' => '字符集',
 '存盘' => '存檔',
 '學裏' => '學裡',
-'安提瓜和巴布达' => '安地卡及巴布達',
 '安提瓜和巴布達' => '安地卡及巴布達',
+'安提瓜和巴布达' => '安地卡及巴布達',
 '宋元' => '宋元',
 '洪都拉斯' => '宏都拉斯',
 '寻址' => '定址',
 '寒假裏' => '寒假裡',
 '宽带' => '寬頻',
-'老挝' => '寮國',
 '老撾' => '寮國',
+'老挝' => '寮國',
 '打门' => '射門',
 '專輯裏' => '專輯裡',
-'赞比亚' => '尚比亞',
 '贊比亞' => '尚比亞',
-'尼日尔' => '尼日',
+'赞比亚' => '尚比亞',
 '尼日爾' => '尼日',
+'尼日尔' => '尼日',
 '山洞裏' => '山洞裡',
 '巴布亞新畿內亞' => '巴布亞紐幾內亞',
 '巴布亚新几内亚' => '巴布亞紐幾內亞',
 '巴巴多斯' => '巴貝多',
 '布基纳法索' => '布吉納法索',
 '布基納法索' => '布吉納法索',
-'布殊' => '布希',
 '布什' => '布希',
+'布殊' => '布希',
 '帕劳' => '帛琉',
 '例程' => '常式',
-'平治之亂' => '平治之亂',
 '平治之乱' => '平治之亂',
+'平治之亂' => '平治之亂',
 '年代裏' => '年代裡',
-'幾內亞比紹' => '幾內亞比索',
 '几内亚比绍' => '幾內亞比索',
+'幾內亞比紹' => '幾內亞比索',
 '彩带' => '彩帶',
 '彩排' => '彩排',
 '彩楼' => '彩樓',
 '彩牌楼' => '彩牌樓',
-'复苏' => '復甦',
 '復蘇' => '復甦',
+'复苏' => '復甦',
 '心裏' => '心裡',
-'闪存' => '快閃記憶體',
 '快闪存储器' => '快閃記憶體',
+'闪存' => '快閃記憶體',
 '想象' => '想像',
 '传感' => '感測',
 '习用' => '慣用',
 '戏彩娱亲' => '戲綵娛親',
 '戲裏' => '戲裡',
-'手电' => '手電筒',
 '手电筒' => '手電筒',
+'手电' => '手電筒',
 '括号' => '括弧',
-'拿破仑' => '拿破崙',
 '拿破侖' => '拿破崙',
+'拿破仑' => '拿破崙',
 '積架' => '捷豹',
 '扫瞄仪' => '掃瞄器',
 '挂钩' => '掛鉤',
@@ -16267,12 +16269,12 @@ $zh2TW = array(
 '桌球' => '撞球',
 '便携式' => '攜帶型',
 '故事裏' => '故事裡',
-'調制解調器' => '數據機',
 '调制解调器' => '數據機',
-'斯洛文尼亚' => '斯洛維尼亞',
+'調制解調器' => '數據機',
 '斯洛文尼亞' => '斯洛維尼亞',
-'æ\96°ç´\80å\85\83' => 'æ\96°ç´\80å\85\83',
+'æ\96¯æ´\9bæ\96\87å°¼äº\9a' => 'æ\96¯æ´\9b維尼äº\9e',
 '新纪元' => '新紀元',
+'新紀元' => '新紀元',
 '日子裏' => '日子裡',
 '春假裏' => '春假裡',
 '春天裏' => '春天裡',
@@ -16284,13 +16286,13 @@ $zh2TW = array(
 '乍得' => '查德',
 '克林頓' => '柯林頓',
 '克林顿' => '柯林頓',
-'格林纳达' => '格瑞那達',
 '格林納達' => '格瑞那達',
+'格林纳达' => '格瑞那達',
 '凡高' => '梵谷',
 '森林裏' => '森林裡',
 '棺材裏' => '棺材裡',
-'榴莲' => '榴槤',
 '榴蓮' => '榴槤',
+'榴莲' => '榴槤',
 '仿真' => '模擬',
 '毛里裘斯' => '模里西斯',
 '毛里求斯' => '模里西斯',
@@ -16301,15 +16303,15 @@ $zh2TW = array(
 '元音' => '母音',
 '永历' => '永曆',
 '文莱' => '汶萊',
-'沙地阿拉伯' => '沙烏地阿拉伯',
 '沙特阿拉伯' => '沙烏地阿拉伯',
-'æ³¢æ\96¯å°¼äº\9aå\92\8cé»\91å¡\9eå\93¥ç»´é\82£' => '波士尼äº\9e赫å¡\9eå\93¥ç¶­ç´\8d',
+'æ²\99å\9c°é\98¿æ\8b\89伯' => 'æ²\99ç\83\8få\9c°é\98¿æ\8b\89伯',
 '波斯尼亞黑塞哥維那' => '波士尼亞赫塞哥維納',
-'博茨瓦納' => '波札那',
+'波斯尼亚和黑塞哥维那' => '波士尼亞赫塞哥維納',
 '博茨瓦纳' => '波札那',
+'博茨瓦納' => '波札那',
 '流程控制' => '流程控制',
-'侯賽因' => '海珊',
 '侯赛因' => '海珊',
+'侯賽因' => '海珊',
 '深淵裏' => '深淵裡',
 '光标' => '游標',
 '鼠标' => '滑鼠',
@@ -16318,18 +16320,18 @@ $zh2TW = array(
 '词组' => '片語',
 '獄裏' => '獄裡',
 '塞拉利昂' => '獅子山',
-'危地馬拉' => '瓜地馬拉',
 '危地马拉' => '瓜地馬拉',
+'危地馬拉' => '瓜地馬拉',
 '冈比亚' => '甘比亞',
 '岡比亞' => '甘比亞',
 '疑兇' => '疑凶',
 '疑凶' => '疑凶',
 '百科裏' => '百科裡',
 '皮裏陽秋' => '皮裡陽秋',
-'卢旺达' => '盧安達',
 '盧旺達' => '盧安達',
-'真兇' => '真凶',
+'卢旺达' => '盧安達',
 '真凶' => '真凶',
+'真兇' => '真凶',
 '眼睛裏' => '眼睛裡',
 '硅片' => '矽片',
 '硅谷' => '矽谷',
@@ -16347,43 +16349,43 @@ $zh2TW = array(
 '蹦极跳' => '笨豬跳',
 '绑紧跳' => '笨豬跳',
 '等于' => '等於',
-'短信' => '簡訊',
 '短訊' => '簡訊',
+'短信' => '簡訊',
 '系列裏' => '系列裡',
 '新西蘭' => '紐西蘭',
 '新西兰' => '紐西蘭',
-'所羅門群島' => '索羅門群島',
 '所罗门群岛' => '索羅門群島',
-'索马里' => '索馬利亞',
+'所羅門群島' => '索羅門群島',
 '索馬里' => '索馬利亞',
+'索马里' => '索馬利亞',
 '结彩' => '結綵',
 '佛得角' => '維德角',
 '網絡' => '網路',
 '网络' => '網路',
-'因特网' => '網際網路',
 '互聯網' => '網際網路',
+'因特网' => '網際網路',
 '彩球' => '綵球',
 '彩绸' => '綵綢',
 '彩线' => '綵線',
 '彩船' => '綵船',
 '彩衣' => '綵衣',
 '綫' => '線',
-'緝兇' => '緝凶',
 '缉凶' => '緝凶',
+'緝兇' => '緝凶',
 '緝凶' => '緝凶',
 '意大利' => '義大利',
 '老字号' => '老字號',
 '圣基茨和尼维斯' => '聖克里斯多福及尼維斯',
 '聖吉斯納域斯' => '聖克里斯多福及尼維斯',
-'圣文森特和格林纳丁斯' => '聖文森及格瑞那丁',
 '聖文森特和格林納丁斯' => '聖文森及格瑞那丁',
+'圣文森特和格林纳丁斯' => '聖文森及格瑞那丁',
 '圣卢西亚' => '聖露西亞',
 '聖盧西亞' => '聖露西亞',
 '圣马力诺' => '聖馬利諾',
 '聖馬力諾' => '聖馬利諾',
 '肚裏' => '肚裡',
-'肯雅' => '肯亞',
 '肯尼亚' => '肯亞',
+'肯雅' => '肯亞',
 '航天大学' => '航天大學',
 '苦裏' => '苦裡',
 '毛里塔尼亚' => '茅利塔尼亞',
@@ -16392,8 +16394,8 @@ $zh2TW = array(
 '万历' => '萬曆',
 '瓦努阿图' => '萬那杜',
 '瓦努阿圖' => '萬那杜',
-'也門' => '葉門',
 '也门' => '葉門',
+'也門' => '葉門',
 '着' => '著',
 '科摩羅' => '葛摩',
 '科摩罗' => '葛摩',
@@ -16402,19 +16404,19 @@ $zh2TW = array(
 '圭亚那' => '蓋亞那',
 '火锅盖帽' => '蓋火鍋',
 '苏里南' => '蘇利南',
-'行兇' => '行凶',
 '行凶' => '行凶',
+'行兇' => '行凶',
+'行凶后' => '行凶後',
 '行兇後' => '行凶後',
 '行凶後' => '行凶後',
-'行凶后' => '行凶後',
-'移动电话' => '行動電話',
 '流動電話' => '行動電話',
+'移动电话' => '行動電話',
 '行程控制' => '行程控制',
 '衞' => '衛',
 '卫生' => '衛生',
 '衞生' => '衛生',
-'埃塞俄比亞' => '衣索比亞',
 '埃塞俄比亚' => '衣索比亞',
+'埃塞俄比亞' => '衣索比亞',
 '裏勾外連' => '裡勾外連',
 '裏面' => '裡面',
 '分辨率' => '解析度',
@@ -16425,39 +16427,39 @@ $zh2TW = array(
 '瑙魯' => '諾魯',
 '变量' => '變數',
 '科特迪瓦' => '象牙海岸',
-'贝宁' => '貝南',
 '貝寧' => '貝南',
+'贝宁' => '貝南',
 '伯利茲' => '貝里斯',
 '伯利兹' => '貝里斯',
 '買兇' => '買凶',
-'買凶' => '買凶',
 '买凶' => '買凶',
+'買凶' => '買凶',
 '数据库' => '資料庫',
 '信息论' => '資訊理論',
 '奔驰' => '賓士',
 '平治' => '賓士',
 '利比里亚' => '賴比瑞亞',
 '利比里亞' => '賴比瑞亞',
-'莱索托' => '賴索托',
 '萊索托' => '賴索托',
+'莱索托' => '賴索托',
 '软驱' => '軟碟機',
-'软件' => '軟體',
 '軟件' => '軟體',
+'软件' => '軟體',
 '加载' => '載入',
-'津巴布韋' => '辛巴威',
 '津巴布韦' => '辛巴威',
+'津巴布韋' => '辛巴威',
 '词汇' => '辭彙',
-'加納' => '迦納',
 '加纳' => '迦納',
-'追兇' => '追凶',
+'加納' => '迦納',
 '追凶' => '追凶',
+'追兇' => '追凶',
 '這裏' => '這裡',
+'逞凶鬥狠' => '逞凶鬥狠',
 '逞兇鬥狠' => '逞凶鬥狠',
 '逞凶斗狠' => '逞凶鬥狠',
-'逞凶鬥狠' => '逞凶鬥狠',
 '即食麵' => '速食麵',
-'快速面' => '速食麵',
 '方便面' => '速食麵',
+'快速面' => '速食麵',
 '连字号' => '連字號',
 '进制' => '進位',
 '入球' => '進球',
@@ -16473,8 +16475,8 @@ $zh2TW = array(
 '鈎心鬥角' => '鉤心鬥角',
 '锎' => '鉲',
 '写保护' => '防寫',
-'阿拉伯聯合酋長國' => '阿拉伯聯合大公國',
 '阿拉伯联合酋长国' => '阿拉伯聯合大公國',
+'阿拉伯聯合酋長國' => '阿拉伯聯合大公國',
 '噪声' => '雜訊',
 '脱机' => '離線',
 '雪裏紅' => '雪裡紅',
@@ -16484,8 +16486,8 @@ $zh2TW = array(
 '异步' => '非同步',
 '声卡' => '音效卡',
 '缺省' => '預設',
-'頒佈' => '頒布',
 '颁布' => '頒布',
+'頒佈' => '頒布',
 '領域裏' => '領域裡',
 '头球' => '頭槌',
 '粒入球' => '顆進球',
@@ -16503,30 +16505,30 @@ $zh2TW = array(
 );
 
 $zh2HK = array(
-'505线' => '505綫',
 '505線' => '505綫',
-'507线' => '507綫',
+'505线' => '505綫',
 '507線' => '507綫',
-'610线' => '610綫',
+'507线' => '507綫',
 '610線' => '610綫',
+'610线' => '610綫',
 '614P線' => '614P綫',
 '614P线' => '614P綫',
-'614線' => '614綫',
 '614线' => '614綫',
+'614線' => '614綫',
 '615P線' => '615P綫',
 '615P线' => '615P綫',
 '615线' => '615綫',
 '615線' => '615綫',
-'705線' => '705綫',
 '705线' => '705綫',
-'706線' => '706綫',
+'705線' => '705綫',
 '706线' => '706綫',
+'706線' => '706綫',
 '751P線' => '751P綫',
 '751P线' => '751P綫',
-'751线' => '751綫',
 '751線' => '751綫',
-'761P線' => '761P綫',
+'751线' => '751綫',
 '761P线' => '761P綫',
+'761P線' => '761P綫',
 '“' => '「',
 '”' => '」',
 '‘' => '『',
@@ -16551,8 +16553,8 @@ $zh2HK = array(
 '乘著錄' => '乘著錄',
 '葉門' => '也門',
 '二極體' => '二極管',
-'因特网' => '互聯網',
 '網際網路' => '互聯網',
+'因特网' => '互聯網',
 '亮著' => '亮着',
 '亮著作' => '亮著作',
 '亮著名' => '亮著名',
@@ -16606,8 +16608,8 @@ $zh2HK = array(
 '住著述' => '住著述',
 '住著錄' => '住著錄',
 '維德角' => '佛得角',
-'作品里' => '作品裏',
 '作品裡' => '作品裏',
+'作品里' => '作品裏',
 '來著' => '來着',
 '來著作' => '來著作',
 '來著名' => '來著名',
@@ -16763,8 +16765,8 @@ $zh2HK = array(
 '動著者' => '動著者',
 '動著述' => '動著述',
 '動著錄' => '動著錄',
-'北環線' => '北環綫',
 '北环线' => '北環綫',
+'北環線' => '北環綫',
 '医院里' => '医院裏',
 '波札那' => '博茨瓦納',
 '珍妮弗·卡普里亚蒂' => '卡佩雅蒂',
@@ -16777,13 +16779,13 @@ $zh2HK = array(
 '印著述' => '印著述',
 '印著錄' => '印著錄',
 '瓜地馬拉' => '危地馬拉',
+'泡麵' => '即食麵',
 '方便面' => '即食麵',
-'速食麵' => '即食麵',
 '快速面' => '即食麵',
-'麵' => '即食麵',
+'速食麵' => '即食麵',
 '厄瓜多' => '厄瓜多爾',
-'厄瓜多尔' => '厄瓜多爾',
 '厄瓜多爾' => '厄瓜多爾',
+'厄瓜多尔' => '厄瓜多爾',
 '厄利垂亞' => '厄立特里亞',
 '去著' => '去着',
 '去著作' => '去著作',
@@ -16932,8 +16934,8 @@ $zh2HK = array(
 '坐著述' => '坐著述',
 '坐著錄' => '坐著錄',
 '坦尚尼亞' => '坦桑尼亞',
-'衣索比亞' => '埃塞俄比亞',
 '衣索匹亞' => '埃塞俄比亞',
+'衣索比亞' => '埃塞俄比亞',
 '吉里巴斯' => '基里巴斯',
 '塞普勒斯' => '塞浦路斯',
 '塞席爾' => '塞舌爾',
@@ -16945,10 +16947,10 @@ $zh2HK = array(
 '壓著者' => '壓著者',
 '壓著述' => '壓著述',
 '壓著錄' => '壓著錄',
-'夏天裡' => '夏天裏',
 '夏天里' => '夏天裏',
-'夏日裡' => '夏日裏',
+'夏天裡' => '夏天裏',
 '夏日里' => '夏日裏',
+'夏日裡' => '夏日裏',
 '夢著' => '夢着',
 '夢著作' => '夢著作',
 '夢著名' => '夢著名',
@@ -17002,8 +17004,8 @@ $zh2HK = array(
 '定著述' => '定著述',
 '定著錄' => '定著錄',
 '沃尓沃' => '富豪',
-'寒假里' => '寒假裏',
 '寒假裡' => '寒假裏',
+'寒假里' => '寒假裏',
 '寫著' => '寫着',
 '寫著作' => '寫著作',
 '寫著名' => '寫著名',
@@ -17012,10 +17014,10 @@ $zh2HK = array(
 '寫著者' => '寫著者',
 '寫著述' => '寫著述',
 '寫著錄' => '寫著錄',
-'將軍澳線' => '將軍澳綫',
 '将军澳线' => '將軍澳綫',
-'å°\88輯裡' => 'å°\88輯è£\8f',
+'å°\87è»\8dæ¾³ç·\9a' => 'å°\87è»\8d澳綫',
 '专辑里' => '專輯裏',
+'專輯裡' => '專輯裏',
 '尋著' => '尋着',
 '尋著作' => '尋著作',
 '尋著名' => '尋著名',
@@ -17032,12 +17034,12 @@ $zh2HK = array(
 '對著者' => '對著者',
 '對著述' => '對著述',
 '對著錄' => '對著錄',
-'尼日利亞' => '尼日利亞',
-'尼日利亚' => '尼日利亞',
 '奈及利亞' => '尼日利亞',
-'尼日' => '尼日爾',
-'尼日爾' => '尼日爾',
+'尼日利亚' => '尼日利亞',
+'尼日利亞' => '尼日利亞',
 '尼日尔' => '尼日爾',
+'尼日爾' => '尼日爾',
+'尼日' => '尼日爾',
 '展著' => '展着',
 '展著作' => '展著作',
 '展著名' => '展著名',
@@ -17080,8 +17082,8 @@ $zh2HK = array(
 '賓士' => '平治',
 '年代里' => '年代裏',
 '年代裡' => '年代裏',
-'干着' => '幹着',
 '幹著' => '幹着',
+'干着' => '幹着',
 '幾內亞比索' => '幾內亞比紹',
 '康著' => '康着',
 '康著作' => '康著作',
@@ -17124,8 +17126,8 @@ $zh2HK = array(
 '心著者' => '心著者',
 '心著述' => '心著述',
 '心著錄' => '心著錄',
-'心里' => '心裏',
 '心裡' => '心裏',
+'心里' => '心裏',
 '忍著' => '忍着',
 '忍著作' => '忍著作',
 '忍著名' => '忍著名',
@@ -17232,10 +17234,10 @@ $zh2HK = array(
 '戰著者' => '戰著者',
 '戰著述' => '戰著述',
 '戰著錄' => '戰著錄',
-'戏里' => '戲裏',
 '戲裡' => '戲裏',
-'狄安娜' => '戴安娜',
+'戏里' => '戲裏',
 '黛安娜' => '戴安娜',
+'狄安娜' => '戴安娜',
 '戴著' => '戴着',
 '戴著作' => '戴著作',
 '戴著名' => '戴著名',
@@ -17468,8 +17470,8 @@ $zh2HK = array(
 '斯洛維尼亞' => '斯洛文尼亞',
 '新著龍虎門' => '新著龍虎門',
 '紐西蘭' => '新西蘭',
-'日子裡' => '日子裏',
 '日子里' => '日子裏',
+'日子裡' => '日子裏',
 '昂著' => '昂着',
 '昂著作' => '昂著作',
 '昂著名' => '昂著名',
@@ -17486,12 +17488,12 @@ $zh2HK = array(
 '映著者' => '映著者',
 '映著述' => '映著述',
 '映著錄' => '映著錄',
-'春假裡' => '春假裏',
 '春假里' => '春假裏',
-'æ\98¥å¤©é\87\8c' => 'æ\98¥å¤©裏',
+'æ\98¥å\81\87裡' => 'æ\98¥å\81\87裏',
 '春天裡' => '春天裏',
-'春日里' => '春日裏',
+'春天里' => '春天裏',
 '春日裡' => '春日裏',
+'春日里' => '春日裏',
 '时间里' => '時間裏',
 '時間裡' => '時間裏',
 '晃著' => '晃着',
@@ -17501,8 +17503,8 @@ $zh2HK = array(
 '晃著者' => '晃著者',
 '晃著述' => '晃著述',
 '晃著錄' => '晃著錄',
-'暑假裡' => '暑假裏',
 '暑假里' => '暑假裏',
+'暑假裡' => '暑假裏',
 '暗著' => '暗着',
 '暗著作' => '暗著作',
 '暗著名' => '暗著名',
@@ -17546,8 +17548,8 @@ $zh2HK = array(
 '村子裡' => '村子裏',
 '东涌线' => '東涌綫',
 '東涌線' => '東涌綫',
-'东铁线' => '東鐵綫',
 '東鐵線' => '東鐵綫',
+'东铁线' => '東鐵綫',
 '枕著' => '枕着',
 '枕著作' => '枕著作',
 '枕著名' => '枕著名',
@@ -17565,8 +17567,8 @@ $zh2HK = array(
 '梳著者' => '梳著者',
 '梳著述' => '梳著述',
 '梳著錄' => '梳著錄',
-'森林里' => '森林裏',
 '森林裡' => '森林裏',
+'森林里' => '森林裏',
 '棺材裡' => '棺材裏',
 '棺材里' => '棺材裏',
 '榴蓮' => '榴槤',
@@ -17581,8 +17583,8 @@ $zh2HK = array(
 '樂著錄' => '樂著錄',
 '寶獅' => '標致',
 '標誌著' => '標誌着',
-'机场快线' => '機場快綫',
 '機場快線' => '機場快綫',
+'机场快线' => '機場快綫',
 '機器人' => '機械人',
 '机器人' => '機械人',
 '历史里' => '歷史裏',
@@ -17615,12 +17617,12 @@ $zh2HK = array(
 '沉著者' => '沉著者',
 '沉著述' => '沉著述',
 '沉著錄' => '沉著錄',
-'沙中線' => '沙中綫',
 '沙中线' => '沙中綫',
+'沙中線' => '沙中綫',
 '沙地阿拉伯' => '沙特阿拉伯',
 '沙烏地阿拉伯' => '沙特阿拉伯',
-'沙田至中环线' => '沙田至中環綫',
 '沙田至中環線' => '沙田至中環綫',
+'沙田至中环线' => '沙田至中環綫',
 '马拉特·萨芬' => '沙芬',
 '沿著' => '沿着',
 '沿著作' => '沿著作',
@@ -17641,8 +17643,8 @@ $zh2HK = array(
 '活著者' => '活著者',
 '活著述' => '活著述',
 '活著錄' => '活著錄',
-'移动电话' => '流動電話',
 '行動電話' => '流動電話',
+'移动电话' => '流動電話',
 '流著' => '流着',
 '流著作' => '流著作',
 '流著名' => '流著名',
@@ -17724,10 +17726,10 @@ $zh2HK = array(
 '无线剧集' => '無綫劇集',
 '無線收費' => '無綫收費',
 '无线收费' => '無綫收費',
-'無線節目' => '無綫節目',
 '无线节目' => '無綫節目',
-'無線電視' => '無綫電視',
+'無線節目' => '無綫節目',
 '无线电视' => '無綫電視',
+'無線電視' => '無綫電視',
 '菸' => '煙',
 '照著' => '照着',
 '照著作' => '照著作',
@@ -17780,8 +17782,8 @@ $zh2HK = array(
 '猜著者' => '猜著者',
 '猜著述' => '猜著述',
 '猜著錄' => '猜著錄',
-'獄裡' => '獄裏',
 '狱里' => '獄裏',
+'獄裡' => '獄裏',
 '獨著' => '獨着',
 '獨著作' => '獨著作',
 '獨著名' => '獨著名',
@@ -17844,12 +17846,12 @@ $zh2HK = array(
 '疑著錄' => '疑著錄',
 '发布' => '發佈',
 '發布' => '發佈',
-'百科里' => '百科裏',
 '百科裡' => '百科裏',
+'百科里' => '百科裏',
 '計程車' => '的士',
 '出租车' => '的士',
-'皮裡陽秋' => '皮裏陽秋',
 '皮里阳秋' => '皮裏陽秋',
+'皮裡陽秋' => '皮裏陽秋',
 '皺著' => '皺着',
 '皺著作' => '皺著作',
 '皺著名' => '皺著名',
@@ -17959,8 +17961,8 @@ $zh2HK = array(
 '瞪著錄' => '瞪著錄',
 '簡訊' => '短訊',
 '短信' => '短訊',
-'硬體' => '硬件',
 '硬件' => '硬件',
+'硬體' => '硬件',
 '福斯' => '福士',
 '福著' => '福着',
 '福著作' => '福著作',
@@ -17970,12 +17972,12 @@ $zh2HK = array(
 '福著者' => '福著者',
 '福著述' => '福著述',
 '福著錄' => '福著錄',
-'秋假里' => '秋假裏',
 '秋假裡' => '秋假裏',
-'ç§\8b天é\87\8c' => 'ç§\8b天裏',
+'ç§\8bå\81\87é\87\8c' => 'ç§\8bå\81\87裏',
 '秋天裡' => '秋天裏',
-'秋日裡' => '秋日裏',
+'秋天里' => '秋天裏',
 '秋日里' => '秋日裏',
+'秋日裡' => '秋日裏',
 '葛摩' => '科摩羅',
 '捷豹' => '積架',
 '空著' => '空着',
@@ -17986,8 +17988,8 @@ $zh2HK = array(
 '空著者' => '空著者',
 '空著述' => '空著述',
 '空著錄' => '空著錄',
-'航天飞机' => '穿梭機',
 '太空梭' => '穿梭機',
+'航天飞机' => '穿梭機',
 '穿著' => '穿着',
 '穿著作' => '穿著作',
 '穿著名' => '穿著名',
@@ -18099,8 +18101,8 @@ $zh2HK = array(
 '考著者' => '考著者',
 '考著述' => '考著述',
 '考著錄' => '考著錄',
-'聖克里斯多福及尼維斯' => '聖吉斯納域斯',
 '圣基茨和尼维斯' => '聖吉斯納域斯',
+'聖克里斯多福及尼維斯' => '聖吉斯納域斯',
 '聖文森及格瑞那丁' => '聖文森特和格林納丁斯',
 '聖露西亞' => '聖盧西亞',
 '聖馬利諾' => '聖馬力諾',
@@ -18116,8 +18118,8 @@ $zh2HK = array(
 '聽著錄' => '聽著錄',
 '肚里' => '肚裏',
 '肚裡' => '肚裏',
-'肯亞' => '肯雅',
 '肯尼亚' => '肯雅',
+'肯亞' => '肯雅',
 '背著' => '背着',
 '背著作' => '背著作',
 '背著名' => '背著名',
@@ -18161,8 +18163,8 @@ $zh2HK = array(
 '苦著錄' => '苦著錄',
 '苦里' => '苦裏',
 '苦裡' => '苦裏',
-'荃灣線' => '荃灣綫',
 '荃湾线' => '荃灣綫',
+'荃灣線' => '荃灣綫',
 '莫三比克' => '莫桑比克',
 '賴索托' => '萊索托',
 '馬自達' => '萬事得',
@@ -18228,8 +18230,8 @@ $zh2HK = array(
 '衣著錄' => '衣著錄',
 '裡勾外連' => '裏勾外連',
 '里勾外连' => '裏勾外連',
-'裡面' => '裏面',
 '里面' => '裏面',
+'裡面' => '裏面',
 '裝著' => '裝着',
 '裝著作' => '裝著作',
 '裝著名' => '裝著名',
@@ -18246,8 +18248,8 @@ $zh2HK = array(
 '裹著者' => '裹著者',
 '裹著述' => '裹著述',
 '裹著錄' => '裹著錄',
-'西鐵線' => '西鐵綫',
 '西铁线' => '西鐵綫',
+'西鐵線' => '西鐵綫',
 '見著' => '見着',
 '見著作' => '見著作',
 '見著名' => '見著名',
@@ -18441,8 +18443,8 @@ $zh2HK = array(
 '辦著錄' => '辦著錄',
 '近角聪信' => '近角聰信',
 '近角聰信' => '近角聰信',
-'迪士尼線' => '迪士尼綫',
 '迪士尼线' => '迪士尼綫',
+'迪士尼線' => '迪士尼綫',
 '迫著' => '迫着',
 '追著' => '追着',
 '追著作' => '追著作',
@@ -18526,8 +18528,8 @@ $zh2HK = array(
 '醯醢' => '醯醢',
 '醯醬' => '醯醬',
 '醯酱' => '醯醬',
-'醯雞' => '醯雞',
 '醯鸡' => '醯雞',
+'醯雞' => '醯雞',
 '釀著' => '釀着',
 '釀著作' => '釀著作',
 '釀著名' => '釀著名',
@@ -18640,15 +18642,15 @@ $zh2HK = array(
 '雜著述' => '雜著述',
 '雜著錄' => '雜著錄',
 '冰淇淋' => '雪糕',
-'雪裡紅' => '雪裏紅',
 '雪里红' => '雪裏紅',
+'雪裡紅' => '雪裏紅',
 '雪裡蕻' => '雪裏蕻',
 '雪里蕻' => '雪裏蕻',
 '靠著' => '靠着',
 '靠著作' => '靠著作',
 '靠著名' => '靠著名',
-'靠著称' => '靠著稱',
 '靠著稱' => '靠著稱',
+'靠著称' => '靠著稱',
 '靠著者' => '靠著者',
 '靠著述' => '靠著述',
 '靠著錄' => '靠著錄',
@@ -18677,10 +18679,10 @@ $zh2HK = array(
 '順著者' => '順著者',
 '順著述' => '順著述',
 '順著錄' => '順著錄',
-'颁布' => '頒佈',
 '頒布' => '頒佈',
-'é¢\86å\9f\9fé\87\8c' => 'é \98å\9f\9fè£\8f',
+'é¢\81å¸\83' => 'é \92ä½\88',
 '領域裡' => '領域裏',
+'领域里' => '領域裏',
 '領著' => '領着',
 '領著作' => '領著作',
 '領著名' => '領著名',
@@ -18697,8 +18699,8 @@ $zh2HK = array(
 '飄著者' => '飄著者',
 '飄著述' => '飄著述',
 '飄著錄' => '飄著錄',
-'馆里' => '館裏',
 '館裡' => '館裏',
+'馆里' => '館裏',
 '馬爾地夫' => '馬爾代夫',
 '馬利共和國' => '馬里共和國',
 '土豆' => '馬鈴薯',
@@ -18776,8 +18778,8 @@ $zh2HK = array(
 '點著者' => '點著者',
 '點著述' => '點著述',
 '點著錄' => '點著錄',
-'点里' => '點裏',
 '點裡' => '點裏',
+'点里' => '點裏',
 );
 
 $zh2CN = array(
@@ -18803,8 +18805,8 @@ $zh2CN = array(
 '互聯網' => '互联网',
 '互動式' => '交互式',
 '人工智慧' => '人工智能',
-'甚麼' => '什么',
 '甚麽' => '什么',
+'甚麼' => '什么',
 '乙太網' => '以太网',
 '優先順序' => '优先级',
 '感測' => '传感',
@@ -18849,16 +18851,16 @@ $zh2CN = array(
 '华乐街' => '华乐街',
 '波札那' => '博茨瓦纳',
 '盧安達' => '卢旺达',
-'衛生' => '卫生',
 '衞生' => '卫生',
+'衛生' => '卫生',
 '瓜地馬拉' => '危地马拉',
 '厄瓜多' => '厄瓜多尔',
-'厄瓜多尔' => '厄瓜多尔',
 '厄瓜多爾' => '厄瓜多尔',
+'厄瓜多尔' => '厄瓜多尔',
 '厄利垂亞' => '厄立特里亚',
 '變數' => '变量',
-'桌球' => '台球',
 '撞球' => '台球',
+'桌球' => '台球',
 '吉布地' => '吉布提',
 '哈薩克' => '哈萨克斯坦',
 '哥斯大黎加' => '哥斯达黎加',
@@ -18867,8 +18869,8 @@ $zh2CN = array(
 '吐瓦魯' => '图瓦卢',
 '土庫曼' => '土库曼斯坦',
 '聖露西亞' => '圣卢西亚',
-'聖克里斯多福及尼維斯' => '圣基茨和尼维斯',
 '聖吉斯納域斯' => '圣基茨和尼维斯',
+'聖克里斯多福及尼維斯' => '圣基茨和尼维斯',
 '聖文森及格瑞那丁' => '圣文森特和格林纳丁斯',
 '聖馬利諾' => '圣马力诺',
 '蓋亞那' => '圭亚那',
@@ -18888,11 +18890,11 @@ $zh2CN = array(
 '福斯' => '大众',
 '大衛碧咸' => '大卫·贝克汉姆',
 '頭槌' => '头球',
-'平治' => '奔驰',
 '賓士' => '奔驰',
+'平治' => '奔驰',
 '忌廉' => '奶油',
-'字元會' => '字元会',
 '字元会' => '字元会',
+'字元會' => '字元会',
 '字元濟' => '字元济',
 '字元济' => '字元济',
 '字型大小' => '字号',
@@ -18900,18 +18902,18 @@ $zh2CN = array(
 '欄位' => '字段',
 '字母' => '字母',
 '字元' => '字符',
-'位元組' => '字节',
 '字節' => '字节',
+'位元組' => '字节',
 '存檔' => '存盘',
 '安地卡及巴布達' => '安提瓜和巴布达',
 '巨集' => '宏',
 '寬頻' => '宽带',
 '定址' => '寻址',
+'奈及利亞' => '尼日利亚',
 '尼日利亞' => '尼日利亚',
 '尼日利亚' => '尼日利亚',
-'奈及利亞' => '尼日利亚',
-'尼日尔' => '尼日尔',
 '尼日爾' => '尼日尔',
+'尼日尔' => '尼日尔',
 '章節附註' => '尾注',
 '區域網' => '局域网',
 '巴貝多' => '巴巴多斯',
@@ -18925,8 +18927,8 @@ $zh2CN = array(
 '蒲隆地' => '布隆迪',
 '希特拉' => '希特勒',
 '帛琉' => '帕劳',
-'平治之亂' => '平治之乱',
 '平治之乱' => '平治之乱',
+'平治之亂' => '平治之乱',
 '非同步' => '异步',
 '迴圈' => '循环',
 '快閃記憶體' => '快闪存储器',
@@ -18937,8 +18939,8 @@ $zh2CN = array(
 '索羅門群島' => '所罗门群岛',
 '打印' => '打印',
 '列印' => '打印',
-'打印機' => '打印机',
 '印表機' => '打印机',
+'打印機' => '打印机',
 '射門' => '打门',
 '掃瞄器' => '扫瞄仪',
 '括弧' => '括号',
@@ -18952,12 +18954,12 @@ $zh2CN = array(
 '斯洛維尼亞' => '斯洛文尼亚',
 '紐西蘭' => '新西兰',
 '即食麵' => '方便面',
-'速食麵' => '方便面',
 '快速面' => '方便面',
 '泡麵' => '方便面',
+'速食麵' => '方便面',
 '伺服器' => '服务器',
-'機器人' => '机器人',
 '機械人' => '机器人',
+'機器人' => '机器人',
 '許可權' => '权限',
 '寶獅' => '标志',
 '格瑞那達' => '格林纳达',
@@ -18986,16 +18988,16 @@ $zh2CN = array(
 '狗隻' => '犬只',
 '卡佩雅蒂' => '珍妮弗·卡普里亚蒂',
 '諾魯' => '瑙鲁',
-'溫納圖' => '瓦努阿图',
 '萬那杜' => '瓦努阿图',
+'溫納圖' => '瓦努阿图',
 '碟片' => '盘片',
-'簡訊' => '短信',
 '短訊' => '短信',
-'ç\9f½å¡µ' => 'ç\9f½å°\98',
+'ç°¡è¨\8a' => 'ç\9f­ä¿¡',
 '矽尘' => '矽尘',
+'矽塵' => '矽尘',
 '矽肺' => '矽肺',
-'矽鋼' => '矽钢',
 '矽钢' => '矽钢',
+'矽鋼' => '矽钢',
 '矽' => '硅',
 '矽片' => '硅片',
 '矽谷' => '硅谷',
@@ -19005,8 +19007,8 @@ $zh2CN = array(
 '磁軌' => '磁道',
 '葛摩' => '科摩罗',
 '象牙海岸' => '科特迪瓦',
-'流動電話' => '移动电话',
 '行動電話' => '移动电话',
+'流動電話' => '移动电话',
 '程式控制' => '程控',
 '突尼西亞' => '突尼斯',
 '谐星' => '笑星',
@@ -19018,11 +19020,11 @@ $zh2CN = array(
 '網路' => '网络',
 '網絡' => '网络',
 '寮國' => '老挝',
-'肯亞' => '肯尼亚',
 '肯雅' => '肯尼亚',
+'肯亞' => '肯尼亚',
 '單車' => '自行车',
-'穿梭機' => '航天飞机',
 '太空梭' => '航天飞机',
+'穿梭機' => '航天飞机',
 '節慶' => '节日',
 '晶元' => '芯片',
 '晶片' => '芯片',
@@ -19038,8 +19040,8 @@ $zh2CN = array(
 '尚比亞' => '赞比亚',
 '绑紧跳' => '蹦极跳',
 '笨豬跳' => '蹦极跳',
-'軟件' => '软件',
 '軟體' => '软件',
+'軟件' => '软件',
 '軟碟機' => '软驱',
 '米高奧雲' => '迈克尔·欧文',
 '舒麥加' => '迈克尔·舒马赫',
@@ -19069,15 +19071,15 @@ $zh2SG = array(
 '民乐' => '华乐',
 '夜校' => '夜学',
 '房价' => '屋价',
-'麵' => '快速面',
+'即食麵' => '快速面',
 '速食麵' => '快速面',
+'泡麵' => '快速面',
 '方便面' => '快速面',
-'即食麵' => '快速面',
-'散紙' => '散钱',
 '零钱' => '散钱',
+'散紙' => '散钱',
 '榴莲' => '榴梿',
 '榴蓮' => '榴梿',
-'蹦极跳' => '绑紧跳',
 '笨豬跳' => '绑紧跳',
+'蹦极跳' => '绑紧跳',
 '笑星' => '谐星',
 );
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.',
                );
index feb6d7b..6c42601 100644 (file)
@@ -107,9 +107,20 @@ class EnhancedChangesList extends ChangesList {
                }
 
                $cacheEntry = $this->cacheEntryFactory->newFromRecentChange( $baseRC, $watched );
+               $this->addCacheEntry( $cacheEntry );
 
-               # Put accumulated information into the cache, for later display
-               # Page moves go on their own line
+               wfProfileOut( __METHOD__ );
+
+               return $ret;
+       }
+
+       /**
+        * Put accumulated information into the cache, for later display.
+        * Page moves go on their own line.
+        *
+        * @param RCCacheEntry $cacheEntry
+        */
+       protected function addCacheEntry( RCCacheEntry $cacheEntry ) {
                $title = $cacheEntry->getTitle();
                $secureName = $title->getPrefixedDBkey();
 
@@ -132,10 +143,6 @@ class EnhancedChangesList extends ChangesList {
 
                        array_push( $this->rc_cache[$secureName], $cacheEntry );
                }
-
-               wfProfileOut( __METHOD__ );
-
-               return $ret;
        }
 
        /**
index 072aa12..7705c10 100644 (file)
@@ -331,11 +331,23 @@ class RecentChange {
        public function notifyRCFeeds() {
                global $wgRCFeeds;
 
+               $performer = $this->getPerformer();
+
                foreach ( $wgRCFeeds as $feed ) {
-                       $omitBots = isset( $feed['omit_bots'] ) ? $feed['omit_bots'] : false;
+                       $feed += array(
+                               'omit_bots' => false,
+                               'omit_anon' => false,
+                               'omit_user' => false,
+                               'omit_minor' => false,
+                               'omit_patrolled' => false,
+                       );
 
                        if (
-                               ( $omitBots && $this->mAttribs['rc_bot'] ) ||
+                               ( $feed['omit_bots'] && $this->mAttribs['rc_bot'] ) ||
+                               ( $feed['omit_anon'] && $performer->isAnon() ) ||
+                               ( $feed['omit_user'] && !$performer->isAnon() ) ||
+                               ( $feed['omit_minor'] && $this->mAttribs['rc_minor'] ) ||
+                               ( $feed['omit_patrolled'] && $this->mAttribs['rc_patrolled'] ) ||
                                $this->mAttribs['rc_type'] == RC_EXTERNAL
                        ) {
                                continue;
index 5db814d..68a7f46 100644 (file)
@@ -421,7 +421,7 @@ class RedisConnRef {
                $conn->clearLastError();
                $res = $conn->evalSha( $sha1, $params, $numKeys );
                // If we got a permission error reply that means that (a) we are not in
-               // multi()/pipeline() and (b) some connection problem likely occured. If
+               // multi()/pipeline() and (b) some connection problem likely occurred. If
                // the password the client gave was just wrong, an exception should have
                // been thrown back in getConnection() previously.
                if ( preg_match( '/^ERR operation not permitted\b/', $conn->getLastError() ) ) {
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 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 79232e5..6286f94 100644 (file)
@@ -329,7 +329,7 @@ class LinksUpdate extends SqlDataUpdate {
                                $toField = $prefix . '_to';
                        }
                        if ( count( $deletions ) ) {
-                               $where[] = "$toField IN (" . $this->mDb->makeList( array_keys( $deletions ) ) . ')';
+                               $where[$toField] = array_keys( $deletions );
                        } else {
                                $where = false;
                        }
index f77a4eb..dd3f351 100644 (file)
@@ -84,7 +84,7 @@ class DifferenceEngine extends ContextSource {
         */
        public $enableDebugComment = false;
 
-       /** @var bool  If true, line X is not displayed when X is 1, for example
+       /** @var bool If true, line X is not displayed when X is 1, for example
         *    to increase readability and conserve space with many small diffs.
         */
        protected $mReducedLineNumbers = false;
@@ -970,8 +970,10 @@ class DifferenceEngine extends ContextSource {
                        $newRev = $this->mNewRev;
                }
 
-               $nEdits = $this->mNewPage->countRevisionsBetween( $oldRev, $newRev );
-               if ( $nEdits > 0 ) {
+               // Sanity: don't show the notice if too many rows must be scanned
+               // @TODO: show some special message for that case
+               $nEdits = $this->mNewPage->countRevisionsBetween( $oldRev, $newRev, 1000 );
+               if ( $nEdits > 0 && $nEdits <= 1000 ) {
                        $limit = 100; // use diff-multi-manyusers if too many users
                        $users = $this->mNewPage->getAuthorsBetween( $oldRev, $newRev, $limit );
                        $numUsers = count( $users );
index 4e48932..35ac60f 100644 (file)
@@ -252,8 +252,9 @@ class ForeignAPIRepo extends FileRepo {
         * @param string $name
         * @param int $width
         * @param int $height
-        * @param null $result
+        * @param array $result Out parameter that will be changed by the function.
         * @param string $otherParams
+        *
         * @return bool
         */
        function getThumbUrl( $name, $width = -1, $height = -1, &$result = null, $otherParams = '' ) {
index 7a9e617..eb55e82 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
@@ -1989,7 +1990,7 @@ class LocalFileDeleteBatch {
                        $res = $dbw->select(
                                'oldimage',
                                array( 'oi_archive_name', 'oi_sha1' ),
-                               'oi_archive_name IN (' . $dbw->makeList( array_keys( $oldRels ) ) . ')',
+                               array( 'oi_archive_name' => array_keys( $oldRels ) ),
                                __METHOD__
                        );
 
@@ -2090,7 +2091,7 @@ class LocalFileDeleteBatch {
                        $concat = $dbw->buildConcat( array( "oi_sha1", $encExt ) );
                        $where = array(
                                'oi_name' => $this->file->getName(),
-                               'oi_archive_name IN (' . $dbw->makeList( array_keys( $oldRels ) ) . ')' );
+                               'oi_archive_name' => array_keys( $oldRels ) );
                        $dbw->insertSelect( 'filearchive', 'oldimage',
                                array(
                                        'fa_storage_group' => $encGroup,
@@ -2153,7 +2154,7 @@ class LocalFileDeleteBatch {
                        $res = $dbw->select( 'oldimage',
                                array( 'oi_archive_name' ),
                                array( 'oi_name' => $this->file->getName(),
-                                       'oi_archive_name IN (' . $dbw->makeList( array_keys( $oldRels ) ) . ')',
+                                       'oi_archive_name' => array_keys( $oldRels ),
                                        $dbw->bitAnd( 'oi_deleted', File::DELETED_FILE ) => File::DELETED_FILE ),
                                __METHOD__ );
 
@@ -2320,7 +2321,7 @@ class LocalFileRestoreBatch {
                $conditions = array( 'fa_name' => $this->file->getName() );
 
                if ( !$this->all ) {
-                       $conditions[] = 'fa_id IN (' . $dbw->makeList( $this->ids ) . ')';
+                       $conditions['fa_id'] = $this->ids;
                }
 
                $result = $dbw->select(
@@ -2505,7 +2506,7 @@ class LocalFileRestoreBatch {
 
                if ( $deleteIds ) {
                        $dbw->delete( 'filearchive',
-                               array( 'fa_id IN (' . $dbw->makeList( $deleteIds ) . ')' ),
+                               array( 'fa_id' => $deleteIds ),
                                __METHOD__ );
                }
 
index 4f501f7..bb42d53 100644 (file)
@@ -16,7 +16,7 @@ class HTMLSelectAndOtherField extends HTMLSelectField {
                } elseif ( array_key_exists( 'other-message', $params ) ) {
                        $params['other'] = wfMessage( $params['other-message'] )->plain();
                } else {
-                       $params['other'] = null;
+                       $params['other'] = wfMessage( 'htmlform-selectorother-other' )->plain();
                }
 
                parent::__construct( $params );
index 3f2e2cb..5223cd3 100644 (file)
@@ -155,10 +155,11 @@ abstract class DatabaseUpdater {
        }
 
        /**
-        * @throws MWException
         * @param DatabaseBase $db
         * @param bool $shared
-        * @param null $maintenance
+        * @param Maintenance $maintenance
+        *
+        * @throws MWException
         * @return DatabaseUpdater
         */
        public static function newForDB( &$db, $shared = false, $maintenance = null ) {
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 79fdc99..42672ca 100644 (file)
@@ -44,13 +44,14 @@ class WebInstaller extends Installer {
        /**
         * Cached session array.
         *
-        * @var array
+        * @var array[]
         */
        protected $session;
 
        /**
         * Captured PHP error text. Temporary.
-        * @var array
+        *
+        * @var string[]
         */
        protected $phpErrors;
 
@@ -61,7 +62,8 @@ class WebInstaller extends Installer {
         *    * Add it to this WebInstaller::$pageSequence property
         *    * Add a "config-page-<name>" message
         *    * Add a "WebInstaller_<name>" class
-        * @var array
+        *
+        * @var string[]
         */
        public $pageSequence = array(
                'Language',
@@ -78,7 +80,8 @@ class WebInstaller extends Installer {
 
        /**
         * Out of sequence pages, selectable by the user at any time.
-        * @var array
+        *
+        * @var string[]
         */
        protected $otherPages = array(
                'Restart',
@@ -91,7 +94,8 @@ class WebInstaller extends Installer {
        /**
         * Array of pages which have declared that they have been submitted, have validated
         * their input, and need no further processing.
-        * @var array
+        *
+        * @var bool[]
         */
        protected $happyPages;
 
@@ -99,24 +103,28 @@ class WebInstaller extends Installer {
         * List of "skipped" pages. These are pages that will automatically continue
         * to the next page on any GET request. To avoid breaking the "back" button,
         * they need to be skipped during a back operation.
-        * @var array
+        *
+        * @var bool[]
         */
        protected $skippedPages;
 
        /**
         * Flag indicating that session data may have been lost.
+        *
         * @var bool
         */
        public $showSessionWarning = false;
 
        /**
         * Numeric index of the page we're on
+        *
         * @var int
         */
        protected $tabIndex = 1;
 
        /**
         * Name of the page we're on
+        *
         * @var string
         */
        protected $currentPageName;
@@ -140,9 +148,9 @@ class WebInstaller extends Installer {
        /**
         * Main entry point.
         *
-        * @param array $session initial session array
+        * @param array[] $session initial session array
         *
-        * @return array New session array
+        * @return array[] New session array
         */
        public function execute( array $session ) {
                $this->session = $session;
@@ -396,7 +404,8 @@ class WebInstaller extends Installer {
 
        /**
         * Temporary error handler for session start debugging.
-        * @param $errno
+        *
+        * @param int $errno Unused
         * @param string $errstr
         */
        public function errorHandler( $errno, $errstr ) {
@@ -406,7 +415,7 @@ class WebInstaller extends Installer {
        /**
         * Clean up from execute()
         *
-        * @return array
+        * @return array[]
         */
        public function finish() {
                $this->output->output();
@@ -430,7 +439,8 @@ class WebInstaller extends Installer {
        /**
         * Get a URL for submission back to the same script.
         *
-        * @param array $query
+        * @param string[] $query
+        *
         * @return string
         */
        public function getUrl( $query = array() ) {
@@ -461,8 +471,9 @@ class WebInstaller extends Installer {
         * Get a session variable.
         *
         * @param string $name
-        * @param $default
-        * @return null
+        * @param array $default
+        *
+        * @return array
         */
        public function getSession( $name, $default = null ) {
                if ( !isset( $this->session[$name] ) ) {
@@ -474,6 +485,7 @@ class WebInstaller extends Installer {
 
        /**
         * Set a session variable.
+        *
         * @param string $name Key for the variable
         * @param mixed $value
         */
@@ -483,6 +495,7 @@ class WebInstaller extends Installer {
 
        /**
         * Get the next tabindex attribute value.
+        *
         * @return int
         */
        public function nextTabIndex() {
@@ -770,7 +783,7 @@ class WebInstaller extends Installer {
        /**
         * Get a labelled text box to configure a variable.
         *
-        * @param array $params
+        * @param mixed[] $params
         *    Parameters are:
         *      var:         The variable to be configured (required)
         *      label:       The message name for the label (required)
@@ -817,7 +830,7 @@ class WebInstaller extends Installer {
        /**
         * Get a labelled textarea to configure a variable
         *
-        * @param array $params
+        * @param mixed[] $params
         *    Parameters are:
         *      var:         The variable to be configured (required)
         *      label:       The message name for the label (required)
@@ -866,7 +879,7 @@ class WebInstaller extends Installer {
         * Get a labelled password box to configure a variable.
         *
         * Implements password hiding
-        * @param array $params
+        * @param mixed[] $params
         *    Parameters are:
         *      var:         The variable to be configured (required)
         *      label:       The message name for the label (required)
@@ -895,7 +908,7 @@ class WebInstaller extends Installer {
        /**
         * Get a labelled checkbox to configure a boolean variable.
         *
-        * @param array $params
+        * @param mixed[] $params
         *    Parameters are:
         *      var:         The variable to be configured (required)
         *      label:       The message name for the label (required)
@@ -946,7 +959,7 @@ class WebInstaller extends Installer {
        /**
         * Get a set of labelled radio buttons.
         *
-        * @param array $params
+        * @param mixed[] $params
         *    Parameters are:
         *      var:             The variable to be configured (required)
         *      label:           The message name for the label (required)
@@ -1033,10 +1046,10 @@ class WebInstaller extends Installer {
         * Assumes that variables containing "password" in the name are (potentially
         * fake) passwords.
         *
-        * @param array $varNames
+        * @param string[] $varNames
         * @param string $prefix The prefix added to variables to obtain form names
         *
-        * @return array
+        * @return string[]
         */
        public function setVarsFromRequest( $varNames, $prefix = 'config_' ) {
                $newValues = array();
@@ -1063,7 +1076,8 @@ class WebInstaller extends Installer {
        /**
         * Helper for Installer::docLink()
         *
-        * @param $page
+        * @param string $page
+        *
         * @return string
         */
        protected function getDocUrl( $page ) {
@@ -1079,9 +1093,10 @@ class WebInstaller extends Installer {
        /**
         * Extension tag hook for a documentation link.
         *
-        * @param $linkText
-        * @param $attribs
-        * @param $parser
+        * @param string $linkText
+        * @param string[] $attribs
+        * @param Parser $parser Unused
+        *
         * @return string
         */
        public function docLink( $linkText, $attribs, $parser ) {
@@ -1095,9 +1110,10 @@ class WebInstaller extends Installer {
        /**
         * Helper for "Download LocalSettings" link on WebInstall_Complete
         *
-        * @param $text
-        * @param $attribs
-        * @param $parser
+        * @param string $text Unused
+        * @param string[] $attribs Unused
+        * @param Parser $parser Unused
+        *
         * @return string Html for download link
         */
        public function downloadLinkHook( $text, $attribs, $parser ) {
@@ -1138,7 +1154,11 @@ class WebInstaller extends Installer {
                return parent::envCheckPath();
        }
 
+       /**
+        * @return String
+        */
        protected function envGetDefaultServer() {
                return WebRequest::detectServer();
        }
+
 }
index e05a3d4..7a7f125 100644 (file)
@@ -33,6 +33,7 @@
  * @since 1.17
  */
 class WebInstallerOutput {
+
        /**
         * The WebInstaller object this WebInstallerOutput is used by.
         *
@@ -52,6 +53,9 @@ class WebInstallerOutput {
         */
        private $headerDone = false;
 
+       /**
+        * @var string
+        */
        public $redirectTarget;
 
        /**
@@ -69,27 +73,39 @@ class WebInstallerOutput {
        private $useShortHeader = false;
 
        /**
-        * Constructor.
-        *
-        * @param $parent WebInstaller
+        * @param WebInstaller $parent
         */
        public function __construct( WebInstaller $parent ) {
                $this->parent = $parent;
        }
 
+       /**
+        * @param string $html
+        */
        public function addHTML( $html ) {
                $this->contents .= $html;
                $this->flush();
        }
 
+       /**
+        * @param string $text
+        */
        public function addWikiText( $text ) {
                $this->addHTML( $this->parent->parse( $text ) );
        }
 
+       /**
+        * @param string $html
+        */
        public function addHTMLNoFlush( $html ) {
                $this->contents .= $html;
        }
 
+       /**
+        * @param string $url
+        *
+        * @throws MWException
+        */
        public function redirect( $url ) {
                if ( $this->headerDone ) {
                        throw new MWException( __METHOD__ . ' called after sending headers' );
@@ -110,6 +126,7 @@ class WebInstallerOutput {
         *   and not properly handling such details as media types in module definitions.
         *
         * @param string $dir 'ltr' or 'rtl'
+        *
         * @return String
         */
        public function getCSS( $dir ) {
@@ -192,6 +209,7 @@ class WebInstallerOutput {
 
        /**
         * "<link>" to index.php?css=foobar for the "<head>"
+        *
         * @return String
         */
        private function getCssUrl() {
@@ -236,7 +254,7 @@ class WebInstallerOutput {
        }
 
        /**
-        * @return array
+        * @return string[]
         */
        public function getHeadAttribs() {
                return array(
@@ -247,6 +265,7 @@ class WebInstallerOutput {
 
        /**
         * Get whether the header has been output
+        *
         * @return bool
         */
        public function headerDone() {
@@ -341,7 +360,11 @@ class WebInstallerOutput {
                echo wfMessage( 'config-title', $wgVersion )->escaped();
        }
 
+       /**
+        * @return string
+        */
        public function getJQuery() {
-               return Html::linkedScript( "../resources/jquery/jquery.js" );
+               return Html::linkedScript( "../resources/src/jquery/jquery.js" );
        }
+
 }
index 4bc6cad..3b3473b 100644 (file)
@@ -36,12 +36,13 @@ abstract class WebInstallerPage {
         */
        public $parent;
 
+       /**
+        * @return string
+        */
        abstract public function execute();
 
        /**
-        * Constructor.
-        *
-        * @param $parent WebInstaller
+        * @param WebInstaller $parent
         */
        public function __construct( WebInstaller $parent ) {
                $this->parent = $parent;
@@ -51,12 +52,16 @@ abstract class WebInstallerPage {
         * Is this a slow-running page in the installer? If so, WebInstaller will
         * set_time_limit(0) before calling execute(). Right now this only applies
         * to Install and Upgrade pages
-        * @return bool
+        *
+        * @return bool Always false in this default implementation.
         */
        public function isSlow() {
                return false;
        }
 
+       /**
+        * @param string $html
+        */
        public function addHTML( $html ) {
                $this->parent->output->addHTML( $html );
        }
@@ -124,18 +129,33 @@ abstract class WebInstallerPage {
                $this->addHTML( $s );
        }
 
+       /**
+        * @return string
+        */
        public function getName() {
                return str_replace( 'WebInstaller_', '', get_class( $this ) );
        }
 
+       /**
+        * @return string
+        */
        protected function getId() {
                return array_search( $this->getName(), $this->parent->pageSequence );
        }
 
+       /**
+        * @param string $var
+        *
+        * @return mixed
+        */
        public function getVar( $var ) {
                return $this->parent->getVar( $var );
        }
 
+       /**
+        * @param string $name
+        * @param mixed $value
+        */
        public function setVar( $name, $value ) {
                $this->parent->setVar( $name, $value );
        }
@@ -175,16 +195,21 @@ abstract class WebInstallerPage {
        }
 
        /**
-        * Opposite to startLiveBox()
+        * Opposite to WebInstallerPage::startLiveBox
         */
        protected function endLiveBox() {
                $this->addHTML( '</textarea></div>
 <script>jQuery( "#config-spinner" ).hide()</script>' );
                $this->parent->output->flush();
        }
+
 }
 
 class WebInstaller_Language extends WebInstallerPage {
+
+       /**
+        * @return string|null
+        */
        public function execute() {
                global $wgLang;
                $r = $this->parent->request;
@@ -244,15 +269,18 @@ class WebInstaller_Language extends WebInstallerPage {
                                $this->parent->getHelpBox( 'config-wiki-language-help' ) );
                $this->addHTML( $s );
                $this->endForm( 'continue', false );
+
+               return null;
        }
 
        /**
         * Get a "<select>" for selecting languages.
         *
-        * @param $name
-        * @param $label
-        * @param $selectedCode
-        * @param $helpHtml string
+        * @param string $name
+        * @param string $label
+        * @param string $selectedCode
+        * @param string $helpHtml
+        *
         * @return string
         */
        public function getLanguageSelector( $name, $label, $selectedCode, $helpHtml = '' ) {
@@ -275,9 +303,14 @@ class WebInstaller_Language extends WebInstallerPage {
 
                return $this->parent->label( $label, $name, $s );
        }
+
 }
 
 class WebInstaller_ExistingWiki extends WebInstallerPage {
+
+       /**
+        * @return string
+        */
        public function execute() {
                // If there is no LocalSettings.php, continue to the installer welcome page
                $vars = Installer::getExistingLocalSettings();
@@ -366,6 +399,12 @@ class WebInstaller_ExistingWiki extends WebInstallerPage {
                $this->endForm( 'continue' );
        }
 
+       /**
+        * @param string[] $names
+        * @param mixed[] $vars
+        *
+        * @return Status
+        */
        protected function importVariables( $names, $vars ) {
                $status = Status::newGood();
                foreach ( $names as $name ) {
@@ -380,7 +419,9 @@ class WebInstaller_ExistingWiki extends WebInstallerPage {
 
        /**
         * Initiate an upgrade of the existing database
-        * @param array $vars Variables from LocalSettings.php
+        *
+        * @param mixed[] $vars Variables from LocalSettings.php
+        *
         * @return Status
         */
        protected function handleExistingUpgrade( $vars ) {
@@ -426,10 +467,14 @@ class WebInstaller_ExistingWiki extends WebInstallerPage {
 
                return $status;
        }
+
 }
 
 class WebInstaller_Welcome extends WebInstallerPage {
 
+       /**
+        * @return string
+        */
        public function execute() {
                if ( $this->parent->request->wasPosted() ) {
                        if ( $this->getVar( '_Environment' ) ) {
@@ -451,11 +496,13 @@ class WebInstaller_Welcome extends WebInstallerPage {
 
                return '';
        }
+
 }
 
 class WebInstaller_DBConnect extends WebInstallerPage {
+
        /**
-        * @return string|void When string, "skip" or "continue"
+        * @return string|null When string, "skip" or "continue"
         */
        public function execute() {
                if ( $this->getVar( '_ExistingDBSettings' ) ) {
@@ -529,8 +576,13 @@ class WebInstaller_DBConnect extends WebInstallerPage {
 
                $this->addHTML( $this->parent->label( 'config-db-type', false, $types ) . $settings );
                $this->endForm();
+
+               return null;
        }
 
+       /**
+        * @return Status
+        */
        public function submit() {
                $r = $this->parent->request;
                $type = $r->getVal( 'DBType' );
@@ -545,13 +597,21 @@ class WebInstaller_DBConnect extends WebInstallerPage {
 
                return $installer->submitConnectForm();
        }
+
 }
 
 class WebInstaller_Upgrade extends WebInstallerPage {
+
+       /**
+        * @return bool Always true.
+        */
        public function isSlow() {
                return true;
        }
 
+       /**
+        * @return string|null
+        */
        public function execute() {
                if ( $this->getVar( '_UpgradeDone' ) ) {
                        // Allow regeneration of LocalSettings.php, unless we are working
@@ -603,6 +663,8 @@ class WebInstaller_Upgrade extends WebInstallerPage {
                $this->addHTML( $this->parent->getInfoBox(
                        wfMessage( 'config-can-upgrade', $GLOBALS['wgVersion'] )->plain() ) );
                $this->endForm();
+
+               return null;
        }
 
        public function showDoneMessage() {
@@ -626,10 +688,14 @@ class WebInstaller_Upgrade extends WebInstallerPage {
                $this->parent->restoreLinkPopups();
                $this->endForm( $regenerate ? 'regenerate' : false, false );
        }
+
 }
 
 class WebInstaller_DBSettings extends WebInstallerPage {
 
+       /**
+        * @return string|null
+        */
        public function execute() {
                $installer = $this->parent->getDBInstaller( $this->getVar( 'wgDBtype' ) );
 
@@ -653,11 +719,17 @@ class WebInstaller_DBSettings extends WebInstallerPage {
                $this->startForm();
                $this->addHTML( $form );
                $this->endForm();
+
+               return null;
        }
+
 }
 
 class WebInstaller_Name extends WebInstallerPage {
 
+       /**
+        * @return string
+        */
        public function execute() {
                $r = $this->parent->request;
                if ( $r->wasPosted() ) {
@@ -751,6 +823,9 @@ class WebInstaller_Name extends WebInstallerPage {
                return 'output';
        }
 
+       /**
+        * @return bool
+        */
        public function submit() {
                $retVal = true;
                $this->parent->setVarsFromRequest( array( 'wgSitename', '_NamespaceType',
@@ -863,9 +938,14 @@ class WebInstaller_Name extends WebInstallerPage {
 
                return $retVal;
        }
+
 }
 
 class WebInstaller_Options extends WebInstallerPage {
+
+       /**
+        * @return string|null
+        */
        public function execute() {
                if ( $this->getVar( '_SkipOptional' ) == 'skip' ) {
                        return 'skip';
@@ -1049,6 +1129,8 @@ class WebInstaller_Options extends WebInstallerPage {
                        $this->getFieldSetEnd()
                );
                $this->endForm();
+
+               return null;
        }
 
        /**
@@ -1077,6 +1159,9 @@ class WebInstaller_Options extends WebInstallerPage {
                return $iframeUrl;
        }
 
+       /**
+        * @return string
+        */
        public function getCCChooser() {
                $iframeAttribs = array(
                        'class' => 'config-cc-iframe',
@@ -1098,6 +1183,9 @@ class WebInstaller_Options extends WebInstallerPage {
                        "</div>\n";
        }
 
+       /**
+        * @return string
+        */
        public function getCCDoneBox() {
                $js = "parent.document.getElementById('config-cc-wrapper').style.height = '$1';";
                // If you change this height, also change it in config.css
@@ -1137,6 +1225,9 @@ class WebInstaller_Options extends WebInstallerPage {
                $this->addHTML( $this->getCCDoneBox() );
        }
 
+       /**
+        * @return bool
+        */
        public function submit() {
                $this->parent->setVarsFromRequest( array( '_RightsProfile', '_LicenseCode',
                        'wgEnableEmail', 'wgPasswordSender', 'wgEnableUploads', 'wgLogo',
@@ -1144,8 +1235,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 +1248,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,
@@ -1217,13 +1307,21 @@ class WebInstaller_Options extends WebInstallerPage {
 
                return true;
        }
+
 }
 
 class WebInstaller_Install extends WebInstallerPage {
+
+       /**
+        * @return bool Always true.
+        */
        public function isSlow() {
                return true;
        }
 
+       /**
+        * @return string|bool
+        */
        public function execute() {
                if ( $this->getVar( '_UpgradeDone' ) ) {
                        return 'skip';
@@ -1252,6 +1350,9 @@ class WebInstaller_Install extends WebInstallerPage {
                return true;
        }
 
+       /**
+        * @param string $step
+        */
        public function startStage( $step ) {
                // Messages: config-install-database, config-install-tables, config-install-interwiki,
                // config-install-stats, config-install-keys, config-install-sysop, config-install-mainpage
@@ -1264,8 +1365,8 @@ class WebInstaller_Install extends WebInstallerPage {
        }
 
        /**
-        * @param $step
-        * @param $status Status
+        * @param string $step
+        * @param Status $status
         */
        public function endStage( $step, $status ) {
                if ( $step == 'extension-tables' ) {
@@ -1281,9 +1382,11 @@ class WebInstaller_Install extends WebInstallerPage {
                        $this->parent->showStatusBox( $status );
                }
        }
+
 }
 
 class WebInstaller_Complete extends WebInstallerPage {
+
        public function execute() {
                // Pop up a dialog box, to make it difficult for the user to forget
                // to download the file
@@ -1317,10 +1420,14 @@ class WebInstaller_Complete extends WebInstallerPage {
                $this->parent->restoreLinkPopups();
                $this->endForm( false, false );
        }
+
 }
 
 class WebInstaller_Restart extends WebInstallerPage {
 
+       /**
+        * @return string|null
+        */
        public function execute() {
                $r = $this->parent->request;
                if ( $r->wasPosted() ) {
@@ -1336,11 +1443,17 @@ class WebInstaller_Restart extends WebInstallerPage {
                $s = $this->parent->getWarningBox( wfMessage( 'config-help-restart' )->plain() );
                $this->addHTML( $s );
                $this->endForm( 'restart' );
+
+               return null;
        }
+
 }
 
 abstract class WebInstaller_Document extends WebInstallerPage {
 
+       /**
+        * @return string
+        */
        abstract protected function getFileName();
 
        public function execute() {
@@ -1351,6 +1464,9 @@ abstract class WebInstaller_Document extends WebInstallerPage {
                $this->endForm( false );
        }
 
+       /**
+        * @return string
+        */
        public function getFileContents() {
                $file = __DIR__ . '/../../' . $this->getFileName();
                if ( !file_exists( $file ) ) {
@@ -1359,15 +1475,26 @@ abstract class WebInstaller_Document extends WebInstallerPage {
 
                return file_get_contents( $file );
        }
+
 }
 
 class WebInstaller_Readme extends WebInstaller_Document {
+
+       /**
+        * @return string
+        */
        protected function getFileName() {
                return 'README';
        }
+
 }
 
 class WebInstaller_ReleaseNotes extends WebInstaller_Document {
+
+       /**
+        * @throws MWException
+        * @return string
+        */
        protected function getFileName() {
                global $wgVersion;
 
@@ -1377,16 +1504,27 @@ class WebInstaller_ReleaseNotes extends WebInstaller_Document {
 
                return 'RELEASE-NOTES-' . $result[1] . '.' . $result[2];
        }
+
 }
 
 class WebInstaller_UpgradeDoc extends WebInstaller_Document {
+
+       /**
+        * @return string
+        */
        protected function getFileName() {
                return 'UPGRADE';
        }
+
 }
 
 class WebInstaller_Copying extends WebInstaller_Document {
+
+       /**
+        * @return string
+        */
        protected function getFileName() {
                return 'COPYING';
        }
+
 }
index 45149c5..de27766 100644 (file)
@@ -76,7 +76,7 @@
     "config-gd": "Found GD graphics library built-in.\nImage thumbnailing will be enabled if you enable uploads.",
     "config-no-scaling": "Could not find GD library or ImageMagick.\nImage thumbnailing will be disabled.",
     "config-no-uri": "<strong>Error:</strong> Could not determine the current URI.\nInstallation aborted.",
-    "config-no-cli-uri": "<strong>Warning:</strong> No --scriptpath specified, using default: <code>$1</code>.",
+    "config-no-cli-uri": "<strong>Warning:</strong> No <code>--scriptpath</code> specified, using default: <code>$1</code>.",
     "config-using-server": "Using server name \"<nowiki>$1</nowiki>\".",
     "config-using-uri": "Using server URL \"<nowiki>$1$2</nowiki>\".",
     "config-uploads-not-safe": "<strong>Warning:</strong> Your default directory for uploads <code>$1</code> is vulnerable to arbitrary scripts execution.\nAlthough MediaWiki checks all uploaded files for security threats, it is highly recommended to [//www.mediawiki.org/wiki/Manual:Security#Upload_security close this security vulnerability] before enabling uploads.",
@@ -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 \"{{int:config-db-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.",
     "config-header-sqlite": "SQLite settings",
     "config-header-oracle": "Oracle settings",
     "config-header-mssql": "Microsoft SQL Server settings",
-    "config-invalid-db-type": "Invalid database type",
-    "config-missing-db-name": "You must enter a value for \"Database name\"",
-    "config-missing-db-host": "You must enter a value for \"Database host\"",
-    "config-missing-db-server-oracle": "You must enter a value for \"Database TNS\"",
-    "config-invalid-db-server-oracle": "Invalid database TNS \"$1\".\nUse either \"TNS Name\" or an \"Easy Connect\" string ([http://docs.oracle.com/cd/E11882_01/network.112/e10836/naming.htm Oracle Naming Methods])",
+    "config-invalid-db-type": "Invalid database type.",
+    "config-missing-db-name": "You must enter a value for \"{{int:config-db-name}}\".",
+    "config-missing-db-host": "You must enter a value for \"{{int:config-db-host}}\".",
+    "config-missing-db-server-oracle": "You must enter a value for \"{{int:config-db-host-oracle}}\".",
+    "config-invalid-db-server-oracle": "Invalid database TNS \"$1\".\nUse either \"TNS Name\" or an \"Easy Connect\" string ([http://docs.oracle.com/cd/E11882_01/network.112/e10836/naming.htm Oracle Naming Methods]).",
     "config-invalid-db-name": "Invalid database name \"$1\".\nUse only ASCII letters (a-z, A-Z), numbers (0-9), underscores (_) and hyphens (-).",
     "config-invalid-db-prefix": "Invalid database prefix \"$1\".\nUse only ASCII letters (a-z, A-Z), numbers (0-9), underscores (_) and hyphens (-).",
     "config-connection-error": "$1.\n\nCheck the host, username and password and try again.",
     "config-extension-link": "Did you know that your wiki supports [//www.mediawiki.org/wiki/Manual:Extensions extensions]?\n\nYou can browse [//www.mediawiki.org/wiki/Category:Extensions_by_category extensions by category] or the [//www.mediawiki.org/wiki/Extension_Matrix Extension Matrix] to see the full list of extensions.",
     "mainpagetext": "<strong>MediaWiki has been successfully installed.</strong>",
     "mainpagedocfooter": "Consult the [//meta.wikimedia.org/wiki/Help:Contents User's Guide] for information on using the wiki software.\n\n== Getting started ==\n* [//www.mediawiki.org/wiki/Manual:Configuration_settings Configuration settings list]\n* [//www.mediawiki.org/wiki/Manual:FAQ MediaWiki FAQ]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list]\n* [//www.mediawiki.org/wiki/Localisation#Translation_resources Localise MediaWiki for your language]"
-}
\ No newline at end of file
+}
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 2d7103c..9b13aea 100644 (file)
@@ -304,11 +304,11 @@ abstract class JobQueue {
         *
         * @param Job|array $jobs A single job or an array of Jobs
         * @param int $flags Bitfield (supports JobQueue::QOS_ATOMIC)
-        * @return bool Returns false on failure
+        * @return void
         * @throws JobQueueError
         */
        final public function push( $jobs, $flags = 0 ) {
-               return $this->batchPush( is_array( $jobs ) ? $jobs : array( $jobs ), $flags );
+               $this->batchPush( is_array( $jobs ) ? $jobs : array( $jobs ), $flags );
        }
 
        /**
@@ -318,8 +318,8 @@ abstract class JobQueue {
         *
         * @param array $jobs List of Jobs
         * @param int $flags Bitfield (supports JobQueue::QOS_ATOMIC)
+        * @return void
         * @throws MWException
-        * @return bool Returns false on failure
         */
        final public function batchPush( array $jobs, $flags = 0 ) {
                if ( !count( $jobs ) ) {
@@ -337,17 +337,14 @@ abstract class JobQueue {
                }
 
                wfProfileIn( __METHOD__ );
-               $ok = $this->doBatchPush( $jobs, $flags );
+               $this->doBatchPush( $jobs, $flags );
                wfProfileOut( __METHOD__ );
-
-               return $ok;
        }
 
        /**
         * @see JobQueue::batchPush()
         * @param array $jobs
         * @param $flags
-        * @return bool
         */
        abstract protected function doBatchPush( array $jobs, $flags );
 
@@ -399,24 +396,21 @@ abstract class JobQueue {
         * Outside callers should use JobQueueGroup::ack() instead of this function.
         *
         * @param Job $job
+        * @return void
         * @throws MWException
-        * @return bool
         */
        final public function ack( Job $job ) {
                if ( $job->getType() !== $this->type ) {
                        throw new MWException( "Got '{$job->getType()}' job; expected '{$this->type}'." );
                }
                wfProfileIn( __METHOD__ );
-               $ok = $this->doAck( $job );
+               $this->doAck( $job );
                wfProfileOut( __METHOD__ );
-
-               return $ok;
        }
 
        /**
         * @see JobQueue::ack()
         * @param Job $job
-        * @return bool
         */
        abstract protected function doAck( Job $job );
 
@@ -539,22 +533,19 @@ abstract class JobQueue {
        /**
         * Deleted all unclaimed and delayed jobs from the queue
         *
-        * @return bool Success
         * @throws JobQueueError
         * @since 1.22
+        * @return void
         */
        final public function delete() {
                wfProfileIn( __METHOD__ );
-               $res = $this->doDelete();
+               $this->doDelete();
                wfProfileOut( __METHOD__ );
-
-               return $res;
        }
 
        /**
         * @see JobQueue::delete()
         * @throws MWException
-        * @return bool Success
         */
        protected function doDelete() {
                throw new MWException( "This method is not implemented." );
index 9502148..f2599ae 100644 (file)
@@ -265,7 +265,8 @@ class JobQueueFederated extends JobQueue {
                        /** @var JobQueue $queue */
                        $queue = $this->partitionQueues[$partition];
                        try {
-                               $ok = $queue->doBatchPush( $jobBatch, $flags | self::QOS_ATOMIC );
+                               $ok = true;
+                               $queue->doBatchPush( $jobBatch, $flags | self::QOS_ATOMIC );
                        } catch ( JobQueueError $e ) {
                                $ok = false;
                                MWExceptionHandler::logException( $e );
@@ -287,7 +288,8 @@ class JobQueueFederated extends JobQueue {
                        $partition = ArrayUtils::pickRandom( $partitionRing->getLocationWeights() );
                        $queue = $this->partitionQueues[$partition];
                        try {
-                               $ok = $queue->doBatchPush( $jobBatch, $flags | self::QOS_ATOMIC );
+                               $ok = true;
+                               $queue->doBatchPush( $jobBatch, $flags | self::QOS_ATOMIC );
                        } catch ( JobQueueError $e ) {
                                $ok = false;
                                MWExceptionHandler::logException( $e );
index 90742ce..b1dfe14 100644 (file)
@@ -254,6 +254,31 @@ class JobQueueGroup {
                return array_diff( $this->getQueueTypes(), $wgJobTypesExcludedFromDefaultQueue );
        }
 
+       /**
+        * Check if there are any queues with jobs (this is cached)
+        *
+        * @param integer $type JobQueueGroup::TYPE_* constant
+        * @return bool
+        * @since 1.23
+        */
+       public function queuesHaveJobs( $type = self::TYPE_ANY ) {
+               global $wgMemc;
+
+               $key = wfMemcKey( 'jobqueue', 'queueshavejobs', $type );
+
+               $value = $wgMemc->get( $key );
+               if ( $value === false ) {
+                       $queues = $this->getQueuesWithJobs();
+                       if ( $type == self::TYPE_DEFAULT ) {
+                               $queues = array_intersect( $queues, $this->getDefaultQueueTypes() );
+                       }
+                       $value = count( $queues ) ? 'true' : 'false';
+                       $wgMemc->add( $key, $value, 15 );
+               }
+
+               return ( $value === 'true' );
+       }
+
        /**
         * Get the list of job types that have non-empty queues
         *
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 a7c5dc0..4d1e72c 100644 (file)
@@ -40,7 +40,7 @@ class HTMLCacheUpdateJob extends Job {
        }
 
        function run() {
-               global $wgUpdateRowsPerJob, $wgUpdateRowsPerQuery, $wgMaxBacklinksInvalidate;
+               global $wgUpdateRowsPerJob, $wgUpdateRowsPerQuery;
 
                static $expected = array( 'recursive', 'pages' ); // new jobs have one of these
 
@@ -57,14 +57,6 @@ class HTMLCacheUpdateJob extends Job {
 
                // Job to purge all (or a range of) backlink pages for a page
                if ( !empty( $this->params['recursive'] ) ) {
-                       // @TODO: try to use delayed jobs if possible?
-                       if ( !isset( $this->params['range'] ) && $wgMaxBacklinksInvalidate !== false ) {
-                               $numRows = $this->title->getBacklinkCache()->getNumLinks(
-                                       $this->params['table'], $wgMaxBacklinksInvalidate );
-                               if ( $numRows > $wgMaxBacklinksInvalidate ) {
-                                       return true;
-                               }
-                       }
                        // Convert this into no more than $wgUpdateRowsPerJob HTMLCacheUpdateJob per-title
                        // jobs and possibly a recursive HTMLCacheUpdateJob job for the rest of the backlinks
                        $jobs = BacklinkJobUtils::partitionBacklinkJob(
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 00cd257..340e7f4 100644 (file)
@@ -211,7 +211,8 @@ class MultiHttpClient {
                        $ch = $handles[$index];
                        curl_multi_remove_handle( $chm, $ch );
                        if ( curl_errno( $ch ) !== 0 ) {
-                               $req['error'] = "(curl error: " . curl_errno( $ch ) . ") " . curl_error( $ch );
+                               $req['response']['error'] = "(curl error: " .
+                                       curl_errno( $ch ) . ") " . curl_error( $ch );
                        }
                        // For convenience with the list() operator
                        $req['response'][0] = $req['response']['code'];
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 e27e28a..d33fc91 100644 (file)
@@ -42,7 +42,7 @@ class LogPager extends ReverseChronologicalPager {
        /** @var string */
        private $typeCGI = '';
 
-       /** @var LogEventsList  */
+       /** @var LogEventsList */
        public $mLogEventsList;
 
        /**
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 8fa39fa..02f2438 100644 (file)
@@ -91,10 +91,11 @@ class CoreParserFunctions {
        }
 
        /**
-        * @param $parser Parser
-        * @param $date
-        * @param null $defaultPref
-        * @return mixed|string
+        * @param Parser $parser
+        * @param string $date
+        * @param string $defaultPref
+        *
+        * @return string
         */
        static function formatDate( $parser, $date, $defaultPref = null ) {
                $lang = $parser->getFunctionLang();
index 0a69b04..d10841f 100644 (file)
@@ -143,7 +143,8 @@ class DateFormatter {
         * @param string $preference User preference
         * @param string $text Text to reformat
         * @param array $options can contain 'linked' and/or 'match-whole'
-        * @return mixed|String
+        *
+        * @return string
         */
        function reformat( $preference, $text, $options = array( 'linked' ) ) {
                $linked = in_array( 'linked', $options );
index d7584ca..2d9078d 100644 (file)
@@ -591,7 +591,7 @@ class Parser {
         * If $frame is not provided, then template variables (e.g., {{{1}}}) within $text are not expanded
         *
         * @param string $text text extension wants to have parsed
-        * @param $frame PPFrame: The frame to use for expanding any template variables
+        * @param PPFrame $frame The frame to use for expanding any template variables
         *
         * @return string
         */
@@ -628,8 +628,8 @@ class Parser {
         * hook.
         *
         * @param string $text text to be expanded
-        * @param $frame PPFrame: The frame to use for expanding any template variables
-        * @return String
+        * @param PPFrame $frame The frame to use for expanding any template variables
+        * @return string
         * @since 1.19
         */
        public function recursivePreprocess( $text, $frame = false ) {
@@ -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 );
 
@@ -676,7 +680,7 @@ class Parser {
         * Set the current user.
         * Should only be used when doing pre-save transform.
         *
-        * @param $user Mixed: User object or null (to reset)
+        * @param User|null $user User object or null (to reset)
         */
        function setUser( $user ) {
                $this->mUser = $user;
@@ -741,7 +745,7 @@ class Parser {
        /**
         * Set the output type
         *
-        * @param $ot Integer: new value
+        * @param int $ot new value
         */
        function setOutputType( $ot ) {
                $this->mOutputType = $ot;
@@ -884,11 +888,11 @@ class Parser {
         *     '<element param="x">tag content</element>' ) )
         * @endcode
         *
-        * @param array $elements list of element names. Comments are always extracted.
+        * @param array $elements List of element names. Comments are always extracted.
         * @param string $text Source text string.
         * @param array $matches Out parameter, Array: extracted tags
-        * @param $uniq_prefix string
-        * @return String: stripped text
+        * @param string $uniq_prefix
+        * @return string Stripped text
         */
        public static function extractTagsAndParams( $elements, $text, &$matches, $uniq_prefix = '' ) {
                static $n = 1;
@@ -1817,9 +1821,9 @@ class Parser {
        /**
         * Process [[ ]] wikilinks
         *
-        * @param $s string
+        * @param string $s
         *
-        * @return String: processed text
+        * @return string Processed text
         *
         * @private
         */
@@ -2171,12 +2175,12 @@ class Parser {
         * breaking URLs in the following text without breaking trails on the
         * wiki links, it's been made into a horrible function.
         *
-        * @param $nt Title
-        * @param $text String
-        * @param array $query or String
-        * @param $trail String
-        * @param $prefix String
-        * @return String: HTML-wikitext mix oh yuck
+        * @param Title $nt
+        * @param string $text
+        * @param array|string $query
+        * @param string $trail
+        * @param string $prefix
+        * @return string HTML-wikitext mix oh yuck
         */
        function makeKnownLinkHolder( $nt, $text = '', $query = array(), $trail = '', $prefix = '' ) {
                list( $inside, $trail ) = Linker::splitTrail( $trail );
@@ -2200,8 +2204,8 @@ class Parser {
         * Not needed quite as much as it used to be since free links are a bit
         * more sensible these days. But bracketed links are still an issue.
         *
-        * @param string $text more-or-less HTML
-        * @return String: less-or-more HTML with NOPARSE bits
+        * @param string $text More-or-less HTML
+        * @return string Less-or-more HTML with NOPARSE bits
         */
        function armorLinks( $text ) {
                return preg_replace( '/\b((?i)' . $this->mUrlProtocols . ')/',
@@ -2220,9 +2224,9 @@ class Parser {
        /**
         * Handle link to subpage if necessary
         *
-        * @param string $target the source of the link
-        * @param &$text String: the link text, modified as necessary
-        * @return string the full name of the link
+        * @param string $target The source of the link
+        * @param string &$text The link text, modified as necessary
+        * @return string The full name of the link
         * @private
         */
        function maybeDoSubpageLink( $target, &$text ) {
@@ -2353,10 +2357,10 @@ class Parser {
        /**
         * Make lists from lines starting with ':', '*', '#', etc. (DBL)
         *
-        * @param $text String
-        * @param $linestart Boolean: whether or not this is at the start of a line.
+        * @param string $text
+        * @param bool $linestart Whether or not this is at the start of a line.
         * @private
-        * @return string the lists rendered as HTML
+        * @return string The lists rendered as HTML
         */
        function doBlockLevels( $text, $linestart ) {
                wfProfileIn( __METHOD__ );
@@ -3069,9 +3073,9 @@ class Parser {
         * This is the ghost of replace_variables().
         *
         * @param string $text The text to parse
-        * @param $flags Integer: bitwise combination of:
-        *          self::PTD_FOR_INCLUSION    Handle "<noinclude>" and "<includeonly>" as if the text is being
-        *                                     included. Default is to assume a direct page view.
+        * @param int $flags Bitwise combination of:
+        *   - self::PTD_FOR_INCLUSION: Handle "<noinclude>" and "<includeonly>" as if the text is being
+        *     included. Default is to assume a direct page view.
         *
         * The generated DOM tree must depend only on the input text and the flags.
         * The DOM tree must be the same in OT_HTML and OT_WIKI mode, to avoid a regression of bug 4899.
@@ -3217,13 +3221,13 @@ class Parser {
         * Return the text of a template, after recursively
         * replacing any variables or templates within the template.
         *
-        * @param array $piece the parts of the template
+        * @param array $piece The parts of the template
         *  $piece['title']: the title, i.e. the part before the |
         *  $piece['parts']: the parameter array
         *  $piece['lineStart']: whether the brace was at the start of a line
-        * @param $frame PPFrame The current frame, contains template arguments
+        * @param PPFrame $frame The current frame, contains template arguments
         * @throws MWException
-        * @return String: the text of the template
+        * @return string The text of the template
         * @private
         */
        function braceSubstitution( $piece, $frame ) {
@@ -3729,8 +3733,8 @@ class Parser {
         * Static function to get a template
         * Can be overridden via ParserOptions::setTemplateCallback().
         *
-        * @param $title  Title
-        * @param $parser Parser
+        * @param Title $title
+        * @param Parser $parser
         *
         * @return array
         */
@@ -4065,9 +4069,9 @@ class Parser {
        /**
         * Increment an include size counter
         *
-        * @param string $type the type of expansion
-        * @param $size Integer: the size of the text
-        * @return Boolean: false if this inclusion would take it over the maximum, true otherwise
+        * @param string $type The type of expansion
+        * @param int $size The size of the text
+        * @return bool false if this inclusion would take it over the maximum, true otherwise
         */
        function incrementIncludeSize( $type, $size ) {
                if ( $this->mIncludeSizes[$type] + $size > $this->mOptions->getMaxIncludeSize() ) {
@@ -4081,7 +4085,7 @@ class Parser {
        /**
         * Increment the expensive function count
         *
-        * @return Boolean: false if the limit has been exceeded
+        * @return bool false if the limit has been exceeded
         */
        function incrementExpensiveFunctionCount() {
                $this->mExpensiveFunctionCount++;
@@ -4155,8 +4159,8 @@ class Parser {
         * $wgTrackingCategories. That way they will be listed on
         * Special:TrackingCategories.
         *
-        * @param string $msg message key
-        * @return Boolean: whether the addition was successful
+        * @param string $msg Message key
+        * @return bool Whether the addition was successful
         */
        public function addTrackingCategory( $msg ) {
                if ( $this->mTitle->getNamespace() === NS_SPECIAL ) {
@@ -4574,12 +4578,12 @@ class Parser {
         * Transform wiki markup when saving a page by doing "\r\n" -> "\n"
         * conversion, substitting signatures, {{subst:}} templates, etc.
         *
-        * @param string $text the text to transform
-        * @param $title Title: the Title object for the current article
-        * @param $user User: the User object describing the current user
-        * @param $options ParserOptions: parsing options
-        * @param $clearState Boolean: whether to clear the parser state first
-        * @return String: the altered wiki markup
+        * @param string $text The text to transform
+        * @param Title $title The Title object for the current article
+        * @param User $user The User object describing the current user
+        * @param ParserOptions $options Parsing options
+        * @param bool $clearState Whether to clear the parser state first
+        * @return string The altered wiki markup
         */
        public function preSaveTransform( $text, Title $title, User $user, ParserOptions $options, $clearState = true ) {
                $this->startParse( $title, $options, self::OT_WIKI, $clearState );
@@ -4749,9 +4753,9 @@ class Parser {
         * 1) Strip ~~~, ~~~~ and ~~~~~ out of signatures @see cleanSigInSig
         * 2) Substitute all transclusions
         *
-        * @param $text String
+        * @param string $text
         * @param bool $parsing Whether we're cleaning (preferences save) or parsing
-        * @return String: signature text
+        * @return string Signature text
         */
        public function cleanSig( $text, $parsing = false ) {
                if ( !$parsing ) {
@@ -4786,8 +4790,8 @@ class Parser {
        /**
         * Strip ~~~, ~~~~ and ~~~~~ out of signatures
         *
-        * @param $text String
-        * @return String: signature text with /~{3,5}/ removed
+        * @param string $text
+        * @return string Signature text with /~{3,5}/ removed
         */
        public static function cleanSigInSig( $text ) {
                $text = preg_replace( '/~{3,5}/', '', $text );
@@ -4825,10 +4829,10 @@ class Parser {
        /**
         * Wrapper for preprocess()
         *
-        * @param string $text the text to preprocess
-        * @param $options ParserOptions: options
-        * @param $title Title object or null to use $wgTitle
-        * @return String
+        * @param string $text The text to preprocess
+        * @param ParserOptions $options Options
+        * @param Title|null $title Title object or null to use $wgTitle
+        * @return string
         */
        public function transformMsg( $text, $options, $title = null ) {
                static $executing = false;
@@ -4871,10 +4875,10 @@ class Parser {
         * this interface, as it is not documented and injudicious use could smash
         * private variables.**
         *
-        * @param $tag Mixed: the tag to use, e.g. 'hook' for "<hook>"
-        * @param $callback Mixed: the callback function (and object) to use for the tag
+        * @param string $tag The tag to use, e.g. 'hook' for "<hook>"
+        * @param mixed $callback The callback function (and object) to use for the tag
         * @throws MWException
-        * @return Mixed|null The old value of the mTagHooks array associated with the hook
+        * @return mixed|null The old value of the mTagHooks array associated with the hook
         */
        public function setHook( $tag, $callback ) {
                $tag = strtolower( $tag );
@@ -4902,10 +4906,10 @@ class Parser {
         * @since 1.10
         * @todo better document or deprecate this
         *
-        * @param $tag Mixed: the tag to use, e.g. 'hook' for "<hook>"
-        * @param $callback Mixed: the callback function (and object) to use for the tag
+        * @param string $tag The tag to use, e.g. 'hook' for "<hook>"
+        * @param mixed $callback The callback function (and object) to use for the tag
         * @throws MWException
-        * @return Mixed|null The old value of the mTagHooks array associated with the hook
+        * @return mixed|null The old value of the mTagHooks array associated with the hook
         */
        function setTransparentTagHook( $tag, $callback ) {
                $tag = strtolower( $tag );
@@ -4944,8 +4948,8 @@ class Parser {
         *   isHTML                    The returned text is HTML, armour it against wikitext transformation
         *
         * @param string $id The magic word ID
-        * @param $callback Mixed: the callback function (and object) to use
-        * @param $flags Integer: a combination of the following flags:
+        * @param mixed $callback The callback function (and object) to use
+        * @param int $flags A combination of the following flags:
         *     SFH_NO_HASH   No leading hash, i.e. {{plural:...}} instead of {{#if:...}}
         *
         *     SFH_OBJECT_ARGS   Pass the template arguments as PPNode objects instead of text. This
@@ -5601,10 +5605,10 @@ class Parser {
         * string. If $text is the empty string and section 0 is replaced, $newText is
         * returned.
         *
-        * @param string $mode one of "get" or "replace"
-        * @param string $newText replacement text for section data.
-        * @return String: for "get", the extracted section text.
-        *                 for "replace", the whole page with the section replaced.
+        * @param string $mode One of "get" or "replace"
+        * @param string $newText Replacement text for section data.
+        * @return string For "get", the extracted section text.
+        *   for "replace", the whole page with the section replaced.
         */
        private function extractSections( $text, $section, $mode, $newText = '' ) {
                global $wgTitle; # not generally used but removes an ugly failure mode
@@ -5736,10 +5740,10 @@ class Parser {
         * specified by $section has been replaced with $text. If the target
         * section does not exist, $oldtext is returned unchanged.
         *
-        * @param string $oldtext former text of the article
-        * @param int $section section identifier
-        * @param string $text replacing text
-        * @return String: modified text
+        * @param string $oldtext Former text of the article
+        * @param int $section Section identifier
+        * @param string $text Replacing text
+        * @return string Modified text
         */
        public function replaceSection( $oldtext, $section, $text ) {
                return $this->extractSections( $oldtext, $section, "replace", $text );
@@ -5748,7 +5752,7 @@ class Parser {
        /**
         * Get the ID of the revision we are parsing
         *
-        * @return Mixed: integer or null
+        * @return int|null
         */
        function getRevisionId() {
                return $this->mRevisionId;
@@ -5801,7 +5805,7 @@ class Parser {
        /**
         * Get the name of the user that edited the last revision
         *
-        * @return String: user name
+        * @return string User name
         */
        function getRevisionUser() {
                if ( is_null( $this->mRevisionUser ) ) {
index 4c7084e..ff74f2a 100644 (file)
@@ -125,9 +125,9 @@ class ParserCache {
         *
         * @todo Document parameter $useOutdated
         *
-        * @param $article     Article
-        * @param $popts       ParserOptions
-        * @param $useOutdated Boolean (default true)
+        * @param Article $article
+        * @param ParserOptions $popts
+        * @param bool $useOutdated (default true)
         * @return bool|mixed|string
         */
        public function getKey( $article, $popts, $useOutdated = true ) {
@@ -171,9 +171,9 @@ class ParserCache {
         * Retrieve the ParserOutput from ParserCache.
         * false if not found or outdated.
         *
-        * @param $article     Article
-        * @param $popts       ParserOptions
-        * @param $useOutdated Boolean (default false)
+        * @param Article $article
+        * @param ParserOptions $popts
+        * @param bool $useOutdated (default false)
         *
         * @return ParserOutput|bool False on failure
         */
index 7c6dde6..edd4911 100644 (file)
@@ -286,7 +286,7 @@ class ParserOptions {
        /**
         * Same as getUserLangObj() but returns a string instead.
         *
-        * @return String   Language code
+        * @return String Language code
         * @since 1.17
         */
        function getUserLang() {
@@ -478,8 +478,8 @@ class ParserOptions {
         * settings.
         *
         * @since 1.17
-        * @param $forOptions Array
-        * @param $title Title: used to get the content language of the page (since r97636)
+        * @param array $forOptions
+        * @param Title $title Used to get the content language of the page (since r97636)
         * @return string Page rendering hash
         */
        public function optionsHash( $forOptions, $title = null ) {
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 6331a30..36f4bd4 100644 (file)
@@ -123,6 +123,12 @@ class ProfilerSimple extends Profiler {
                }
        }
 
+       public function getRawData() {
+               // Calling the method of the parent class results in fatal error.
+               // @todo Implement this correctly.
+               return array();
+       }
+
        public function getFunctionReport() {
                /* Implement in output subclasses */
                return '';
index b2fb902..77659f6 100644 (file)
@@ -795,9 +795,11 @@ class ResourceLoader {
                                                $scripts = $module->getScriptURLsForDebug( $context );
                                        } else {
                                                $scripts = $module->getScript( $context );
-                                               if ( is_string( $scripts ) && strlen( $scripts ) && substr( $scripts, -1 ) !== ';' ) {
-                                                       // bug 27054: Append semicolon to prevent weird bugs
-                                                       // caused by files not terminating their statements right
+                                               // rtrim() because there are usually a few line breaks after the last ';'.
+                                               // A new line at EOF, a new line added by ResourceLoaderFileModule::readScriptFiles, etc.
+                                               if ( is_string( $scripts ) && strlen( $scripts ) && substr( rtrim( $scripts ), -1 ) !== ';' ) {
+                                                       // Append semicolon to prevent weird bugs caused by files not
+                                                       // terminating their statements right (bug 27054)
                                                        $scripts .= ";\n";
                                                }
                                        }
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 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 dd6bec2..f739d3b 100644 (file)
@@ -97,7 +97,8 @@ class ActiveUsersPager extends UsersPager {
                        'qcc_type' => 'activeusers',
                        'qcc_namespace' => NS_USER,
                        'user_name = qcc_title',
-                       'rc_user_text = qcc_title'
+                       'rc_user_text = qcc_title',
+                       'rc_type != ' . $dbr->addQuotes( RC_EXTERNAL ) // Don't count wikidata.
                );
                if ( $this->requestedUser != '' ) {
                        $conds[] = 'qcc_title >= ' . $dbr->addQuotes( $this->requestedUser );
@@ -340,6 +341,7 @@ class SpecialActiveUsers extends SpecialPage {
                        array( 'rc_user_text', 'lastedittime' => 'MAX(rc_timestamp)' ),
                        array(
                                'rc_user > 0', // actual accounts
+                               'rc_type != ' . $dbw->addQuotes( RC_EXTERNAL ), // no wikidata
                                'rc_log_type IS NULL OR rc_log_type != ' . $dbw->addQuotes( 'newusers' ),
                                'rc_timestamp >= ' . $dbw->addQuotes( $dbw->timestamp( $sTimestamp ) ),
                                'rc_timestamp <= ' . $dbw->addQuotes( $dbw->timestamp( $eTimestamp ) )
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 9b1b2b3..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() {
index c867f06..fbddfbd 100644 (file)
@@ -138,6 +138,7 @@ class SpecialEmailUser extends UnlistedSpecialPage {
                $ret = self::getTarget( $this->mTarget );
                if ( !$ret instanceof User ) {
                        if ( $this->mTarget != '' ) {
+                               // Messages used here: notargettext, noemailtext, nowikiemailtext
                                $ret = ( $ret == 'notarget' ) ? 'emailnotarget' : ( $ret . 'text' );
                                $out->wrapWikiMsg( "<p class='error'>$1</p>", $ret );
                        }
@@ -305,6 +306,7 @@ class SpecialEmailUser extends UnlistedSpecialPage {
 
                $target = self::getTarget( $data['Target'] );
                if ( !$target instanceof User ) {
+                       // Messages used here: notargettext, noemailtext, nowikiemailtext
                        return $context->msg( $target . 'text' )->parseAsBlock();
                }
 
index 82a4f70..31034f9 100644 (file)
@@ -132,6 +132,88 @@ class SpecialListGroupRights extends SpecialPage {
                        ) );
                }
                $out->addHTML( Xml::closeElement( 'table' ) );
+               $this->outputNamespaceProtectionInfo();
+       }
+
+       private function outputNamespaceProtectionInfo() {
+               global $wgNamespaceProtection, $wgParser, $wgContLang;
+               $out = $this->getOutput();
+
+               if ( count( $wgNamespaceProtection ) == 0 ) {
+                       return;
+               }
+
+               $header = $this->msg( 'listgrouprights-namespaceprotection-header' )->parse();
+               $out->addHTML(
+                       Html::rawElement( 'h2', array(), Html::element( 'span', array(
+                               'class' => 'mw-headline',
+                               'id' => $wgParser->guessSectionNameFromWikiText( $header )
+                       ), $header ) ) .
+                       Xml::openElement( 'table', array( 'class' => 'wikitable' ) ) .
+                       Html::element(
+                               'th',
+                               array(),
+                               $this->msg( 'listgrouprights-namespaceprotection-namespace' )->text()
+                       ) .
+                       Html::element(
+                               'th',
+                               array(),
+                               $this->msg( 'listgrouprights-namespaceprotection-restrictedto' )->text()
+                       )
+               );
+
+               ksort( $wgNamespaceProtection );
+               foreach ( $wgNamespaceProtection as $namespace => $rights ) {
+                       if ( !in_array( $namespace, MWNamespace::getValidNamespaces() ) ) {
+                               continue;
+                       }
+
+                       if ( $namespace == NS_MAIN ) {
+                               $namespaceText = $this->msg( 'blanknamespace' )->text();
+                       } else {
+                               $namespaceText = $wgContLang->convertNamespace( $namespace );
+                       }
+
+                       $out->addHTML(
+                               Xml::openElement( 'tr' ) .
+                               Html::rawElement(
+                                       'td',
+                                       array(),
+                                       Linker::link(
+                                               SpecialPage::getTitleFor( 'Allpages' ),
+                                               $namespaceText,
+                                               array(),
+                                               array( 'namespace' => $namespace )
+                                       )
+                               ) .
+                               Xml::openElement( 'td' ) . Xml::openElement( 'ul' )
+                       );
+
+                       if ( !is_array( $rights ) ) {
+                               $rights = array( $rights );
+                       }
+
+                       foreach ( $rights as $right ) {
+                               $out->addHTML(
+                                       Html::rawElement( 'li', array(), $this->msg(
+                                               'listgrouprights-right-display',
+                                               User::getRightDescription( $right ),
+                                               Html::element(
+                                                       'span',
+                                                       array( 'class' => 'mw-listgrouprights-right-name' ),
+                                                       $right
+                                               )
+                                       )->parse() )
+                               );
+                       }
+
+                       $out->addHTML(
+                               Xml::closeElement( 'ul' ) .
+                               Xml::closeElement( 'td' ) .
+                               Xml::closeElement( 'tr' )
+                       );
+               }
+               $out->addHTML( Xml::closeElement( 'table' ) );
        }
 
        /**
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 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 f8e5c84..08edf73 100644 (file)
@@ -67,7 +67,7 @@ class UserrightsPage extends SpecialPage {
         * Manage forms to be shown according to posted data.
         * Depending on the submit button used, call a form or a save function.
         *
-        * @param $par Mixed: string if any subpage provided, else null
+        * @param string|null $par String if any subpage provided, else null
         * @throws UserBlockedError|PermissionsError
         */
        public function execute( $par ) {
@@ -218,11 +218,11 @@ class UserrightsPage extends SpecialPage {
        /**
         * Save user groups changes in the database.
         *
-        * @param $user User object
-        * @param array $add of groups to add
-        * @param array $remove of groups to remove
-        * @param string $reason reason for group change
-        * @return Array: Tuple of added, then removed groups
+        * @param User $user
+        * @param array $add Array of groups to add
+        * @param array $remove Array of groups to remove
+        * @param string $reason Reason for group change
+        * @return array Tuple of added, then removed groups
         */
        function doSaveUserGroups( $user, $add, $remove, $reason = '' ) {
                global $wgAuth;
@@ -445,8 +445,8 @@ class UserrightsPage extends SpecialPage {
         * form will be able to manipulate based on the current user's system
         * permissions.
         *
-        * @param array $groups list of groups the given user is in
-        * @return Array:  Tuple of addable, then removable groups
+        * @param array $groups List of groups the given user is in
+        * @return array Tuple of addable, then removable groups
         */
        protected function splitGroups( $groups ) {
                list( $addable, $removable, $addself, $removeself ) = array_values( $this->changeableGroups() );
@@ -466,8 +466,8 @@ class UserrightsPage extends SpecialPage {
        /**
         * Show the form to edit group memberships.
         *
-        * @param $user      User or UserRightsProxy you're editing
-        * @param $groups    Array:  Array of groups the user is in
+        * @param User|UserRightsProxy $user User or UserRightsProxy you're editing
+        * @param array $groups Array of groups the user is in
         */
        protected function showEditUserGroupsForm( $user, $groups ) {
                $list = array();
@@ -682,7 +682,7 @@ class UserrightsPage extends SpecialPage {
        }
 
        /**
-        * @param $group String: the name of the group to check
+        * @param string $group The name of the group to check
         * @return bool Can we remove the group?
         */
        private function canRemove( $group ) {
index c8add01..f07d97b 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(
@@ -417,7 +422,7 @@ class SpecialVersion extends SpecialPage {
        /**
         * Generate wikitext showing extensions name, URL, author and description.
         *
-        * @return String: Wikitext
+        * @return string Wikitext
         */
        function getExtensionCredits() {
                global $wgExtensionCredits;
@@ -616,19 +621,42 @@ 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" );
                        }
                }
 
@@ -733,7 +761,7 @@ class SpecialVersion extends SpecialPage {
        /**
         * Generate wikitext showing hooks in $wgHooks.
         *
-        * @return String: wikitext
+        * @return string Wikitext
         */
        private function getWgHooks() {
                global $wgSpecialVersionShowHooks, $wgHooks;
@@ -804,7 +832,7 @@ class SpecialVersion extends SpecialPage {
        /**
         * Get information about client's IP address.
         *
-        * @return String: HTML fragment
+        * @return string HTML fragment
         */
        private function IPInfo() {
                $ip = str_replace( '--', ' - ', htmlspecialchars( $this->getRequest()->getIP() ) );
@@ -826,11 +854,11 @@ class SpecialVersion extends SpecialPage {
         *   If no '...' string variant is found, but an authors file is found an
         *   'and others' will be added to the end of the credits.
         *
-        * @param $authors mixed: string or array of strings
-        * @param $extName string: name of the extension for link creation
-        * @param $extDir  string: path to the extension root directory
+        * @param string|array $authors
+        * @param string $extName Name of the extension for link creation
+        * @param string $extDir Path to the extension root directory
         *
-        * @return String: HTML fragment
+        * @return string HTML fragment
         */
        function listAuthors( $authors, $extName, $extDir ) {
                $hasOthers = false;
@@ -930,10 +958,10 @@ class SpecialVersion extends SpecialPage {
        /**
         * Convert an array of items into a list for display.
         *
-        * @param array $list of elements to display
-        * @param $sort Boolean: whether to sort the items in $list
+        * @param array $list List of elements to display
+        * @param bool $sort Whether to sort the items in $list
         *
-        * @return String
+        * @return string
         */
        function listToText( $list, $sort = true ) {
                $cnt = count( $list );
@@ -956,10 +984,10 @@ class SpecialVersion extends SpecialPage {
        /**
         * Convert an array or object to a string for display.
         *
-        * @param $list Mixed: will convert an array to string if given and return
-        *              the paramater unaltered otherwise
+        * @param mixed $list will convert an array to string if given and return
+        *   the paramater unaltered otherwise
         *
-        * @return Mixed
+        * @return mixed
         */
        public static function arrayToString( $list ) {
                if ( is_array( $list ) && count( $list ) == 1 ) {
@@ -1070,7 +1098,7 @@ class SpecialVersion extends SpecialPage {
         *
         * @param string $dir directory of the svn checkout
         *
-        * @return Integer: revision number as int
+        * @return int Revision number
         */
        public static function getSvnRevision( $dir ) {
                $info = self::getSvnInfo( $dir );
index f50eb49..ad2196d 100644 (file)
@@ -177,12 +177,12 @@ class UploadStash {
        /**
         * Stash a file in a temp directory and record that we did this in the database, along with other metadata.
         *
-        * @param string $path path to file you want stashed
-        * @param string $sourceType the type of upload that generated this file (currently, I believe, 'file' or null)
+        * @param string $path Path to file you want stashed
+        * @param string $sourceType The type of upload that generated this file (currently, I believe, 'file' or null)
         * @throws UploadStashBadPathException
         * @throws UploadStashFileException
         * @throws UploadStashNotLoggedInException
-        * @return UploadStashFile: file, or null on failure
+        * @return UploadStashFile|null File, or null on failure
         */
        public function stashFile( $path, $sourceType = null ) {
                if ( !is_file( $path ) ) {
@@ -293,7 +293,7 @@ class UploadStash {
         * Does not clean up files in the repo, just the record of them.
         *
         * @throws UploadStashNotLoggedInException
-        * @return boolean: success
+        * @return bool success
         */
        public function clear() {
                if ( !$this->isLoggedIn ) {
@@ -318,9 +318,9 @@ class UploadStash {
        /**
         * Remove a particular file from the stash.  Also removes it from the repo.
         *
-        * @param $key
+        * @param string $key
         * @throws UploadStashNoSuchKeyException|UploadStashNotLoggedInException|UploadStashWrongOwnerException
-        * @return boolean: success
+        * @return bool Success
         */
        public function removeFile( $key ) {
                if ( !$this->isLoggedIn ) {
@@ -352,7 +352,8 @@ class UploadStash {
        /**
         * Remove a file (see removeFile), but doesn't check ownership first.
         *
-        * @return boolean: success
+        * @param string $key
+        * @return bool Success
         */
        public function removeFileNoAuth( $key ) {
                wfDebug( __METHOD__ . " clearing row $key\n" );
@@ -456,8 +457,8 @@ class UploadStash {
        /**
         * Helper function: do the actual database query to fetch file metadata.
         *
-        * @param string $key key
-        * @param $readFromDB: constant (default: DB_SLAVE)
+        * @param string $key
+        * @param int $readFromDB Constant (default: DB_SLAVE)
         * @return boolean
         */
        protected function fetchFileMetadata( $key, $readFromDB = DB_SLAVE ) {
@@ -514,9 +515,9 @@ class UploadStashFile extends UnregisteredLocalFile {
         * A LocalFile wrapper around a file that has been temporarily stashed, so we can do things like create thumbnails for it
         * Arguably UnregisteredLocalFile should be handling its own file repo but that class is a bit retarded currently
         *
-        * @param $repo FileRepo: repository where we should find the path
-        * @param string $path path to file
-        * @param string $key key to store the path and any stashed data under
+        * @param FileRepo $repo Repository where we should find the path
+        * @param string $path Path to file
+        * @param string $key Key to store the path and any stashed data under
         * @throws UploadStashBadPathException
         * @throws UploadStashFileNotFoundException
         */
@@ -554,7 +555,7 @@ class UploadStashFile extends UnregisteredLocalFile {
         * However, we also can't return the empty string, as the rest of MediaWiki demands this (and calls to imagemagick
         * convert require it to be there)
         *
-        * @return String: dummy value
+        * @return string Dummy value
         */
        public function getDescriptionUrl() {
                return $this->getUrl();
@@ -565,8 +566,8 @@ class UploadStashFile extends UnregisteredLocalFile {
         * The actual argument is the result of thumbName although we seem to have
         * buggy code elsewhere that expects a boolean 'suffix'
         *
-        * @param string $thumbName name of thumbnail (e.g. "120px-123456.jpg" ), or false to just get the path
-        * @return String: path thumbnail should take on filesystem, or containing directory if thumbname is false
+        * @param string $thumbName Name of thumbnail (e.g. "120px-123456.jpg" ), or false to just get the path
+        * @return string Path thumbnail should take on filesystem, or containing directory if thumbname is false
         */
        public function getThumbPath( $thumbName = false ) {
                $path = dirname( $this->path );
@@ -581,9 +582,9 @@ class UploadStashFile extends UnregisteredLocalFile {
         * We override this because we want to use the pretty url name instead of the
         * ugly file name.
         *
-        * @param array $params handler-specific parameters
-        * @param $flags integer Bitfield that supports THUMB_* constants
-        * @return String: base name for URL, like '120px-12345.jpg', or null if there is no handler
+        * @param array $params Handler-specific parameters
+        * @param int $flags Bitfield that supports THUMB_* constants
+        * @return string Base name for URL, like '120px-12345.jpg', or null if there is no handler
         */
        function thumbName( $params, $flags = 0 ) {
                return $this->generateThumbName( $this->getUrlName(), $params );
@@ -591,8 +592,8 @@ class UploadStashFile extends UnregisteredLocalFile {
 
        /**
         * Helper function -- given a 'subpage', return the local URL e.g. /wiki/Special:UploadStash/subpage
-        * @param $subPage String
-        * @return String: local URL for this subpage in the Special:UploadStash space.
+        * @param string $subPage
+        * @return string Local URL for this subpage in the Special:UploadStash space.
         */
        private function getSpecialUrl( $subPage ) {
                return SpecialPage::getTitleFor( 'UploadStash', $subPage )->getLocalURL();
@@ -604,8 +605,8 @@ class UploadStashFile extends UnregisteredLocalFile {
         * the thumbnail urls be predictable. However, in our model the URL is not based on the filename
         * (that's hidden in the db)
         *
-        * @param string $thumbName basename of thumbnail file -- however, we don't want to use the file exactly
-        * @return String: URL to access thumbnail, or URL with partial path
+        * @param string $thumbName Basename of thumbnail file -- however, we don't want to use the file exactly
+        * @return string URL to access thumbnail, or URL with partial path
         */
        public function getThumbUrl( $thumbName = false ) {
                wfDebug( __METHOD__ . " getting for $thumbName \n" );
@@ -616,7 +617,7 @@ class UploadStashFile extends UnregisteredLocalFile {
         * The basename for the URL, which we want to not be related to the filename.
         * Will also be used as the lookup key for a thumbnail file.
         *
-        * @return String: base url name, like '120px-123456.jpg'
+        * @return string Base url name, like '120px-123456.jpg'
         */
        public function getUrlName() {
                if ( ! $this->urlName ) {
@@ -629,7 +630,7 @@ class UploadStashFile extends UnregisteredLocalFile {
         * Return the URL of the file, if for some reason we wanted to download it
         * We tend not to do this for the original file, but we do want thumb icons
         *
-        * @return String: url
+        * @return string Url
         */
        public function getUrl() {
                if ( !isset( $this->url ) ) {
@@ -642,7 +643,7 @@ class UploadStashFile extends UnregisteredLocalFile {
         * Parent classes use this method, for no obvious reason, to return the path (relative to wiki root, I assume).
         * But with this class, the URL is unrelated to the path.
         *
-        * @return String: url
+        * @return string Url
         */
        public function getFullUrl() {
                return $this->getUrl();
@@ -651,7 +652,7 @@ class UploadStashFile extends UnregisteredLocalFile {
        /**
         * Getter for file key (the unique id by which this file's location & metadata is stored in the db)
         *
-        * @return String: file key
+        * @return string File key
         */
        public function getFileKey() {
                return $this->fileKey;
@@ -659,7 +660,7 @@ class UploadStashFile extends UnregisteredLocalFile {
 
        /**
         * Remove the associated temporary file
-        * @return Status: success
+        * @return status Success
         */
        public function remove() {
                if ( !$this->repo->fileExists( $this->path ) ) {
index e60293b..c7bb4f3 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,7 +455,51 @@ 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 );
+               array_map( 'fclose', array_filter( $this->fileHandles ) );
        }
 }
diff --git a/languages/ConverterRule.php b/languages/ConverterRule.php
new file mode 100644 (file)
index 0000000..4091041
--- /dev/null
@@ -0,0 +1,502 @@
+<?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
+ * @ingroup Language
+ */
+
+/**
+ * Parser for rules of language conversion , parse rules in -{ }- tag.
+ * @ingroup Language
+ * @author fdcn <fdcn64@gmail.com>, PhiLiP <philip.npc@gmail.com>
+ */
+class ConverterRule {
+       public $mText; // original text in -{text}-
+       public $mConverter; // LanguageConverter object
+       public $mRuleDisplay = '';
+       public $mRuleTitle = false;
+       public $mRules = '';// string : the text of the rules
+       public $mRulesAction = 'none';
+       public $mFlags = array();
+       public $mVariantFlags = array();
+       public $mConvTable = array();
+       public $mBidtable = array();// array of the translation in each variant
+       public $mUnidtable = array();// array of the translation in each variant
+
+       /**
+        * Constructor
+        *
+        * @param string $text The text between -{ and }-
+        * @param LanguageConverter $converter
+        */
+       public function __construct( $text, $converter ) {
+               $this->mText = $text;
+               $this->mConverter = $converter;
+       }
+
+       /**
+        * Check if variants array in convert array.
+        *
+        * @param array|string $variants Variant language code
+        * @return string Translated text
+        */
+       public function getTextInBidtable( $variants ) {
+               $variants = (array)$variants;
+               if ( !$variants ) {
+                       return false;
+               }
+               foreach ( $variants as $variant ) {
+                       if ( isset( $this->mBidtable[$variant] ) ) {
+                               return $this->mBidtable[$variant];
+                       }
+               }
+               return false;
+       }
+
+       /**
+        * Parse flags with syntax -{FLAG| ... }-
+        * @private
+        */
+       function parseFlags() {
+               $text = $this->mText;
+               $flags = array();
+               $variantFlags = array();
+
+               $sepPos = strpos( $text, '|' );
+               if ( $sepPos !== false ) {
+                       $validFlags = $this->mConverter->mFlags;
+                       $f = StringUtils::explode( ';', substr( $text, 0, $sepPos ) );
+                       foreach ( $f as $ff ) {
+                               $ff = trim( $ff );
+                               if ( isset( $validFlags[$ff] ) ) {
+                                       $flags[$validFlags[$ff]] = true;
+                               }
+                       }
+                       $text = strval( substr( $text, $sepPos + 1 ) );
+               }
+
+               if ( !$flags ) {
+                       $flags['S'] = true;
+               } elseif ( isset( $flags['R'] ) ) {
+                       $flags = array( 'R' => true );// remove other flags
+               } elseif ( isset( $flags['N'] ) ) {
+                       $flags = array( 'N' => true );// remove other flags
+               } elseif ( isset( $flags['-'] ) ) {
+                       $flags = array( '-' => true );// remove other flags
+               } elseif ( count( $flags ) == 1 && isset( $flags['T'] ) ) {
+                       $flags['H'] = true;
+               } elseif ( isset( $flags['H'] ) ) {
+                       // replace A flag, and remove other flags except T
+                       $temp = array( '+' => true, 'H' => true );
+                       if ( isset( $flags['T'] ) ) {
+                               $temp['T'] = true;
+                       }
+                       if ( isset( $flags['D'] ) ) {
+                               $temp['D'] = true;
+                       }
+                       $flags = $temp;
+               } else {
+                       if ( isset( $flags['A'] ) ) {
+                               $flags['+'] = true;
+                               $flags['S'] = true;
+                       }
+                       if ( isset( $flags['D'] ) ) {
+                               unset( $flags['S'] );
+                       }
+                       // try to find flags like "zh-hans", "zh-hant"
+                       // allow syntaxes like "-{zh-hans;zh-hant|XXXX}-"
+                       $variantFlags = array_intersect( array_keys( $flags ), $this->mConverter->mVariants );
+                       if ( $variantFlags ) {
+                               $variantFlags = array_flip( $variantFlags );
+                               $flags = array();
+                       }
+               }
+               $this->mVariantFlags = $variantFlags;
+               $this->mRules = $text;
+               $this->mFlags = $flags;
+       }
+
+       /**
+        * Generate conversion table.
+        * @private
+        */
+       function parseRules() {
+               $rules = $this->mRules;
+               $bidtable = array();
+               $unidtable = array();
+               $variants = $this->mConverter->mVariants;
+               $varsep_pattern = $this->mConverter->getVarSeparatorPattern();
+
+               // Split according to $varsep_pattern, but ignore semicolons from HTML entities
+               $rules = preg_replace( '/(&[#a-zA-Z0-9]+);/', "$1\x01", $rules );
+               $choice = preg_split( $varsep_pattern, $rules );
+               $choice = str_replace( "\x01", ';', $choice );
+
+               foreach ( $choice as $c ) {
+                       $v = explode( ':', $c, 2 );
+                       if ( count( $v ) != 2 ) {
+                               // syntax error, skip
+                               continue;
+                       }
+                       $to = trim( $v[1] );
+                       $v = trim( $v[0] );
+                       $u = explode( '=>', $v, 2 );
+                       // if $to is empty, strtr() could return a wrong result
+                       if ( count( $u ) == 1 && $to && in_array( $v, $variants ) ) {
+                               $bidtable[$v] = $to;
+                       } elseif ( count( $u ) == 2 ) {
+                               $from = trim( $u[0] );
+                               $v = trim( $u[1] );
+                               if ( array_key_exists( $v, $unidtable )
+                                       && !is_array( $unidtable[$v] )
+                                       && $to
+                                       && in_array( $v, $variants ) ) {
+                                       $unidtable[$v] = array( $from => $to );
+                               } elseif ( $to && in_array( $v, $variants ) ) {
+                                       $unidtable[$v][$from] = $to;
+                               }
+                       }
+                       // syntax error, pass
+                       if ( !isset( $this->mConverter->mVariantNames[$v] ) ) {
+                               $bidtable = array();
+                               $unidtable = array();
+                               break;
+                       }
+               }
+               $this->mBidtable = $bidtable;
+               $this->mUnidtable = $unidtable;
+       }
+
+       /**
+        * @private
+        *
+        * @return string
+        */
+       function getRulesDesc() {
+               $codesep = $this->mConverter->mDescCodeSep;
+               $varsep = $this->mConverter->mDescVarSep;
+               $text = '';
+               foreach ( $this->mBidtable as $k => $v ) {
+                       $text .= $this->mConverter->mVariantNames[$k] . "$codesep$v$varsep";
+               }
+               foreach ( $this->mUnidtable as $k => $a ) {
+                       foreach ( $a as $from => $to ) {
+                               $text .= $from . '⇒' . $this->mConverter->mVariantNames[$k] .
+                                       "$codesep$to$varsep";
+                       }
+               }
+               return $text;
+       }
+
+       /**
+        * Parse rules conversion.
+        * @private
+        *
+        * @param $variant
+        *
+        * @return string
+        */
+       function getRuleConvertedStr( $variant ) {
+               $bidtable = $this->mBidtable;
+               $unidtable = $this->mUnidtable;
+
+               if ( count( $bidtable ) + count( $unidtable ) == 0 ) {
+                       return $this->mRules;
+               } else {
+                       // display current variant in bidirectional array
+                       $disp = $this->getTextInBidtable( $variant );
+                       // or display current variant in fallbacks
+                       if ( !$disp ) {
+                               $disp = $this->getTextInBidtable(
+                                       $this->mConverter->getVariantFallbacks( $variant ) );
+                       }
+                       // or display current variant in unidirectional array
+                       if ( !$disp && array_key_exists( $variant, $unidtable ) ) {
+                               $disp = array_values( $unidtable[$variant] );
+                               $disp = $disp[0];
+                       }
+                       // or display frist text under disable manual convert
+                       if ( !$disp && $this->mConverter->mManualLevel[$variant] == 'disable' ) {
+                               if ( count( $bidtable ) > 0 ) {
+                                       $disp = array_values( $bidtable );
+                                       $disp = $disp[0];
+                               } else {
+                                       $disp = array_values( $unidtable );
+                                       $disp = array_values( $disp[0] );
+                                       $disp = $disp[0];
+                               }
+                       }
+                       return $disp;
+               }
+       }
+
+       /**
+        * Similar to getRuleConvertedStr(), but this prefers to use original
+        * page title if $variant === $this->mConverter->mMainLanguageCode
+        * and may return false in this case (so this title conversion rule
+        * will be ignored and the original title is shown).
+        *
+        * @since 1.22
+        * @param $variant The variant code to display page title in
+        * @return String|false The converted title or false if just page name
+        */
+       function getRuleConvertedTitle( $variant ) {
+               if ( $variant === $this->mConverter->mMainLanguageCode ) {
+                       // If a string targeting exactly this variant is set,
+                       // use it. Otherwise, just return false, so the real
+                       // page name can be shown (and because variant === main,
+                       // there'll be no further automatic conversion).
+                       $disp = $this->getTextInBidtable( $variant );
+                       if ( $disp ) {
+                               return $disp;
+                       }
+                       if ( array_key_exists( $variant, $this->mUnidtable ) ) {
+                               $disp = array_values( $this->mUnidtable[$variant] );
+                               $disp = $disp[0];
+                       }
+                       // Assigned above or still false.
+                       return $disp;
+               } else {
+                       return $this->getRuleConvertedStr( $variant );
+               }
+       }
+
+       /**
+        * Generate conversion table for all text.
+        * @private
+        */
+       function generateConvTable() {
+               // Special case optimisation
+               if ( !$this->mBidtable && !$this->mUnidtable ) {
+                       $this->mConvTable = array();
+                       return;
+               }
+
+               $bidtable = $this->mBidtable;
+               $unidtable = $this->mUnidtable;
+               $manLevel = $this->mConverter->mManualLevel;
+
+               $vmarked = array();
+               foreach ( $this->mConverter->mVariants as $v ) {
+                       /* for bidirectional array
+                               fill in the missing variants, if any,
+                               with fallbacks */
+                       if ( !isset( $bidtable[$v] ) ) {
+                               $variantFallbacks =
+                                       $this->mConverter->getVariantFallbacks( $v );
+                               $vf = $this->getTextInBidtable( $variantFallbacks );
+                               if ( $vf ) {
+                                       $bidtable[$v] = $vf;
+                               }
+                       }
+
+                       if ( isset( $bidtable[$v] ) ) {
+                               foreach ( $vmarked as $vo ) {
+                                       // use syntax: -{A|zh:WordZh;zh-tw:WordTw}-
+                                       // or -{H|zh:WordZh;zh-tw:WordTw}-
+                                       // or -{-|zh:WordZh;zh-tw:WordTw}-
+                                       // to introduce a custom mapping between
+                                       // words WordZh and WordTw in the whole text
+                                       if ( $manLevel[$v] == 'bidirectional' ) {
+                                               $this->mConvTable[$v][$bidtable[$vo]] = $bidtable[$v];
+                                       }
+                                       if ( $manLevel[$vo] == 'bidirectional' ) {
+                                               $this->mConvTable[$vo][$bidtable[$v]] = $bidtable[$vo];
+                                       }
+                               }
+                               $vmarked[] = $v;
+                       }
+                       /* for unidirectional array fill to convert tables */
+                       if ( ( $manLevel[$v] == 'bidirectional' || $manLevel[$v] == 'unidirectional' )
+                               && isset( $unidtable[$v] )
+                       ) {
+                               if ( isset( $this->mConvTable[$v] ) ) {
+                                       $this->mConvTable[$v] = array_merge( $this->mConvTable[$v], $unidtable[$v] );
+                               } else {
+                                       $this->mConvTable[$v] = $unidtable[$v];
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Parse rules and flags.
+        * @param string $variant Variant language code
+        */
+       public function parse( $variant = null ) {
+               if ( !$variant ) {
+                       $variant = $this->mConverter->getPreferredVariant();
+               }
+
+               $this->parseFlags();
+               $flags = $this->mFlags;
+
+               // convert to specified variant
+               // syntax: -{zh-hans;zh-hant[;...]|<text to convert>}-
+               if ( $this->mVariantFlags ) {
+                       // check if current variant in flags
+                       if ( isset( $this->mVariantFlags[$variant] ) ) {
+                               // then convert <text to convert> to current language
+                               $this->mRules = $this->mConverter->autoConvert( $this->mRules,
+                                       $variant );
+                       } else {
+                               // if current variant no in flags,
+                               // then we check its fallback variants.
+                               $variantFallbacks =
+                                       $this->mConverter->getVariantFallbacks( $variant );
+                               if ( is_array( $variantFallbacks ) ) {
+                                       foreach ( $variantFallbacks as $variantFallback ) {
+                                               // if current variant's fallback exist in flags
+                                               if ( isset( $this->mVariantFlags[$variantFallback] ) ) {
+                                                       // then convert <text to convert> to fallback language
+                                                       $this->mRules =
+                                                               $this->mConverter->autoConvert( $this->mRules,
+                                                                       $variantFallback );
+                                                       break;
+                                               }
+                                       }
+                               }
+                       }
+                       $this->mFlags = $flags = array( 'R' => true );
+               }
+
+               if ( !isset( $flags['R'] ) && !isset( $flags['N'] ) ) {
+                       // decode => HTML entities modified by Sanitizer::removeHTMLtags
+                       $this->mRules = str_replace( '=&gt;', '=>', $this->mRules );
+                       $this->parseRules();
+               }
+               $rules = $this->mRules;
+
+               if ( !$this->mBidtable && !$this->mUnidtable ) {
+                       if ( isset( $flags['+'] ) || isset( $flags['-'] ) ) {
+                               // fill all variants if text in -{A/H/-|text} without rules
+                               foreach ( $this->mConverter->mVariants as $v ) {
+                                       $this->mBidtable[$v] = $rules;
+                               }
+                       } elseif ( !isset( $flags['N'] ) && !isset( $flags['T'] ) ) {
+                               $this->mFlags = $flags = array( 'R' => true );
+                       }
+               }
+
+               $this->mRuleDisplay = false;
+               foreach ( $flags as $flag => $unused ) {
+                       switch ( $flag ) {
+                               case 'R':
+                                       // if we don't do content convert, still strip the -{}- tags
+                                       $this->mRuleDisplay = $rules;
+                                       break;
+                               case 'N':
+                                       // process N flag: output current variant name
+                                       $ruleVar = trim( $rules );
+                                       if ( isset( $this->mConverter->mVariantNames[$ruleVar] ) ) {
+                                               $this->mRuleDisplay = $this->mConverter->mVariantNames[$ruleVar];
+                                       } else {
+                                               $this->mRuleDisplay = '';
+                                       }
+                                       break;
+                               case 'D':
+                                       // process D flag: output rules description
+                                       $this->mRuleDisplay = $this->getRulesDesc();
+                                       break;
+                               case 'H':
+                                       // process H,- flag or T only: output nothing
+                                       $this->mRuleDisplay = '';
+                                       break;
+                               case '-':
+                                       $this->mRulesAction = 'remove';
+                                       $this->mRuleDisplay = '';
+                                       break;
+                               case '+':
+                                       $this->mRulesAction = 'add';
+                                       $this->mRuleDisplay = '';
+                                       break;
+                               case 'S':
+                                       $this->mRuleDisplay = $this->getRuleConvertedStr( $variant );
+                                       break;
+                               case 'T':
+                                       $this->mRuleTitle = $this->getRuleConvertedTitle( $variant );
+                                       $this->mRuleDisplay = '';
+                                       break;
+                               default:
+                                       // ignore unknown flags (but see error case below)
+                       }
+               }
+               if ( $this->mRuleDisplay === false ) {
+                       $this->mRuleDisplay = '<span class="error">'
+                               . wfMessage( 'converter-manual-rule-error' )->inContentLanguage()->escaped()
+                               . '</span>';
+               }
+
+               $this->generateConvTable();
+       }
+
+       /**
+        * @todo FIXME: code this function :)
+        */
+       public function hasRules() {
+               // TODO:
+       }
+
+       /**
+        * Get display text on markup -{...}-
+        * @return string
+        */
+       public function getDisplay() {
+               return $this->mRuleDisplay;
+       }
+
+       /**
+        * Get converted title.
+        * @return string
+        */
+       public function getTitle() {
+               return $this->mRuleTitle;
+       }
+
+       /**
+        * Return how deal with conversion rules.
+        * @return string
+        */
+       public function getRulesAction() {
+               return $this->mRulesAction;
+       }
+
+       /**
+        * Get conversion table. (bidirectional and unidirectional
+        * conversion table)
+        * @return array
+        */
+       public function getConvTable() {
+               return $this->mConvTable;
+       }
+
+       /**
+        * Get conversion rules string.
+        * @return string
+        */
+       public function getRules() {
+               return $this->mRules;
+       }
+
+       /**
+        * Get conversion flags.
+        * @return array
+        */
+       public function getFlags() {
+               return $this->mFlags;
+       }
+}
index 57e73da..8451401 100644 (file)
@@ -1,7 +1,5 @@
 <?php
 /**
- * Contains the LanguageConverter class and ConverterRule class
- *
  * 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
@@ -55,7 +53,7 @@ class LanguageConverter {
        public $mManualLevel;
 
        /**
-        * @var String: memcached key name
+        * @var string memcached key name
         */
        public $mCacheKey;
 
@@ -75,12 +73,12 @@ class LanguageConverter {
        /**
         * Constructor
         *
-        * @param $langobj Language: the Language Object
-        * @param $maincode String: the main language code of this language
-        * @param $variants Array: the supported variants of this language
-        * @param $variantfallbacks Array: the fallback language of each variant
-        * @param $flags Array: defining the custom strings that maps to the flags
-        * @param $manualLevel Array: limit for supported variants
+        * @param Language $langobj
+        * @param string $maincode The main language code of this language
+        * @param array $variants The supported variants of this language
+        * @param array $variantfallbacks The fallback language of each variant
+        * @param array $flags Defining the custom strings that maps to the flags
+        * @param array $manualLevel Limit for supported variants
         */
        public function __construct( $langobj, $maincode, $variants = array(),
                                                                $variantfallbacks = array(), $flags = array(),
@@ -120,7 +118,7 @@ class LanguageConverter {
         * Get all valid variants.
         * Call this instead of using $this->mVariants directly.
         *
-        * @return Array: contains all valid variants
+        * @return array Contains all valid variants
         */
        public function getVariants() {
                return $this->mVariants;
@@ -133,9 +131,9 @@ class LanguageConverter {
         * when zh-sg is preferred but not defined, we will pick zh-hans
         * in this case. Right now this is only used by zh.
         *
-        * @param $variant String: the language code of the variant
-        * @return String|array: The code of the fallback language or the
-        *                               main code if there is no fallback
+        * @param string $variant The language code of the variant
+        * @return string|array The code of the fallback language or the
+        *   main code if there is no fallback
         */
        public function getVariantFallbacks( $variant ) {
                if ( isset( $this->mVariantFallbacks[$variant] ) ) {
@@ -146,7 +144,7 @@ class LanguageConverter {
 
        /**
         * Get the title produced by the conversion rule.
-        * @return String: The converted title text
+        * @return string The converted title text
         */
        public function getConvRuleTitle() {
                return $this->mConvRuleTitle;
@@ -154,7 +152,7 @@ class LanguageConverter {
 
        /**
         * Get preferred language variant.
-        * @return String: the preferred language code
+        * @return string The preferred language code
         */
        public function getPreferredVariant() {
                global $wgDefaultLanguageVariant, $wgUser;
@@ -184,7 +182,7 @@ class LanguageConverter {
        /**
         * Get default variant.
         * This function would not be affected by user's settings
-        * @return String: the default variant code
+        * @return string The default variant code
         */
        public function getDefaultVariant() {
                global $wgDefaultLanguageVariant;
@@ -207,8 +205,8 @@ class LanguageConverter {
 
        /**
         * Validate the variant
-        * @param $variant String: the variant to validate
-        * @return Mixed: returns the variant if it is valid, null otherwise
+        * @param string $variant The variant to validate
+        * @return mixed Returns the variant if it is valid, null otherwise
         */
        public function validateVariant( $variant = null ) {
                if ( $variant !== null && in_array( $variant, $this->mVariants ) ) {
@@ -220,7 +218,7 @@ class LanguageConverter {
        /**
         * Get the variant specified in the URL
         *
-        * @return Mixed: variant if one found, false otherwise.
+        * @return mixed Variant if one found, false otherwise.
         */
        public function getURLVariant() {
                global $wgRequest;
@@ -243,7 +241,7 @@ class LanguageConverter {
        /**
         * Determine if the user has a variant set.
         *
-        * @return Mixed: variant if one found, false otherwise.
+        * @return mixed Variant if one found, false otherwise.
         */
        protected function getUserVariant() {
                global $wgUser, $wgContLang;
@@ -277,7 +275,7 @@ class LanguageConverter {
        /**
         * Determine the language variant from the Accept-Language header.
         *
-        * @return Mixed: variant if one found, false otherwise.
+        * @return mixed Variant if one found, false otherwise.
         */
        protected function getHeaderVariant() {
                global $wgRequest;
@@ -456,9 +454,9 @@ class LanguageConverter {
         * Doesn't parse rules or do any of that other stuff, for that use
         * convert() or convertTo().
         *
-        * @param $text String: text to convert
-        * @param $variant String: variant language code
-        * @return String: translated text
+        * @param string $text Text to convert
+        * @param string $variant Variant language code
+        * @return string Translated text
         */
        public function translate( $text, $variant ) {
                wfProfileIn( __METHOD__ );
@@ -475,8 +473,8 @@ class LanguageConverter {
        /**
         * Call translate() to convert text to all valid variants.
         *
-        * @param $text String: the text to be converted
-        * @return Array: variant => converted text
+        * @param string $text The text to be converted
+        * @return array Variant => converted text
         */
        public function autoConvertToAllVariants( $text ) {
                wfProfileIn( __METHOD__ );
@@ -534,8 +532,8 @@ class LanguageConverter {
         * Auto convert a Title object to a readable string in the
         * preferred variant.
         *
-        * @param $title Title a object of Title
-        * @return String: converted title text
+        * @param Title $title A object of Title
+        * @return string Converted title text
         */
        public function convertTitle( $title ) {
                $variant = $this->getPreferredVariant();
@@ -552,9 +550,9 @@ class LanguageConverter {
        /**
         * Get the namespace display name in the preferred variant.
         *
-        * @param $index int namespace id
-        * @param $variant string|null variant code or null for preferred variant
-        * @return String: namespace name for display
+        * @param int $index Namespace id
+        * @param string|null $variant Variant code or null for preferred variant
+        * @return string Namespace name for display
         */
        public function convertNamespace( $index, $variant = null ) {
                if ( $variant === null ) {
@@ -591,8 +589,8 @@ class LanguageConverter {
         * -{flags|code1:text1;code2:text2;...}-  or
         * -{text}- in which case no conversion should take place for text
         *
-        * @param $text String: text to be converted
-        * @return String: converted text
+        * @param string $text Text to be converted
+        * @return string Converted text
         */
        public function convert( $text ) {
                $variant = $this->getPreferredVariant();
@@ -602,9 +600,9 @@ class LanguageConverter {
        /**
         * Same as convert() except a extra parameter to custom variant.
         *
-        * @param $text String: text to be converted
-        * @param $variant String: the target variant code
-        * @return String: converted text
+        * @param string $text Text to be converted
+        * @param string $variant The target variant code
+        * @return string Converted text
         */
        public function convertTo( $text, $variant ) {
                global $wgDisableLangConversion;
@@ -620,10 +618,10 @@ class LanguageConverter {
         * Recursively convert text on the outside. Allow to use nested
         * markups to custom rules.
         *
-        * @param $text String: text to be converted
-        * @param $variant String: the target variant code
-        * @param $depth Integer: depth of recursion
-        * @return String: converted text
+        * @param string $text Text to be converted
+        * @param string $variant The target variant code
+        * @param int $depth Depth of recursion
+        * @return string Converted text
         */
        protected function recursiveConvertTopLevel( $text, $variant, $depth = 0 ) {
                $startPos = 0;
@@ -659,13 +657,13 @@ class LanguageConverter {
        /**
         * Recursively convert text on the inside.
         *
-        * @param $text String: text to be converted
-        * @param $variant String: the target variant code
-        * @param $startPos int
-        * @param $depth Integer: depth of recursion
+        * @param string $text Text to be converted
+        * @param string $variant The target variant code
+        * @param int $startPos
+        * @param int $depth Depth of recursion
         *
         * @throws MWException
-        * @return String: converted text
+        * @return string Converted text
         */
        protected function recursiveConvertRule( $text, $variant, &$startPos, $depth = 0 ) {
                // Quick sanity check (no function calls)
@@ -739,11 +737,11 @@ class LanguageConverter {
         * non-existing link in one variant actually exists in another variant.
         * This function tries to find it. See e.g. LanguageZh.php
         *
-        * @param $link String: the name of the link
-        * @param $nt Mixed: the title object of the link
-        * @param $ignoreOtherCond Boolean: to disable other conditions when
-        *              we need to transclude a template or update a category's link
-        * @return Null, the input parameters may be modified upon return
+        * @param string $link The name of the link
+        * @param mixed $nt The title object of the link
+        * @param bool $ignoreOtherCond To disable other conditions when
+        *   we need to transclude a template or update a category's link
+        * @return void Null, the input parameters may be modified upon return
         */
        public function findVariantLink( &$link, &$nt, $ignoreOtherCond = false ) {
                # If the article has already existed, there is no need to
@@ -843,7 +841,7 @@ class LanguageConverter {
        /**
         * Load conversion tables either from the cache or the disk.
         * @private
-        * @param $fromCache Boolean: load from memcached? Defaults to true.
+        * @param bool $fromCache Load from memcached? Defaults to true.
         */
        function loadTables( $fromCache = true ) {
                global $wgLangConvMemc;
@@ -911,9 +909,9 @@ class LanguageConverter {
         * To make the tables more manageable, subpages are allowed
         * and will be parsed recursively if $recursive == true.
         *
-        * @param $code String: language code
-        * @param $subpage String: subpage name
-        * @param $recursive Boolean: parse subpages recursively? Defaults to true.
+        * @param string $code Language code
+        * @param string $subpage Subpage name
+        * @param bool $recursive Parse subpages recursively? Defaults to true.
         *
         * @return array
         */
@@ -1020,9 +1018,9 @@ class LanguageConverter {
         * Enclose a string with the "no conversion" tag. This is used by
         * various functions in the Parser.
         *
-        * @param $text String: text to be tagged for no conversion
-        * @param $noParse Boolean: unused
-        * @return String: the tagged text
+        * @param string $text Text to be tagged for no conversion
+        * @param bool $noParse Unused
+        * @return string The tagged text
         */
        public function markNoConversion( $text, $noParse = false ) {
                # don't mark if already marked
@@ -1051,16 +1049,16 @@ class LanguageConverter {
         * MediaWiki:Conversiontable* is updated.
         * @private
         *
-        * @param $page WikiPage object
-        * @param $user Object: User object for the current user
-        * @param $content Content: new page content
-        * @param $summary String: edit summary of the edit
-        * @param $isMinor Boolean: was the edit marked as minor?
-        * @param $isWatch Boolean: did the user watch this page or not?
-        * @param $section
-        * @param $flags int Bitfield
-        * @param $revision Object: new Revision object or null
-        * @return Boolean: true
+        * @param WikiPage $page
+        * @param User $user User object for the current user
+        * @param Content $content new page content
+        * @param string $summary edit summary of the edit
+        * @param bool $isMinor was the edit marked as minor?
+        * @param bool $isWatch did the user watch this page or not?
+        * @param string|int $section
+        * @param int $flags Bitfield
+        * @param Revision $revision new Revision object or null
+        * @return bool true
         */
        function OnPageContentSaveComplete( $page, $user, $content, $summary, $isMinor,
                        $isWatch, $section, $flags, $revision ) {
@@ -1082,9 +1080,9 @@ class LanguageConverter {
         * Armour rendered math against conversion.
         * Escape special chars in parsed math text. (in most cases are img elements)
         *
-        * @param $text String: text to armour against conversion
-        * @return String: armoured text where { and } have been converted to
-        *                 &#123; and &#125;
+        * @param string $text Text to armour against conversion
+        * @return string Armoured text where { and } have been converted to
+        *   &#123; and &#125;
         * @deprecated since 1.22 is no longer used
         */
        public function armourMath( $text ) {
@@ -1123,485 +1121,3 @@ class LanguageConverter {
                return $this->mVarSeparatorPattern;
        }
 }
-
-/**
- * Parser for rules of language conversion , parse rules in -{ }- tag.
- * @ingroup Language
- * @author fdcn <fdcn64@gmail.com>, PhiLiP <philip.npc@gmail.com>
- */
-class ConverterRule {
-       public $mText; // original text in -{text}-
-       public $mConverter; // LanguageConverter object
-       public $mRuleDisplay = '';
-       public $mRuleTitle = false;
-       public $mRules = '';// string : the text of the rules
-       public $mRulesAction = 'none';
-       public $mFlags = array();
-       public $mVariantFlags = array();
-       public $mConvTable = array();
-       public $mBidtable = array();// array of the translation in each variant
-       public $mUnidtable = array();// array of the translation in each variant
-
-       /**
-        * Constructor
-        *
-        * @param $text String: the text between -{ and }-
-        * @param $converter LanguageConverter object
-        */
-       public function __construct( $text, $converter ) {
-               $this->mText = $text;
-               $this->mConverter = $converter;
-       }
-
-       /**
-        * Check if variants array in convert array.
-        *
-        * @param $variants Array or string: variant language code
-        * @return String: translated text
-        */
-       public function getTextInBidtable( $variants ) {
-               $variants = (array)$variants;
-               if ( !$variants ) {
-                       return false;
-               }
-               foreach ( $variants as $variant ) {
-                       if ( isset( $this->mBidtable[$variant] ) ) {
-                               return $this->mBidtable[$variant];
-                       }
-               }
-               return false;
-       }
-
-       /**
-        * Parse flags with syntax -{FLAG| ... }-
-        * @private
-        */
-       function parseFlags() {
-               $text = $this->mText;
-               $flags = array();
-               $variantFlags = array();
-
-               $sepPos = strpos( $text, '|' );
-               if ( $sepPos !== false ) {
-                       $validFlags = $this->mConverter->mFlags;
-                       $f = StringUtils::explode( ';', substr( $text, 0, $sepPos ) );
-                       foreach ( $f as $ff ) {
-                               $ff = trim( $ff );
-                               if ( isset( $validFlags[$ff] ) ) {
-                                       $flags[$validFlags[$ff]] = true;
-                               }
-                       }
-                       $text = strval( substr( $text, $sepPos + 1 ) );
-               }
-
-               if ( !$flags ) {
-                       $flags['S'] = true;
-               } elseif ( isset( $flags['R'] ) ) {
-                       $flags = array( 'R' => true );// remove other flags
-               } elseif ( isset( $flags['N'] ) ) {
-                       $flags = array( 'N' => true );// remove other flags
-               } elseif ( isset( $flags['-'] ) ) {
-                       $flags = array( '-' => true );// remove other flags
-               } elseif ( count( $flags ) == 1 && isset( $flags['T'] ) ) {
-                       $flags['H'] = true;
-               } elseif ( isset( $flags['H'] ) ) {
-                       // replace A flag, and remove other flags except T
-                       $temp = array( '+' => true, 'H' => true );
-                       if ( isset( $flags['T'] ) ) {
-                               $temp['T'] = true;
-                       }
-                       if ( isset( $flags['D'] ) ) {
-                               $temp['D'] = true;
-                       }
-                       $flags = $temp;
-               } else {
-                       if ( isset( $flags['A'] ) ) {
-                               $flags['+'] = true;
-                               $flags['S'] = true;
-                       }
-                       if ( isset( $flags['D'] ) ) {
-                               unset( $flags['S'] );
-                       }
-                       // try to find flags like "zh-hans", "zh-hant"
-                       // allow syntaxes like "-{zh-hans;zh-hant|XXXX}-"
-                       $variantFlags = array_intersect( array_keys( $flags ), $this->mConverter->mVariants );
-                       if ( $variantFlags ) {
-                               $variantFlags = array_flip( $variantFlags );
-                               $flags = array();
-                       }
-               }
-               $this->mVariantFlags = $variantFlags;
-               $this->mRules = $text;
-               $this->mFlags = $flags;
-       }
-
-       /**
-        * Generate conversion table.
-        * @private
-        */
-       function parseRules() {
-               $rules = $this->mRules;
-               $bidtable = array();
-               $unidtable = array();
-               $variants = $this->mConverter->mVariants;
-               $varsep_pattern = $this->mConverter->getVarSeparatorPattern();
-
-               // Split according to $varsep_pattern, but ignore semicolons from HTML entities
-               $rules = preg_replace( '/(&[#a-zA-Z0-9]+);/', "$1\x01", $rules );
-               $choice = preg_split( $varsep_pattern, $rules );
-               $choice = str_replace( "\x01", ';', $choice );
-
-               foreach ( $choice as $c ) {
-                       $v = explode( ':', $c, 2 );
-                       if ( count( $v ) != 2 ) {
-                               // syntax error, skip
-                               continue;
-                       }
-                       $to = trim( $v[1] );
-                       $v = trim( $v[0] );
-                       $u = explode( '=>', $v, 2 );
-                       // if $to is empty, strtr() could return a wrong result
-                       if ( count( $u ) == 1 && $to && in_array( $v, $variants ) ) {
-                               $bidtable[$v] = $to;
-                       } elseif ( count( $u ) == 2 ) {
-                               $from = trim( $u[0] );
-                               $v = trim( $u[1] );
-                               if ( array_key_exists( $v, $unidtable )
-                                       && !is_array( $unidtable[$v] )
-                                       && $to
-                                       && in_array( $v, $variants ) ) {
-                                       $unidtable[$v] = array( $from => $to );
-                               } elseif ( $to && in_array( $v, $variants ) ) {
-                                       $unidtable[$v][$from] = $to;
-                               }
-                       }
-                       // syntax error, pass
-                       if ( !isset( $this->mConverter->mVariantNames[$v] ) ) {
-                               $bidtable = array();
-                               $unidtable = array();
-                               break;
-                       }
-               }
-               $this->mBidtable = $bidtable;
-               $this->mUnidtable = $unidtable;
-       }
-
-       /**
-        * @private
-        *
-        * @return string
-        */
-       function getRulesDesc() {
-               $codesep = $this->mConverter->mDescCodeSep;
-               $varsep = $this->mConverter->mDescVarSep;
-               $text = '';
-               foreach ( $this->mBidtable as $k => $v ) {
-                       $text .= $this->mConverter->mVariantNames[$k] . "$codesep$v$varsep";
-               }
-               foreach ( $this->mUnidtable as $k => $a ) {
-                       foreach ( $a as $from => $to ) {
-                               $text .= $from . '⇒' . $this->mConverter->mVariantNames[$k] .
-                                       "$codesep$to$varsep";
-                       }
-               }
-               return $text;
-       }
-
-       /**
-        * Parse rules conversion.
-        * @private
-        *
-        * @param $variant
-        *
-        * @return string
-        */
-       function getRuleConvertedStr( $variant ) {
-               $bidtable = $this->mBidtable;
-               $unidtable = $this->mUnidtable;
-
-               if ( count( $bidtable ) + count( $unidtable ) == 0 ) {
-                       return $this->mRules;
-               } else {
-                       // display current variant in bidirectional array
-                       $disp = $this->getTextInBidtable( $variant );
-                       // or display current variant in fallbacks
-                       if ( !$disp ) {
-                               $disp = $this->getTextInBidtable(
-                                               $this->mConverter->getVariantFallbacks( $variant ) );
-                       }
-                       // or display current variant in unidirectional array
-                       if ( !$disp && array_key_exists( $variant, $unidtable ) ) {
-                               $disp = array_values( $unidtable[$variant] );
-                               $disp = $disp[0];
-                       }
-                       // or display frist text under disable manual convert
-                       if ( !$disp && $this->mConverter->mManualLevel[$variant] == 'disable' ) {
-                               if ( count( $bidtable ) > 0 ) {
-                                       $disp = array_values( $bidtable );
-                                       $disp = $disp[0];
-                               } else {
-                                       $disp = array_values( $unidtable );
-                                       $disp = array_values( $disp[0] );
-                                       $disp = $disp[0];
-                               }
-                       }
-                       return $disp;
-               }
-       }
-
-       /**
-        * Similar to getRuleConvertedStr(), but this prefers to use original
-        * page title if $variant === $this->mConverter->mMainLanguageCode
-        * and may return false in this case (so this title conversion rule
-        * will be ignored and the original title is shown).
-        *
-        * @since 1.22
-        * @param $variant The variant code to display page title in
-        * @return String|false The converted title or false if just page name
-        */
-       function getRuleConvertedTitle( $variant ) {
-               if ( $variant === $this->mConverter->mMainLanguageCode ) {
-                       // If a string targeting exactly this variant is set,
-                       // use it. Otherwise, just return false, so the real
-                       // page name can be shown (and because variant === main,
-                       // there'll be no further automatic conversion).
-                       $disp = $this->getTextInBidtable( $variant );
-                       if ( $disp ) {
-                               return $disp;
-                       }
-                       if ( array_key_exists( $variant, $this->mUnidtable ) ) {
-                               $disp = array_values( $this->mUnidtable[$variant] );
-                               $disp = $disp[0];
-                       }
-                       // Assigned above or still false.
-                       return $disp;
-               } else {
-                       return $this->getRuleConvertedStr( $variant );
-               }
-       }
-
-       /**
-        * Generate conversion table for all text.
-        * @private
-        */
-       function generateConvTable() {
-               // Special case optimisation
-               if ( !$this->mBidtable && !$this->mUnidtable ) {
-                       $this->mConvTable = array();
-                       return;
-               }
-
-               $bidtable = $this->mBidtable;
-               $unidtable = $this->mUnidtable;
-               $manLevel = $this->mConverter->mManualLevel;
-
-               $vmarked = array();
-               foreach ( $this->mConverter->mVariants as $v ) {
-                       /* for bidirectional array
-                               fill in the missing variants, if any,
-                               with fallbacks */
-                       if ( !isset( $bidtable[$v] ) ) {
-                               $variantFallbacks =
-                                       $this->mConverter->getVariantFallbacks( $v );
-                               $vf = $this->getTextInBidtable( $variantFallbacks );
-                               if ( $vf ) {
-                                       $bidtable[$v] = $vf;
-                               }
-                       }
-
-                       if ( isset( $bidtable[$v] ) ) {
-                               foreach ( $vmarked as $vo ) {
-                                       // use syntax: -{A|zh:WordZh;zh-tw:WordTw}-
-                                       // or -{H|zh:WordZh;zh-tw:WordTw}-
-                                       // or -{-|zh:WordZh;zh-tw:WordTw}-
-                                       // to introduce a custom mapping between
-                                       // words WordZh and WordTw in the whole text
-                                       if ( $manLevel[$v] == 'bidirectional' ) {
-                                               $this->mConvTable[$v][$bidtable[$vo]] = $bidtable[$v];
-                                       }
-                                       if ( $manLevel[$vo] == 'bidirectional' ) {
-                                               $this->mConvTable[$vo][$bidtable[$v]] = $bidtable[$vo];
-                                       }
-                               }
-                               $vmarked[] = $v;
-                       }
-                       /* for unidirectional array fill to convert tables */
-                       if ( ( $manLevel[$v] == 'bidirectional' || $manLevel[$v] == 'unidirectional' )
-                               && isset( $unidtable[$v] )
-                       ) {
-                               if ( isset( $this->mConvTable[$v] ) ) {
-                                       $this->mConvTable[$v] = array_merge( $this->mConvTable[$v], $unidtable[$v] );
-                               } else {
-                                       $this->mConvTable[$v] = $unidtable[$v];
-                               }
-                       }
-               }
-       }
-
-       /**
-        * Parse rules and flags.
-        * @param $variant String: variant language code
-        */
-       public function parse( $variant = null ) {
-               if ( !$variant ) {
-                       $variant = $this->mConverter->getPreferredVariant();
-               }
-
-               $this->parseFlags();
-               $flags = $this->mFlags;
-
-               // convert to specified variant
-               // syntax: -{zh-hans;zh-hant[;...]|<text to convert>}-
-               if ( $this->mVariantFlags ) {
-                       // check if current variant in flags
-                       if ( isset( $this->mVariantFlags[$variant] ) ) {
-                               // then convert <text to convert> to current language
-                               $this->mRules = $this->mConverter->autoConvert( $this->mRules,
-                                       $variant );
-                       } else {
-                               // if current variant no in flags,
-                               // then we check its fallback variants.
-                               $variantFallbacks =
-                                       $this->mConverter->getVariantFallbacks( $variant );
-                               if ( is_array( $variantFallbacks ) ) {
-                                       foreach ( $variantFallbacks as $variantFallback ) {
-                                               // if current variant's fallback exist in flags
-                                               if ( isset( $this->mVariantFlags[$variantFallback] ) ) {
-                                                       // then convert <text to convert> to fallback language
-                                                       $this->mRules =
-                                                               $this->mConverter->autoConvert( $this->mRules,
-                                                                       $variantFallback );
-                                                       break;
-                                               }
-                                       }
-                               }
-                       }
-                       $this->mFlags = $flags = array( 'R' => true );
-               }
-
-               if ( !isset( $flags['R'] ) && !isset( $flags['N'] ) ) {
-                       // decode => HTML entities modified by Sanitizer::removeHTMLtags
-                       $this->mRules = str_replace( '=&gt;', '=>', $this->mRules );
-                       $this->parseRules();
-               }
-               $rules = $this->mRules;
-
-               if ( !$this->mBidtable && !$this->mUnidtable ) {
-                       if ( isset( $flags['+'] ) || isset( $flags['-'] ) ) {
-                               // fill all variants if text in -{A/H/-|text} without rules
-                               foreach ( $this->mConverter->mVariants as $v ) {
-                                       $this->mBidtable[$v] = $rules;
-                               }
-                       } elseif ( !isset( $flags['N'] ) && !isset( $flags['T'] ) ) {
-                               $this->mFlags = $flags = array( 'R' => true );
-                       }
-               }
-
-               $this->mRuleDisplay = false;
-               foreach ( $flags as $flag => $unused ) {
-                       switch ( $flag ) {
-                               case 'R':
-                                       // if we don't do content convert, still strip the -{}- tags
-                                       $this->mRuleDisplay = $rules;
-                                       break;
-                               case 'N':
-                                       // process N flag: output current variant name
-                                       $ruleVar = trim( $rules );
-                                       if ( isset( $this->mConverter->mVariantNames[$ruleVar] ) ) {
-                                               $this->mRuleDisplay = $this->mConverter->mVariantNames[$ruleVar];
-                                       } else {
-                                               $this->mRuleDisplay = '';
-                                       }
-                                       break;
-                               case 'D':
-                                       // process D flag: output rules description
-                                       $this->mRuleDisplay = $this->getRulesDesc();
-                                       break;
-                               case 'H':
-                                       // process H,- flag or T only: output nothing
-                                       $this->mRuleDisplay = '';
-                                       break;
-                               case '-':
-                                       $this->mRulesAction = 'remove';
-                                       $this->mRuleDisplay = '';
-                                       break;
-                               case '+':
-                                       $this->mRulesAction = 'add';
-                                       $this->mRuleDisplay = '';
-                                       break;
-                               case 'S':
-                                       $this->mRuleDisplay = $this->getRuleConvertedStr( $variant );
-                                       break;
-                               case 'T':
-                                       $this->mRuleTitle = $this->getRuleConvertedTitle( $variant );
-                                       $this->mRuleDisplay = '';
-                                       break;
-                               default:
-                                       // ignore unknown flags (but see error case below)
-                       }
-               }
-               if ( $this->mRuleDisplay === false ) {
-                       $this->mRuleDisplay = '<span class="error">'
-                               . wfMessage( 'converter-manual-rule-error' )->inContentLanguage()->escaped()
-                               . '</span>';
-               }
-
-               $this->generateConvTable();
-       }
-
-       /**
-        * @todo FIXME: code this function :)
-        */
-       public function hasRules() {
-               // TODO:
-       }
-
-       /**
-        * Get display text on markup -{...}-
-        * @return string
-        */
-       public function getDisplay() {
-               return $this->mRuleDisplay;
-       }
-
-       /**
-        * Get converted title.
-        * @return string
-        */
-       public function getTitle() {
-               return $this->mRuleTitle;
-       }
-
-       /**
-        * Return how deal with conversion rules.
-        * @return string
-        */
-       public function getRulesAction() {
-               return $this->mRulesAction;
-       }
-
-       /**
-        * Get conversion table. (bidirectional and unidirectional
-        * conversion table)
-        * @return array
-        */
-       public function getConvTable() {
-               return $this->mConvTable;
-       }
-
-       /**
-        * Get conversion rules string.
-        * @return string
-        */
-       public function getRules() {
-               return $this->mRules;
-       }
-
-       /**
-        * Get conversion flags.
-        * @return array
-        */
-       public function getFlags() {
-               return $this->mFlags;
-       }
-}
index a728c9d..06cb1b5 100644 (file)
@@ -190,9 +190,9 @@ class SrConverter extends LanguageConverter {
         * Guess if a text is written in Cyrillic or Latin.
         * Overrides LanguageConverter::guessVariant()
         *
-        * @param string  $text The text to be checked
-        * @param string  $variant Language code of the variant to be checked for
-        * @return bool  true if $text appears to be written in $variant
+        * @param string $text The text to be checked
+        * @param string $variant Language code of the variant to be checked for
+        * @return bool true if $text appears to be written in $variant
         *
         * @author Nikola Smolenski <smolensk@eunet.rs>
         * @since 1.19
index 63989e9..a630a37 100644 (file)
     "accountcreated": "Ureuëng ngui ka teupeugöt",
     "accountcreatedtext": "Ureuëng ngui keu [[{{ns:User}}:$1|$1]]([[{{ns:User talk}}:$1|talk]]) ka teupeugöt.",
     "createaccount-title": "Peugöt ureuëng ngui keu {{SITENAME}}",
-    "usernamehasherror": "Nan ureueng ngui han jeut na tanda pageue",
     "login-throttled": "Droeneuh ka lé that neuujoe tamöng.\nNeuprèh $1 sigohlom neuujoe lom.",
     "login-abort-generic": "Log tamöng droëneuh han meuhasé- Ngon ka geupeubateuë.",
     "loginlanguagelabel": "Bahsa: $1",
     "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",
     "reuploaddesc": "Riwang u laman peutamöng",
     "uploadnologin": "Hana lom meutamöng",
     "uploadnologintext": "Droeneuh suwah $1 keu neupeutamöng beureukaih.",
-    "uploadlog": "ceunatat peutamöng",
     "uploadlogpage": "Log peutamöng",
     "uploadlogpagetext": "Nyoe nakeuh dapeuta peutamöng barô.\nEu [[Special:NewFiles|galeri beureukaih barô]] keu seuneudeuh barô.",
     "filename": "Nan beureukaih",
     "filedesc": "Ehtisa",
     "fileuploadsummary": "Éhtisa:",
     "filesource": "Nè",
-    "uploadedfiles": "Beureukaih nyang meupeutamöng",
     "minlength1": "Nan beureukaih beuna saboh haraih.",
     "illegalfilename": "Nan beureukaih \"$1\" meuasoe seunurat nyang han jeut na bak nan. Tulông gantoe nan nyan sigohlom neupeutamöng lom.",
     "filename-toolong": "Nan beureukaih han jeut leubèh nibak 240 bita.",
     "filehist-dimensions": "Dimènsi",
     "filehist-filesize": "Rayek beureukah",
     "filehist-comment": "Seuneu'ôt",
-    "filehist-missing": "Beureukaih hana meutumèe",
     "imagelinks": "Seuneungui beureukaih",
     "linkstoimage": "{{PLURAL:$1|laman}} di yup nyoë mupawôt u beureukaih nyoë:",
     "nolinkstoimage": "Hana laman nyang na meupawôt u beureukaih nyoë.",
index d3c1d16..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",
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 0edb8f4..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": "ለመከታተል",
index 0333af4..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",
index cd0ec77..b01ffee 100644 (file)
     "disclaimers": "अस्वीकरण",
     "disclaimerpage": "Project:साधारण अस्वीकरण",
     "edithelp": "संपादन मॆं सहायता",
-    "helppage": "Help:सहायता",
     "mainpage": "मुख्य पृष्ठ",
     "privacy": "गोपनीयता नीति",
     "privacypage": "Project:गोपनीयता नीति",
index 62074f8..467801a 100644 (file)
     "print": "اطبع",
     "view": "مطالعة",
     "edit": "عدل",
+    "edit-local": "تعديل الوصف المحلي",
     "create": "أنشئ",
+    "create-local": "أضف وصفا محليا",
     "editthispage": "عدل هذه الصفحة",
     "create-this-page": "أنشئ صفحة بهذا العنوان",
     "delete": "حذف",
     "pool-timeout": "انتهت مهلة القفل",
     "pool-queuefull": "الطابور ملآن",
     "pool-errorunknown": "خطأ غير معروف",
+    "pool-servererror": "خدمة العداد غير متاحة ( $1 ).",
     "aboutsite": "عن {{SITENAME}}",
     "aboutpage": "Project:عن",
     "copyright": "المحتوى منشور وفق $1 إن لم يرد خلاف ذلك.",
     "accountcreatedtext": "أنشئ حساب مستخدم ل[[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|نقاش]]).",
     "createaccount-title": "إنشاء حساب في {{SITENAME}}",
     "createaccount-text": "شخص ما أنشأ حسابا لعنوان بريدك الإلكتروني في {{SITENAME}} ($4) بالاسم \"$2\"، كلمة السر \"$3\".\nينبغي عليك تسجيل الدخول وتغيير كلمة السر الخاصة بك الآن.\n\nيمكنك تجاهل هذه الرسالة، لو تم إنشاء هذا الحساب بالخطأ.",
-    "usernamehasherror": "لا يمكن أن يحتوي اسم المستخدم على محارف هاش",
     "login-throttled": "لقد قمت بمحاولات دخول كثيرة جدا مؤخرا.\nمن فضلك انتظر $1 قبل المحاولة مرة أخرى.",
     "login-abort-generic": "لم ينجح ولوجك - تم إجهاضه",
     "loginlanguagelabel": "اللغة: $1",
     "resetpass-abort-generic": "منعت مُلحقة إتمام صيرورة تغيير كلمة السّر.",
     "resetpass-expired": "انتهت مدة صلاحية كلمة السر الخاصة بك. الرجاء تعيين كلمة سر جديدة لتسجيل الدخول.",
     "resetpass-expired-soft": "انتهت مدة صلاحية كلمة السر الخاصة بك. الرجاء تعيين كلمة سر جديدة الآن أو النقر على زر إلغاء لإعادة تعيين كلمة السر لاحقاً.",
+    "resetpass-validity-soft": "كلمة السر الخاصة بك غير مقبولة :  $1 \n\nرجاءا اختر كلمة سر جديدة الآن، أو انقر فوق \"{{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": "صفحات المستخدمين",
     "upload-permitted": "أنواع الملفات المسموحة: $1.",
     "upload-preferred": "أنواع الملفات المفضلة: $1.",
     "upload-prohibited": "أنواع الملفات الممنوعة: $1.",
-    "uploadlog": "سجل الرفع",
     "uploadlogpage": "سجل الرفع",
     "uploadlogpagetext": "في الأسفل قائمة بأحدث عمليات رفع الملفات.\nانظر [[Special:NewFiles|معرض الملفات الجديدة]] لعرض بصري أكثر",
     "filename": "اسم الملف",
     "filereuploadsummary": "تغييرات الملف:",
     "filestatus": "حالة حقوق النسخ:",
     "filesource": "مصدر:",
-    "uploadedfiles": "الملفات المرفوعة",
     "ignorewarning": "تجاهل التحذير واحفظ الملف على أية حال.",
     "ignorewarnings": "تجاهل أية تحذيرات",
     "minlength1": "أسماء الملفات يجب أن تتكون من حرف واحد على الأقل.",
     "overwroteimage": "رفع نسخة جديدة من \"[[$1]]\"",
     "uploaddisabled": "تم تعطيل الرفع",
     "copyuploaddisabled": "الرفع من مسار معطل.",
-    "uploadfromurl-queued": "رفعك قد أضيف إلى الطابور",
     "uploaddisabledtext": "رفع الملفات معطل.",
     "php-uploaddisabledtext": "رفع ملفات PHP معطل. من فضلك تحقق من إعدادات رفع الملفات.",
     "uploadscripted": "هذا الملف يضم كود HTML أو كود آخر يمكن أن يفسره متصفح الوب بطريقة خاطئة.",
+    "uploadscriptednamespace": "يحتوي ملف SVG هذا على اسم نطاق غير مشروع \" $1 \"",
     "uploadinvalidxml": "تعذر تحليل XML في الملف المرفوع.",
     "uploadvirus": "الملف يحتوي على فيروس! التفاصيل: $1",
     "uploadjava": "يحتوي ملف ZIP هذا على ملفات جافا .class.\nلا يسمح برفع ملفات جافا لأنها تتيح تخطي القيود الأمنية.",
     "upload-misc-error": "خطأ غير معروف في الرفع",
     "upload-misc-error-text": "حدث خطأ غير معروف أثناء عملية الرفع.\nمن فضلك تاكد أن المسار صحيح ومن الممكن الدخول عليه ثم حاول مرة أخرى.\nإذا استمرت المشكلة في الحدوث، اتصل [[Special:ListUsers/sysop|بإداري]].",
     "upload-too-many-redirects": "احتوى المسار تحويلات كثيرة جدا",
-    "upload-unknown-size": "حجم غير معروف",
     "upload-http-error": "صودف خطأ HTTP: $1",
     "upload-copy-upload-invalid-domain": "رفع النسخ غير متاح من هذا الموقع",
     "backend-fail-stream": "لا يمكن عرض الملف $1.",
     "img-auth-streaming": "عرض \"$1\".",
     "img-auth-public": "وظيفة img_auth.php هي لإخراج الملفات من ويكي سري.\nهذا الويكي مضبوط كويكي علني.\nلتأمين إضافي، img_auth.php تم تعطيلها.",
     "img-auth-noread": "لا يملك المستخدم صلاحية قراءة \"$1\".",
-    "img-auth-bad-query-string": "يحتوي المسار عبارة استعلام غير صالحة.",
     "http-invalid-url": "مسار غير صالح: $1",
     "http-invalid-scheme": "المسارات ذات البروتكول \"$1\" غير مدعومة.",
     "http-request-error": "فشل طلب HTTP لسبب غير معروف.",
     "filehist-dimensions": "الأبعاد",
     "filehist-filesize": "حجم الملف",
     "filehist-comment": "تعليق",
-    "filehist-missing": "ملف مفقود",
     "imagelinks": "استخدام الملف",
     "linkstoimage": "{{PLURAL:$1||الصفحة التالية تصل|الصفحتان التاليتان تصلان|ال$1 صفحات التالية تصل|ال$1 صفحة التالية تصل}} إلى هذا الملف:",
     "linkstoimage-more": "أكثر من {{PLURAL:$1||صفحة واحدة تصل|صفحتين تصلان|$1 صفحات تصل|$1 صفحة تصل}} إلى هذا الملف.\nالقائمة التالية تعرض فقط {{PLURAL:$1||أول صفحة تصل|أول صفحتين تصلان|أول $1 صفحات تصل|أول $1 صفحة تصل}} إلى هذا الملف.\n[[Special:WhatLinksHere/$2|قائمة كاملة]] متوفرة.",
     "download": "تنزيل",
     "unwatchedpages": "صفحات غير مراقبة",
     "listredirects": "عرض التحويلات",
+    "listduplicatedfiles": "قائمة الملفات مع المكررات",
     "unusedtemplates": "قوالب غير مستخدمة",
     "unusedtemplatestext": "هذه الصفحة تعرض كل الصفحات في نطاق {{ns:template}} غير المضمنة في صفحة أخرى.\nتذكر بأن تتحقق من الوصلات الأخرى للقوالب قبل حذفها.",
     "unusedtemplateswlh": "وصلات أخرى",
     "emailuser-title-notarget": "مراسلة المستخدم",
     "emailpage": "إرسال رسالة للمستخدم",
     "emailpagetext": "يمكنك استخدام الاستمارة بالأسفل لإرسال رسالة بريد إلكتروني إلى {{GENDER:$1|هذا المستخدم|هذه المستخدمة}}.\nسيظهر عنوان البريد الإلكتروني الذي أدخلته في [[Special:Preferences|تفضيلاتك]] كعنوان المرسل في البريد الإلكتروني، كي يستطيع المتلقي الرد عليك مباشرة.",
-    "usermailererror": "جسم البريد أرجع خطأ:",
     "defemailsubject": "رسالة {{SITENAME}} من المستخدم \"$1\"",
     "usermaildisabled": "بريد المستخدم الإلكتروني معطل",
     "usermaildisabledtext": "لا يمكنك إرسال بريد إلكتروني إلى مستخدمين آخرين على هذه الويكي",
     "noemailtitle": "لا يوجد عنوان بريد إلكتروني",
     "noemailtext": "لم يحدد هذا المستخدم عنوان بريد إلكتروني صحيح.",
-    "nowikiemailtitle": "لا بريد إلكتروني مسموح به",
     "nowikiemailtext": "هذا المستخدم اختار ألا يستقبل البريد الإلكتروني من المستخدمين الآخرين.",
     "emailnotarget": "المستلم ليس مستخدمًا موجودًا أو ليس مستخدمًا صحيحًا.",
     "emailtarget": "أدخل اسم مستخدم المستلم",
     "nowatchlist": "لا توجد مدخلات في قائمة مراقبتك.",
     "watchlistanontext": "الرجاء $1 لعرض أو تعديل الصفحات في قائمة مراقبتك.",
     "watchnologin": "غير مسجل الدخول",
-    "watchnologintext": "يجب أن تكون [[Special:UserLogin|مسجل الدخول]] لتعدل قائمة مراقبتك.",
     "addwatch": "إضافة إلى قائمة المراقبة",
     "addedwatchtext": "أضيفت الصفحة  \"[[:$1]]\" إلى [[Special:Watchlist|قائمة مراقبتك]].\nالتغييرات القادمة على هذه الصفحة وصفحة نقاشها سيتم وضعها هناك.",
     "removewatch": "إزالة من قائمة المراقبة",
     "watching": "يراقب...",
     "unwatching": "إزالة المراقبة...",
     "watcherrortext": "حدث خطأ أثناء تغيير إعدادات الرصد الخاصة بك \"$1\".",
-    "enotif_mailer": "نظام {{SITENAME}} البريدي للإخطارات",
     "enotif_reset": "علم على كل الصفحات كمزارة",
     "enotif_impersonal_salutation": "مستخدم {{SITENAME}}",
     "enotif_subject_deleted": "الصفحة {{SITENAME}} $1 حذفها {{الجنس: $2 | $2 }}",
     "excontent": "المحتوى كان: '$1'",
     "excontentauthor": "المحتوى كان: '$1' (والمساهم الوحيد كان '[[Special:Contributions/$2|$2]]')",
     "exbeforeblank": "المحتوى قبل الإفراغ كان: '$1'",
-    "exblank": "الصفحة كانت فارغة",
     "delete-confirm": "حذف \"$1\"",
     "delete-legend": "حذف",
     "historywarning": "'''تحذير:''' الصفحة التي توشك على حذفها لها تاريخ فيه {{PLURAL:$1||مراجعة واحدة|مراجعتان|$1 مراجعات|$1 مراجعة}} تقريبا:",
     "importunknownsource": "نوع مصدر استيراد مجهول",
     "importcantopen": "لم يمكن فتح ملف الاستيراد",
     "importbadinterwiki": "وصلة إنترويكي سيئة",
-    "importnotext": "فارغ أو لا نص",
     "importsuccess": "الاستيراد انتهى!",
-    "importhistoryconflict": "هناك مراجعة تاريخ متعارضة موجودة (ربما تكون قد استوردت هذه الصفحة من قبل)",
     "importnosources": "لم يتم تعريف مصادر للاستيراد عبر الويكي وعمليات رفع التاريخ المباشرة معطلة.",
     "importnofile": "لم يتم رفع ملف استيراد.",
     "importuploaderrorsize": "رفع ملف الاستيراد فشل.\nالملف أكبر من حجم الرفع المسموح.",
index d19963f..853c4d5 100644 (file)
     "accountcreatedtext": "ܐܬܒܪܝ ܚܘܫܒܢܐ ܕܡܦܠܚܢܐ ܠ $1.",
     "createaccount-title": "ܒܪܝܐ ܕܚܘܫܒܢܐ ܒ {{SITENAME}}",
     "loginlanguagelabel": "ܠܫܢܐ: $1",
+    "pt-login": "ܥܘܠ",
+    "pt-login-button": "ܥܘܠ",
+    "pt-createaccount": "ܒܪܝ ܚܘܫܒܢܐ",
+    "pt-userlogout": "ܦܠܘܛ",
     "changepassword": "ܫܚܠܦ ܡܠܬܐ ܕܥܠܠܐ",
     "resetpass_header": "ܫܚܠܦ ܡܠܬܐ ܕܥܠܠܐ ܕܚܘܫܒܢܐ",
     "oldpassword": "ܡܠܬܐ ܕܥܠܠܐ ܥܬܝܩܬܐ:",
     "rcnotefrom": "ܠܬܚܬ ܫܘܚܠܦ̈ܐ ܕܡܢ '''$2''' (ܥܕ '''$1''' ܡܬܚܙܝܢ̈ܐ).",
     "rclistfrom": "ܚܘܝ ܫܘܚܠܦ̈ܐ ܚܕ̈ܬܐ ܡܢ $1",
     "rcshowhideminor": "$1 ܫܘܚܠܦ̈ܐ ܙܥܘܪ̈ܐ",
+    "rcshowhideminor-show": "ܚܘܝ",
+    "rcshowhideminor-hide": "ܛܫܝ",
     "rcshowhidebots": "$1 ܒܘܬ̈ܐ (Bots)",
+    "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": "ܬܫܥܝܬܐ",
     "uploadbtn": "ܐܣܩ ܠܦܦܐ",
     "uploadnologin": "ܠܝܬܝܟ ܥܠܝܠܐ",
     "uploaderror": "ܦܘܕܐ ܒܡܣܩܬܐ",
-    "uploadlog": "ܣܓܠܐ ܕܣܠܩܐ",
     "uploadlogpage": "ܣܓܠܐ ܕܣܠܩܐ",
     "filename": "ܫܡܐ ܕܠܦܦܐ",
     "filedesc": "ܦܣܝܩܬ̈ܐ",
     "upload-proto-error": "ܦܪܘܛܘܩܘܠ ܠܐ ܬܪܝܨܐ",
     "upload-file-error": "ܦܘܕܐ ܓܘܝܐ",
     "upload-misc-error": "ܦܘܕܐ ܠܐ ܝܕܝܥܐ ܒܐܣܩܬܐ ܕܠܦܦܐ",
-    "upload-unknown-size": "ܥܓܪܐ ܠܐ ܝܕܝܥܐ",
     "img-auth-nofile": "ܠܦܦܐ \"$1\" ܠܝܬ ܠܗ ܐܝܬܘܬܐ.",
     "http-read-error": "HTTP ܦܘܕܐ ܒܩܪܝܬܐ.",
     "http-curl-error": "ܦܘܕܐ ܒܫܟܚܐ ܕURL: $1",
     "nowatchlist": "ܠܝܬ ܠܟ ܡܕܡ ܒܪ̈ܗܝܬܐ ܕܝܠܟ",
     "watchlistanontext": "$1 ܠܚܙܝܐ ܐܘ ܫܚܠܦܬܐ ܕܦܐܬܬ̈ܐ ܒܪ̈ܗܝܬܟ.",
     "watchnologin": "ܠܝܬܝܟ ܥܠܝܠܐ",
-    "watchnologintext": "ܐܠܨܐ ܕܬܗܘܐ [[Special:UserLogin|ܥܠܝܠܐ]] ܠܫܚܠܦܬܐ ܕܪ̈ܗܝܬܟ.",
     "addwatch": "ܐܘܣܦ ܥܠ ܪ̈ܗܝܬܝ",
     "addedwatchtext": "ܦܐܬܐ ܕ\"[[:$1]]\" ܐܬܬܘܣܦܬ ܠ[[Special:Watchlist|ܪ̈ܗܝܬܟ]].\nܐܝܢܐ ܫܘܚܠܦܐ ܥܠ ܦܐܬܐ ܗܕܐ ܒܕܥܬܝܕ ܬܬܓܠܚ ܥܡ ܦܐܬܐ ܕܡܡܠܠܐ ܕܝܠܗ ܬܡܢ.",
     "removewatch": "ܫܩܘܠ ܡܢ ܪ̈ܗܝܬܝ",
     "confirm": "ܫܪܪ",
     "excontent": "ܚܒܝܫܬ̈ܐ ܗܘ̈ܝ: '$1'",
     "excontentauthor": "ܚܒܝܫܬ̈ܐ ܗܘ̈ܝ: '$1' (ܘܫܘܬܦܢܐ ܝܚܝܕܝܐ ܗܘܐ '[[Special:Contributions/$2|$2]]')",
-    "exblank": "ܦܐܬܐ ܣܦܝܩܬܐ ܗܘܐ",
     "delete-confirm": "ܫܘܦ \"$1\"",
     "delete-legend": "ܫܘܦ",
     "actioncomplete": "ܥܡܠܝܬܐ ܓܡܪܬ",
     "import-upload-filename": "ܫܡܐ ܕܠܦܦܐ:",
     "import-revision-count": "$1 {{PLURAL:$1|ܬܢܝܬܐ |ܬܢܝܬ̈ܐ}}",
     "importnopages": "ܠܝܬ ܦܐܬܬ̈ܐ ܠܡܥܠܢܘܬܐ.",
-    "importnotext": "ܣܦܝܩܐ ܐܘ ܠܝܬ ܒܗ ܟܬܒܬܐ",
     "importsuccess": "ܡܥܠܢܘܬܐ ܓܡܪܬ",
     "import-noarticle": "ܠܝܬ ܦܐܬܬ̈ܐ ܠܡܥܠܢܘܬܐ!",
     "import-upload": "ܐܣܩ ܓܠܝܬ̈ܐ  ܕ XML",
index 7dd1c4d..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": "راقب",
index ae29d9e..64f5e01 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": "আপোনাৰ তথ্যসমূহ তলত লিখক।",
     "accountcreatedtext": "[[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|talk]])ৰ কাৰণে সদস্য একাউণ্ট সৃষ্টি কৰা হ'ল।",
     "createaccount-title": "{{SITENAME}}ৰ কাৰণে একাউণ্ট সৃষ্টি কৰক।",
     "createaccount-text": "আপোনাৰ ই-মেইল ঠিকনাৰ কাৰণে {{SITENAME}} ($4)ত \"$2\" নামৰ কোনোবাই, \"$3\" গুপ্তশব্দ দি সদস্যভুক্তি কৰিছে। অনুগ্ৰহ কৰি আপুনি প্ৰৱেশ কৰক আৰু গুপ্তশব্দটো সলনি কৰক।\n\nযদি এইয়া ভুলতে হৈছে, তেনেহলে আপুনি এই বাৰ্তাটো অবজ্ঞা কৰিব পাৰে ।",
-    "usernamehasherror": "সদস্যনামত হেচ্‌ চিহ্ন থাকিব নোৱাৰে",
     "login-throttled": "আপুনি স‍ম্প্ৰতি অজস্ৰবাৰ লগ্‌-ইনৰ প্ৰয়াস কৰিছে ।\nঅনুগ্ৰহ কৰি $1 সময়ৰ পিছত আকৌ চেষ্টা কৰক ।",
     "login-abort-generic": "আপোনাৰ প্ৰৱেশ অসফল হৈছে- বাতিল কৰা হ’ল",
     "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": "ইতিবৃত্ত",
     "upload-permitted": "অনুমোদিত ফাইল ধৰণ: $1",
     "upload-preferred": "বাঞ্ছিত ফাইল ধৰণ: $1",
     "upload-prohibited": "বঞ্চিত ফাইল ধৰণ: $1",
-    "uploadlog": "আপল’ড ল’গ",
     "uploadlogpage": "আপল’ড ল’গ",
     "uploadlogpagetext": "সকলোতকৈ শেহতীয়াভাৱে আপল’ড কৰা ফাইলসমূহৰ তালিকা তলত দিয়া হৈছে ।\nঅধিক দৃশ্যগত পৰ্য্যালোচনাৰ বাবে [[Special:NewFiles|নতুন ফাইলৰ গেলাৰী]] চাওক ।",
     "filename": "ফাইলনাম",
     "filereuploadsummary": "ফাইলত সালসলনিসমূহ",
     "filestatus": "স্বত্বাধিকাৰ স্থিতি:",
     "filesource": "উৎস:",
-    "uploadedfiles": "আপলোড কৰা ফাইলসমূহ",
     "ignorewarning": "সতৰ্কবাণী আওকাণ কৰি ফাইল সংৰক্ষণ কৰক",
     "ignorewarnings": "সকলো সতৰ্কবাণী আওকাণ কৰক",
     "minlength1": "ফাইলনাম কমেও এটা আখৰৰ হ'ব লাগে ।",
     "overwroteimage": "\"[[$1]]\" ৰ এটা নতুন সংস্কৰণ আপল’ড কৰা হৈছে",
     "uploaddisabled": "আপল’ড নিষ্ক্ৰিয় হৈ আছে",
     "copyuploaddisabled": "ইউ.আৰ.এল.ৰ মাধ্যমেৰে আপল’ড নিষ্ক্ৰিয় হৈ আছে ।",
-    "uploadfromurl-queued": "আপোনাৰ আপল’ড শাৰীত ৰখা হৈছে ।",
     "uploaddisabledtext": "ফাইল আপল’ড নিষ্ক্ৰিয় হৈ আছে ।",
     "php-uploaddisabledtext": "পি.এইচ.পি.ত ফাইল আপল’ড নিষ্ক্ৰিয় হৈ আছে ।\nঅনুগ্ৰহ কৰি file_uploads ছেটিং পৰীক্ষা কৰক ।",
     "uploadscripted": "এই ফাইলত HTML বা স্ক্ৰিপ্ত ক’ড আছে যিবোৰ ৱেব ব্ৰাউজাৰে ভুলকৈ ব্যাখ্যা কৰিব পাৰে ।",
     "upload-misc-error": "অজ্ঞাত আপল’ড ত্ৰুটি",
     "upload-misc-error-text": "আপল’ডৰ সময়ত কোনো অজ্ঞাত সমস্যাই দেখা দিছে ।\nURL টোৰ বৈধতা বিচাৰ কৰি পুনৰ চেষ্টা কৰক ।\nযদি তাৰ পিছতো সমস্যা হয়, তেন্তে এজন [[Special:ListUsers/sysop|প্ৰশাসকৰ]] লগত যোগাযোগ কৰক ।",
     "upload-too-many-redirects": "এই URL টোত অতি বেছি পুনৰ্নিৰ্দেশনা আছে",
-    "upload-unknown-size": "অজ্ঞাত আকাৰ",
     "upload-http-error": "এটা HTTP ত্ৰুটিয়ে দেখা দিছে: $1",
     "upload-copy-upload-invalid-domain": "এই ডমেইনত কপী আপল'ড নাপাব।",
     "backend-fail-stream": "$1 ফাইলটো ষ্ট্ৰীম কৰিব পৰা নগ'ল।",
     "img-auth-streaming": "\"$1\" স্ট্ৰিম হৈ আছে ।",
     "img-auth-public": "img_auth.phpৰ কাম হৈছে ব্যক্তিগত ৱিকিৰ পৰা ফাইল বাহিৰলৈ পঠোৱা ।\nএই ৱিকিক ৰাজহুৱা ৱিকিৰূপে কনফিগাৰ কৰা হৈছে ।\nসুৰক্ষাৰ বাবে img_auth.php নিষ্ক্ৰিয় কৰা হ'ল ।",
     "img-auth-noread": "সদস্যৰ \"$1\" ত প্ৰৱেশাধিকাৰ নাই ।",
-    "img-auth-bad-query-string": "এই ইউ.আৰ.এল.-ত অযুক্তিসংগত কুৱেৰী ষ্ট্ৰিং আছে ।",
     "http-invalid-url": "অবৈধ URL: $1",
     "http-invalid-scheme": "\"$1\" আঁচনি থকা URLসমূহ সমৰ্থিত নহয় ।",
     "http-request-error": "অজ্ঞাত ত্ৰুটিৰ বাবে HTTP অনুৰোধ ব্যাহত হৈছে ।",
     "filehist-dimensions": "আকাৰ",
     "filehist-filesize": "ফাইলৰ আকাৰ (বাইট)",
     "filehist-comment": "মন্তব্য",
-    "filehist-missing": "ফাইল সন্ধানহীন",
     "imagelinks": "ফাইল ব্যৱহাৰ",
     "linkstoimage": "তলত দিয়া {{PLURAL:$1|পৃষ্ঠাটো|$1 পৃষ্ঠাবোৰ}} এই ফাইলৰ লগত জড়িত:",
     "linkstoimage-more": "এই ফাইলৰ লগত $1ৰো বেছি {{PLURAL:$1|পৃষ্ঠা সংযোগ|পৃষ্ঠা সংযোগ}} হৈ আছে ।\nতলৰ তালিকাত {{PLURAL:$1|প্ৰথম পৃষ্ঠা সংযোগ|প্ৰথম $1 পৃষ্ঠা সংযোগ}} দেখুওৱা হৈছে ।\nএখন [[Special:WhatLinksHere/$2|সম্পূৰ্ণ তালিকা]]ও পাব ।",
     "protectedpages-cascade": "কেৱল প্ৰপাতাকাৰ সুৰক্ষা",
     "protectedpages-noredirect": "পুনঃনিৰ্দেশ লুকুৱাওক",
     "protectedpagesempty": "এই পাৰামিটাৰবোৰেৰে কোনো পৃষ্ঠা এতিয়া সুৰক্ষিত কৰা হোৱা নাই ।",
+    "protectedpages-page": "পৃষ্ঠা",
+    "protectedpages-expiry": "ম্যাদ উকলিব",
     "protectedtitles": "সুৰক্ষিত শিৰোনামাসমূহ",
     "protectedtitlesempty": "এই পাৰামিটাৰবোৰেৰে কোনো শিৰোনামা এতিয়া সুৰক্ষিত কৰা হোৱা নাই ।",
     "listusers": "সদস্য তালিকা",
     "emailuser-title-notarget": "ব্যৱহাৰকাৰী ই-পত্ৰ প্ৰেৰণ কৰক",
     "emailpage": "ই-পত্ৰ ব্যৱহাৰকাৰী",
     "emailpagetext": "তলৰ প্ৰপত্ৰখন ব্যৱহাৰ কৰি আপুনি এই {{GENDER:$1|সদস্যজনলৈ}} ই-মেইল পঠাব পাৰে ।\nআপুনি [[Special:Preferences|আপোনাৰ সদস্য পছন্দসমূহ]]ত প্ৰৱেশ কৰা ই-মেইল ঠিকনাটো প্ৰেৰকৰ ঠিকনা হিছাপে দেখা যাব, যাতে মেইলৰ প্ৰাপকে আপোনাক উত্তৰ দিব পাৰে ।",
-    "usermailererror": "মেইল বিষয়বস্তুৰ ত্ৰুটি:",
     "defemailsubject": "\"$1\" সদস্যৰ পৰা {{SITENAME}} ই-মেইল",
     "usermaildisabled": "ব্যৱহাৰকাৰীৰ ই-মেইল নিষ্ক্ৰিয়",
     "usermaildisabledtext": "আপুনি এই ৱিকিত আন সদস্যলৈ ই-পত্ৰ পঠিয়াব নোৱাৰে",
     "noemailtitle": "কোনো ই-পত্ৰ ঠিকনা নাই",
     "noemailtext": "এই সদস্যজনে কোনো বৈধ ই-পত্ৰ ঠিকনা নিৰ্বাচন কৰা নাই ।",
-    "nowikiemailtitle": "কোনো ই-পত্ৰ অনুমোদিত নহয়",
     "nowikiemailtext": "এই সদস্যজনে আন সদস্যৰপৰা ই-পত্ৰ পাবলৈ বিচৰা নাই ।",
     "emailnotarget": "পাওঁতাৰ অস্তিত্বহীন বা অবৈধ সদস্যনাম",
     "emailtarget": "পাওঁতাৰ সদস্যনাম ভৰ্তি কৰক",
     "nowatchlist": "আপোনাৰ নিৰীক্ষণ তালিকাত একো নাই ।",
     "watchlistanontext": "আপোনাৰ লক্ষ্য তালিকাত থকা বস্তুবোৰ চাবলৈ বা সম্পাদনা কৰিবলৈ অনুগ্ৰহ কৰি $1 কৰক।",
     "watchnologin": "প্ৰৱেশ কৰা নাই",
-    "watchnologintext": "নিৰীক্ষণ তালিকা পৰিৱৰ্তন কৰিবলৈ আপুনি আগতে [[Special:UserLogin|প্ৰৱেশ]] কৰিব লাগিব ।",
     "addwatch": "লক্ষ্য-তালিকাত অন্তৰ্ভুক্ত কৰক",
     "addedwatchtext": "আপোনাৰ [[Special:Watchlist|লক্ষ্য তালিকাত ]] \"[[:$1]]\" পৃষ্ঠাটো অন্তৰ্ভুক্ত কৰা হ'ল।\nভৱিষ্যতে এই পৃষ্ঠা বা ইয়াৰ আলোচনা পৃষ্ঠাত হোৱা সাল-সলনি আপুনি আপোনাৰ লক্ষ্য তালিকাত দেখিব।",
     "removewatch": "লক্ষ্য-তালিকাৰ পৰা আঁতৰাওক",
     "watching": "চকু দিয়া হৈছে.....",
     "unwatching": "আঁতৰোৱা হৈ আছে.....",
     "watcherrortext": "\"$1\"ৰ বাবে আপোনাৰ নিৰীক্ষণ তালিকাৰ ছেটিং সলনি কৰোঁতে এটা সমস্যাই দেখা দিছে ।",
-    "enotif_mailer": "{{SITENAME}} জাননী ই-পত্ৰ প্ৰেৰক",
     "enotif_reset": "সকলো পৃষ্ঠা পৰিদৰ্শিত বুলি চিহ্নিত কৰক",
     "enotif_impersonal_salutation": "{{SITENAME}} সদস্য",
     "enotif_subject_deleted": "{{SITENAME}} পৃষ্ঠা $1 {{gender:$2|$2}} ৰ দ্বাৰা বিলোপ কৰা হ’ল",
     "excontent": "বিষয়বস্তু আছিল: \"$1\"",
     "excontentauthor": "বিষয়বস্তু আছিল: \"$1\" (আৰু একমাত্ৰ অৱদানকাৰী আছিল \"[[Special:Contributions/$2|$2]]\")",
     "exbeforeblank": "খালী কৰাৰ আগেয়ে বিষয়বস্তু আছিল: $1",
-    "exblank": "পৃষ্ঠা খালি আছিল",
     "delete-confirm": "\"$1\" বিলোপ কৰক",
     "delete-legend": "বিলোপ কৰক",
     "historywarning": "'''সাৱধান:''' আপুনি বিলোপ কৰিব বিচৰা পৃষ্ঠাখনৰ ইতিহাসত প্ৰায় {{PLURAL:$1|সংস্কৰণ|সংস্কৰণ}} আছে:",
     "importunknownsource": "অজ্ঞাত আমদানি উৎসৰ প্ৰকাৰ",
     "importcantopen": "আমদানি ফাইল খুলিব পৰা নগ'ল",
     "importbadinterwiki": "আন্ত:ৱিকি সংযোগ বেয়া",
-    "importnotext": "খালী বা পাঠ বিহীন",
     "importsuccess": "আমদানি সমাপ্ত !",
-    "importhistoryconflict": "পৰস্পৰবিৰোধী ইতিহাস সংশোধনী আছে (এই পৃষ্ঠা আগতেও আমদানি কৰা হ'ব পাৰে)",
     "importnosources": "কোনো আন্তঃৱিকি আমদানি উৎসৰ সংজ্ঞা দিয়া হোৱা নাই আৰু প্ৰত্যক্ষ ইতিহাস আপল'ড নিষ্ক্ৰিয় কৰা হৈছে ।",
     "importnofile": "কোনো আমদানি নথি আপল'ড কৰা হোৱা নাই ।",
     "importuploaderrorsize": "আমদানি নথিৰ আপল'ড অসফল হৈছে ।\nঅনুমোদিত আপল'ড নথিতকৈ এই নথিৰ আকাৰ ডাঙৰ ।",
index 86fb62e..ed3bbf0 100644 (file)
     "permalink": "Enllaz permanente",
     "print": "Imprentar",
     "view": "Ver",
+    "view-foreign": "Ver en $1",
     "edit": "Editar",
+    "edit-local": "Editar la descripción llocal",
     "create": "Crear",
+    "create-local": "Amestar descripción llocal",
     "editthispage": "Editar esta páxina",
     "create-this-page": "Crear esta páxina",
     "delete": "Desaniciar",
     "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.",
     "accountcreatedtext": "Creóse la cuenta d'usuariu pa [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|alderique]]).",
     "createaccount-title": "Creación de cuenta pa {{SITENAME}}",
     "createaccount-text": "Daquién creó una cuenta cola to direición de corréu electrónicu en {{SITENAME}} ($4) col nome «$2», y cola contraseña «$3».\nAgora tendríes d'aniciar sesión y camudar la contraseña.\n\nPues escaecer esti mensaxe si esta cuenta creóse por error.",
-    "usernamehasherror": "El nome d'usuariu nun pue contener caráuteres «hash»",
     "login-throttled": "Ficisti demasiaos intentos d'aniciu de sesión recientes.\nPor favor espera $1 enantes d'intentalo otra vuelta.",
     "login-abort-generic": "Falló la identificación - Encaboxao",
     "loginlanguagelabel": "Llingua: $1",
     "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",
     "upload-permitted": "Menes d'archivu permitíes: $1.",
     "upload-preferred": "Menes d'archivu preferíes: $1.",
     "upload-prohibited": "Menes d'archivu prohibíes: $1.",
-    "uploadlog": "rexistru de xubíes",
     "uploadlogpage": "Rexistru de xubíes",
     "uploadlogpagetext": "Abaxo amuésase una llista de les xubíes d'archivos más recientes.\nMira la [[Special:NewFiles|galería d'archivos nuevos]] pa una güeyada más visual.",
     "filename": "Nome del ficheru",
     "filereuploadsummary": "Cambios del ficheru:",
     "filestatus": "Estáu de Copyright:",
     "filesource": "Fonte:",
-    "uploadedfiles": "Archivos xubíos",
     "ignorewarning": "Inorar l'avisu y grabar l'archivu de toes formes",
     "ignorewarnings": "Inorar tolos avisos",
     "minlength1": "Los nomes d'archivu han tener a lo menos una lletra.",
     "overwroteimage": "xubió una versión nueva de \"[[$1]]\"",
     "uploaddisabled": "Deshabilitaes les xubíes",
     "copyuploaddisabled": "Xubir por URL ta desactivao.",
-    "uploadfromurl-queued": "La to xubía ta na cola.",
     "uploaddisabledtext": "Les xubíes de ficheros tán desactivaes.",
     "php-uploaddisabledtext": "Les xubíes de ficheros tan desactivaes en PHP.\nPor favor, comprueba la configuración de file_uploads.",
     "uploadscripted": "Esti ficheru contién códigu HTML o scripts que se puen interpretar equivocadamente por un navegador.",
     "upload-misc-error": "Error de xubida desconocíu",
     "upload-misc-error-text": "Hebo un error desconocíu na xubida del ficheru.\nPor favor comprueba que l'URL ye válidu y accesible, y inténtalo otra vuelta.\nSi'l problema persiste, contauta con un [[Special:ListUsers/sysop|alministrador]] del sistema.",
     "upload-too-many-redirects": "La URL contenía demasiaes redireiciones",
-    "upload-unknown-size": "Tamañu desconocíu",
     "upload-http-error": "Hebo un error HTTP: $1",
     "upload-copy-upload-invalid-domain": "La xubida de copies nun ta disponible dende esti dominiu.",
     "backend-fail-stream": "Nun se pudo tresmitir el ficheru $1.",
     "img-auth-streaming": "Unviando \"$1\".",
     "img-auth-public": "La función de img_auth.php ye sacar ficheros d'una wiki privada.\nEsta wiki ta configurada como wiki pública.\nPa una meyor seguridá, img_auth.php ta desactiváu.",
     "img-auth-noread": "L'usuariu nun tien accesu pa lleer \"$1\".",
-    "img-auth-bad-query-string": "La URL tien una cadena de consulta inválida.",
     "http-invalid-url": "URL inválida: $1",
     "http-invalid-scheme": "Les URLs col esquema \"$1\" nun tienen sofitu.",
     "http-request-error": "La llamada HTTP fallló por un error desconocíu.",
     "filehist-dimensions": "Dimensiones",
     "filehist-filesize": "Tamañu del ficheru",
     "filehist-comment": "Comentariu",
-    "filehist-missing": "Falta ficheru",
     "imagelinks": "Usu del ficheru",
     "linkstoimage": "{{PLURAL:$1|La páxina siguiente enllacia|Les páxines siguientes enllacien}} a esti ficheru:",
     "linkstoimage-more": "Más de $1 {{PLURAL:$1|páxina enllacia|páxines enllacien}} a esti archivu.\nLa llista siguiente amuesa{{PLURAL:$1|'l primer enllaz de páxina| los primeros $1 enllaces de páxina}} a esti archivu namái.\nHai disponible una [[Special:WhatLinksHere/$2|llista completa]].",
     "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",
+    "listgrouprights-namespaceprotection-header": "Torgues d'espaciu de nomes",
+    "listgrouprights-namespaceprotection-namespace": "Espaciu de nomes",
+    "listgrouprights-namespaceprotection-restrictedto": "Permisu(os) d'edición del usuariu",
+    "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 <code><nowiki>__NOINDEX__</nowiki></code> (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 <code><nowiki>__INDEX__</nowiki></code> (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 <code>$wgMaxArticleSize</code>; 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 <code>{{{Daqué}}}</code>), la páxina ye mayor que <code>$wgMaxArticleSize</code>.",
+    "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 <code><nowiki>__HIDDENCAT__</nowiki></code>, 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",
     "emailuser-title-notarget": "Unviar un corréu electrónicu a un usuariu",
     "emailpage": "Envigar un corréu electrónicu a un usuariu",
     "emailpagetext": "Pues usar el formulariu de más abaxo pa unviar un corréu electrónicu a {{GENDER:$1|esti usuariu|esta usuaria}}.\nLa direición de corréu electrónicu qu'especificasti nes [[Special:Preferences|tos preferencies d'usuariu]] va apaecer como la direición \"Dende\" del corréu, pa que'l que lo recibe seya quien a respondete direutamente a ti.",
-    "usermailererror": "L'operador de corréu devolvió un error:",
     "defemailsubject": "Corréu electrónicu del usuariu «$1» de {{SITENAME}}",
     "usermaildisabled": "Corréu del usuariu desactiváu",
     "usermaildisabledtext": "Nun pues unviar corréu a otros usuarios d'esta wiki",
     "noemailtitle": "Ensin direición de corréu",
     "noemailtext": "Esti usuariu nun especificó una direición de corréu válida.",
-    "nowikiemailtitle": "Nun se permite'l corréu electrónicu",
     "nowikiemailtext": "Esti usuariu nun quier recibir correos d'otros usuarios.",
     "emailnotarget": "Nome d'usuariu del destinatariu non esistente o inválidu.",
     "emailtarget": "Escribi'l nome d'usuariu del destinatariu",
     "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",
     "watching": "Vixilando...",
     "unwatching": "Dexando de vixilar...",
     "watcherrortext": "Hebo un fallu al camudar la configuración de la to llista de vixilancia pa «$1».",
-    "enotif_mailer": "Notificación de corréu de {{SITENAME}}",
     "enotif_reset": "Marcar toles páxines visitaes",
     "enotif_impersonal_salutation": "Usuariu de {{SITENAME}}",
     "enotif_subject_deleted": "{{GENDER:$2|$2}} desanició la páxina «$1» de {{SITENAME}}",
     "excontent": "el conteníu yera: '$1'",
     "excontentauthor": "el conteníu yera: '$1' (y l'únicu autor yera '[[Special:Contributions/$2|$2]]')",
     "exbeforeblank": "el conteníu enantes de dexar en blanco yera: '$1'",
-    "exblank": "la páxina taba vacia",
     "delete-confirm": "Desaniciar «$1»",
     "delete-legend": "Desaniciar",
     "historywarning": "'''Avisu:'''' La páxina que vas desaniciar tien un historial con aproximadamente $1 {{PLURAL:$1|revisión|revisiones}}:",
     "importunknownsource": "Triba d'orixe d'importación desconocida",
     "importcantopen": "Nun se pudo abrir el ficheru d'importación",
     "importbadinterwiki": "Enllaz interwiki incorreutu",
-    "importnotext": "Vaciu o ensin testu",
     "importsuccess": "¡Importación finalizada!",
-    "importhistoryconflict": "Existe un conflictu na revisión del historial (seique esta páxina fuera importada previamente)",
     "importnosources": "Nun se definió l'orixe de la importación treswiki y les xubíes direutes del historial tán deshabilitaes.",
     "importnofile": "Nun se xubió nengún archivu d'importación.",
     "importuploaderrorsize": "Falló la xubida del archivu d'importación. L'archivu ye más grande que'l tamañu permitíu de xubida.",
index 0355847..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á",
index 49799f0..1c1ce0e 100644 (file)
     "accountcreatedtext": "$1 üçün istifadəçi hesabı yaradıldı.",
     "createaccount-title": "{{SITENAME}} hesabın yaradılması",
     "createaccount-text": "Biriləri {{SITENAME}} saytında ($4) sizin e-poçt ünvanınızdan istifadə edərək, parolu \"$3\" olan, \"$2\" adlı bir hesab yaratdı.\n\nSayta daxil olmalı və parolunuzu dəyişdirməlisiniz.\n\nƏgər istifadəçi hesabını səhvən yaratmısınızsa, bu mesajı gözardı edə bilərsiniz.",
-    "usernamehasherror": "İstifadəçi adında \"diyez\" simvolunun istifadəsi mümkün deyil",
     "login-throttled": "Sistemə daxil olmaq üçün həddən artıq cəhd etmisiniz.\nYeni cəhd etməzdən əvvəl bir qədər gözləyin.",
     "login-abort-generic": "Giriş uğursuz alındı - Rədd",
     "loginlanguagelabel": "Dil: $1",
     "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",
     "upload-permitted": "İcazə verilən fayl tipləri: $1.",
     "upload-preferred": "İcazə verilən fayl tipləri: $1.",
     "upload-prohibited": "İcazə verilməyən fayl tipləri: $1.",
-    "uploadlog": "yükləmə qeydi",
     "uploadlogpage": "Yükləmə qeydləri",
     "uploadlogpagetext": "Aşağıda ən yeni yükləmə jurnal qeydləri verilmişdir.",
     "filename": "Fayl adı",
     "filereuploadsummary": "Fayl dəyişiklikləri:",
     "filestatus": "Müəllif statusu:",
     "filesource": "Mənbə:",
-    "uploadedfiles": "Yüklənmiş fayllar",
     "ignorewarning": "Xəbərdarlıqlara əhəmiyyət vermə və faylı saxla",
     "ignorewarnings": "Bütün xəbərdarlıqlara məhəl qoymamaq",
     "minlength1": "Fayl adı ən azı bir hərfdən ibarət olmalıdır.",
     "overwroteimage": "\"[[$1]]\"-in yeni versiyası yükləndi",
     "uploaddisabled": "Yükləmə baş tutmadı",
     "copyuploaddisabled": "URL-dən yükləmə baş tutmadı.",
-    "uploadfromurl-queued": "Yükləməniz növbə gözləyir",
     "uploaddisabledtext": "Fayl yüklənməsi baş tutmadı.",
     "uploadvirus": "Faylda virus var! \nDetallar: $1",
     "upload-source": "Mənbə faylı",
     "upload-file-error": "Daxili xəta",
     "upload-misc-error": "Naməlum yükləmə xətası",
     "upload-too-many-redirects": "URL-də xeyli yönləndirmə var",
-    "upload-unknown-size": "Naməlum həcm",
     "upload-http-error": " HTTP xətası var : $1",
     "backend-fail-notexists": "\"$1\" faylı mövcud deyil",
     "backend-fail-delete": "\"$1\" faylı sililmədi.",
     "img-auth-nofile": "Fayl \"$1\" mövcud deyil.",
     "img-auth-streaming": "\"$1\" axını.",
     "img-auth-noread": "İstifadəçinin \"$1\"i oxumaq hüququ yoxdur.",
-    "img-auth-bad-query-string": "URL ünvanda yanlış axtarış sətri var.",
     "http-invalid-url": "Səhv URL: $1",
     "http-read-error": "HTTP oxuma xətası",
     "http-timed-out": "HTTP istəyinin vaxtı bitdi.",
     "filehist-dimensions": "Ölçülər",
     "filehist-filesize": "Faylın həcmi",
     "filehist-comment": "Şərh",
-    "filehist-missing": "Fayl çatışmır",
     "imagelinks": "Fayl keçidləri",
     "linkstoimage": "{{PLURAL:$1|səhifə|$1 səhifə}} bu fayla istinad edir:",
     "nolinkstoimage": "Bu fayla keçid verən səhifə yoxdur.",
     "mailnologin": "Ünvan yoxdur",
     "emailuser": "İstifadəçiyə e-məktub göndər",
     "emailpage": "İstifadəçiyə e-məktub yolla",
-    "usermailererror": "Elektron poçtla məlumat göndərilən zaman xəta baş vermişdir:",
     "defemailsubject": "\"$1\" adlı istifadəçidən {{SITENAME}} e-məktubu",
     "usermaildisabled": "İstifadəçi e-maili işləmir",
     "noemailtitle": "E-məktub ünvanı yoxdur",
     "noemailtext": "Bu istifadəçi işlək e-məktub ünvanını qeyd etməmişdir.",
-    "nowikiemailtitle": "E-poçtlara icazə verilmir",
     "emailtarget": "Qəbul edən istifadəçinin adını daxil edin",
     "emailusername": "İstifadəçi adı:",
     "emailusernamesubmit": "Göndər",
     "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",
     "watchlist-options": "İzləmə siyahısının nizamlamaları",
     "watching": "İzlənilir...",
     "unwatching": "İzlənilmir...",
-    "enotif_mailer": "{{SITENAME}} Bildiriş Xidməti",
     "enotif_reset": "Baxılmış bütün səhifələri işarələ.",
     "enotif_impersonal_salutation": "{{SITENAME}} istifadəçisi",
     "enotif_lastvisited": "Sonuncu ziyarətinizdən indiyədək olan bütün dəyişiklikləri görmək üçün baxın: $1.",
     "excontent": "Köhnə məzmun: '$1'",
     "excontentauthor": "tərkib: '$1' (və '[[Special:Contributions/$2|$2]]' tarixçədə fəaliyyəti qeyd edilən yeganə istifadəçidir)",
     "exbeforeblank": "Silinmədən əvvəlki məzmun: '$1'",
-    "exblank": "səhifə boş",
     "delete-confirm": "Silinən səhifə: \"$1\"",
     "delete-legend": "Sil",
     "historywarning": "'''Xəbərdarlıq:''' Silinəcək səhifənin tarixçəsində qeyd olunmuş $1 {{PLURAL:$1|redaktə|redaktə}} var:",
     "importfailed": "Uğursuz çıxarış: <nowiki>$1</nowiki>",
     "importcantopen": "Çıxarılacaq fayl açılmadı",
     "importbadinterwiki": "Yanlış interviki keçidi",
-    "importnotext": "Boş və ya mətn yoxdur",
     "importsuccess": "Çıxarma başa çatdı!",
     "import-noarticle": "Çıxarılacaq səhifə yoxdur!",
     "xml-error-string": "$1 $2 sətrində, $3 sütünunda ($4 bayt): $5",
index 45ff4b7..ca4fab6 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": "دَییشدیر",
     "accountcreatedtext": "[[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|دانیشیق]]) ایستیفاده‌چی حسابی یارادیلیب‌دیر.",
     "createaccount-title": "{{SITENAME}} اوچون حساب یارادیلماسی",
     "createaccount-text": "بیر کس، سیزین ایمیل آدرسینیزه {{SITENAME}} ($4) سایتیندا «$2» آدی و «$3» رمزی ایله بیر حساب آچیب‌دیر. سیز گرک گیریش ائدیب و رمزینیزی ایندی دَییشدیره‌سیز.\n\nبو حساب یانلیش دوزلیب‌سه، بو مئساژا محل قویمایابیلرسیز.",
-    "usernamehasherror": "ایستیفاده‌چی آدیندا hash حرفلری اولا بیلمز",
     "login-throttled": "سیزین چوخ گیریش چالیشماغینیز اولوب‌دور.\nلوطفاً یئنی‌دن چالیشماق‌دان اؤنجه بیر آز دؤزون.",
     "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": "ایستیفاده‌چی صحیفه‌لری",
     "upload-permitted": "ایجازه وئریلن فايل تیپلری: $1.",
     "upload-preferred": "ایجازه وئریلن فايل تیپلری: $1.",
     "upload-prohibited": "ایجازه وئریلمه‌ين فايل تیپلری: $1.",
-    "uploadlog": "يوکله‌مه قئيدی",
     "uploadlogpage": "یوکلمه قئیدلری",
     "uploadlogpagetext": "آشاغیدا ان سون یوکله‌نیلن فایل‌لارین لیستی گؤستریلیر.\nداها گؤرونوش‌لو گؤسترمک اوچون، [[Special:NewFiles|یئنی فایل‌لار گالئری‌سینه]] باخین.",
     "filename": "فایل آدی",
     "filereuploadsummary": "فایل دَییشیکلری:",
     "filestatus": "مؤلف حوقوقلاری:",
     "filesource": "قایناق:",
-    "uploadedfiles": "یوکلنمیش فایللار‌",
     "ignorewarning": "خبردارلیقلارا اهمیت وئرمه و فايلی ساخلا",
     "ignorewarnings": "بوتون خبردارلیقلارا محل قويماماق",
     "minlength1": "فايل آدی ان آزی بیر حرفدن عبارت اولمالیدیر.",
     "overwroteimage": "\"[[$1]]\"-این یئنی نوسخه سی یوکلندی",
     "uploaddisabled": "يوکله‌مه باش توتمادی",
     "copyuploaddisabled": "اینترنت آدرسی ایله یوکلمه باش توتمادی.",
-    "uploadfromurl-queued": "يوکله‌مه‌نیز نؤوبه گؤزله‌يیر",
     "uploaddisabledtext": "فايل يوکلنمه‌سی باش توتمادی.",
     "php-uploaddisabledtext": "پی اچ پی فایل یوکلملری دؤوره خاریجی‌دیر. خاهیش ائدیریک file_uploads تنظیم لرین یئنی دن بیر باخین.",
     "uploadscripted": "بو فایل بیر اینتئرنئت آختاریش برنامه سی طرفین‌دن سهو چئوریلبیلجک بیر HTML و یا ایسکریپت کودو عبارت‌دیر.",
     "upload-misc-error": "بیلین‌مه‌ین یوکلمه خطاسی",
     "upload-misc-error-text": "یوکلمه اسناسیندا بیلینمه‌ین بیر خطا میدانا گلدی.\nخاهیش ائدیریک علاقه‌نین اعتبارلی و چاتیلا بیلر اولدوغونو تصدیق و یئنی‌دن جهد ائدین.\nاگر پروبلئم تکرارلانسا، بیر [[Special:ListUsers/sysop|administrator]] ایله علاقه ساخلایین",
     "upload-too-many-redirects": "آدرس ده چوخ یؤنلندیرمه وار",
-    "upload-unknown-size": "بیلین‌مه‌ين هجم",
     "upload-http-error": "اچ تی تی پی ختاسی وار : $1",
     "upload-copy-upload-invalid-domain": "فایل یوکلنمه سی بو بازه ده امکانی یوخدور",
     "backend-fail-stream": "$1 فای‌لی یولانمامادی.",
     "img-auth-streaming": "\"$1\" آخینی.",
     "img-auth-public": "img_auth.php 'نین فونکسیاسی خصوصی بیر ویکی فایل‌لاری چیخارماق‌دیر.\nبو wiki اومومی بیر wiki اولا‌راق قورولوب.\nان اویغون تهلوکه‌سیزلیک اوچون، img_auth.php دؤوره خاریجی بوراخیلدی.",
     "img-auth-noread": "ایستیفاده‌چی‌نین «$1»بیر  اوخوماق حقوقو يوخدور.",
-    "img-auth-bad-query-string": "آدرس اونواندا يانلیش آختاریش ستری وار.",
     "http-invalid-url": "سهو اورل: $1",
     "http-invalid-scheme": "\"$1\" سماسینا صاحب اورللئر دستک‌لنمیر",
     "http-request-error": "هتتپ ایستیی بیلینمه‌ین بیر سببله موفقیت‌سیز اولدو.",
     "filehist-dimensions": "اؤلچولر",
     "filehist-filesize": "فایل اؤلچوسو",
     "filehist-comment": "باخیش",
-    "filehist-missing": "فایل یوخدور",
     "imagelinks": "فايل ایشلدمه‌سی",
     "linkstoimage": "آشاغیداکی {{PLURAL:$1|صحیفه|$1 صحیفه‌لر}} بو فایلا {{PLURAL:$1|باغلانیر|باغلانیرلار}}",
     "linkstoimage-more": "بو فایلا {{PLURAL:$1|بیر|$1}}-دن چوخ صحیفه باغلانتی‌سی واردیر.\nآشاغیداکی لیست بو فایلا یالنیز ایلک $1 صحیفه باغلانتیسینی گؤستریر.\nبیر [[Special:WhatLinksHere/$2|بوتون لیست]] ده واردیر.",
     "emailuser-title-notarget": "ایستیفاده‌چی‌یه ایمیل گؤندر",
     "emailpage": "ایستیفاده‌چی‌یه ایمیل گؤندر",
     "emailpagetext": "آشغیداکی فورم‌دان، بو {{GENDER:$1|ایستیفاده‌چی}}‌یه ایمیل گؤندرمک اوچون ایستیفاده ائده بیلرسینیز.\n[[Special:Preferences|اؤز ترجیحلرینیز]]ده وئرن ایمیل آدرسی، بو ایمیلین \"From\" یئرینده گؤستریله‌جک‌دیر و بونا گؤره ایمیلی آلان سیزه موستقیم جاواب گؤندره بیلر.",
-    "usermailererror": "ایمیل‌دن بو خطا قایتاریلدی:",
     "defemailsubject": "«$1» آدلی ایستیفاده‌چی‌دن، {{SITENAME}} ایمیلی",
     "usermaildisabled": "ایستیفاده‌چی ایمیلی باغلی‌دیر",
     "usermaildisabledtext": "بو ویکی‌ده باشقا ایستیفاده‌چیلره ایمیل گؤندره بیلنمه‌سینیز",
     "noemailtitle": "ایمیل آدرسی یوخدور",
     "noemailtext": "بو ایستیفاده‌چی، بیر گئچرلی ایمیل آدرسی وئرمه‌ییب‌دیر.",
-    "nowikiemailtitle": "ایمیل ایجازه‌سی یوخدور",
     "nowikiemailtext": "بو ایستیفاده‌چی، باشقا ایستیفاده‌چیلردن ایمیل آلماماغینی بیلدیریب‌دیر.",
     "emailnotarget": "آلان اوچون، اولمایان یوخسا گئچرسیز ایستیفاده‌چی آدی.",
     "emailtarget": "آلانین ایستیفاده‌چی آدینی دَییشدیر",
     "nowatchlist": "ایزلمه سیاهینیز بؤش‌دور.",
     "watchlistanontext": "لطفاً، ایزلدیگینیز صحیفه‌لری گؤرمک و یا رئداکته ائتمک اوچون $1.",
     "watchnologin": "داخیل اولمامیسینیز",
-    "watchnologintext": "ایزلمه سیاهینیزدا دییشیک‌لیک آپارماق اوچون [[Special:UserLogin|داخیل اولمالیسینیز]].",
     "addwatch": "ایزلمه سیاهی‌سینا علاوه ائت",
     "addedwatchtext": "\"[[:$1]]\" صحیفه‌سی [[Special:Watchlist|ایزله‌دیکلرینیزه]] آرتیریلدی. بو صحیفه‌ده و ایلگیلی دانیشیق صحیفه‌سین‌ده‌کی بوتون دییشیکلیکلر اوردا گؤستریله‌جکلر.",
     "removewatch": "بو صحیفنی ایزلدیگیم صحیفه‌لر سیاهی‌سین‌دان چیخار",
     "watching": "ایزله‌نیلیر...",
     "unwatching": "ایزله‌مه...",
     "watcherrortext": "ایزلئمئ سیاهی‌سی ترجیحلرینیزی \"$1\" اوچون دییشدیررکن بیر خطا میدانا گلدی.",
-    "enotif_mailer": "{{SITENAME}} بیلدیریش خیدمتی",
     "enotif_reset": "باخیلمیش بوتون صحیفه‌لری ایشاره‌له.",
     "enotif_impersonal_salutation": "{{SITENAME}} ایستیفاده‌چی‌سی",
     "enotif_subject_deleted": "{{SITENAME}} $1 صحیفه‌سی، {{gender:$2|$2}} ایله سیلینیب‌دیر",
     "excontent": "کؤهنه مظمون: '$1'",
     "excontentauthor": "ترکیب: '$1 (و'[[Special:Contributions/$2|$2]]' تاریخچه‌ده فالیتی قئید ائدیلن یئگانه ایستیفاده‌چی‌دیر)",
     "exbeforeblank": "سیلینمه‌دن اوولکی مزمون: '$1",
-    "exblank": "صحیفه بوش",
     "delete-confirm": "سیل $1",
     "delete-legend": "سیل",
     "historywarning": "'خبردارلیق:' سیلینه‌جک صحیفه‌نین تاریخچه‌سینده قئید اولونموش $1 {{PLURAL::$1|دییشدیر|دییشدیرمه}} وار:",
     "importunknownsource": "بیلینمه‌ین ایچری کؤچورمه قایناق نؤوو",
     "importcantopen": "ایچری توکمه فایل پرونده لری آچیلمادی",
     "importbadinterwiki": "یانلیش اینتئرویکی کئچیدی",
-    "importnotext": "بوش و یا متن یوخ‌دور",
     "importsuccess": "ایچری توکمه باشا چاتدی!",
-    "importhistoryconflict": "اوست-اوسته دوشمه‌ین کئچمیش رئویزیونو مؤوجود (بو صحیفه داها اول‌دن ایچه کؤچورولموش اولا بیلر)",
     "importnosources": "هئچ ویکیلئراراسی ایچه کؤچورمه قایناغی تعیین و بیرباشا کئچمیش یوکلملری دؤوره خاریجی.",
     "importnofile": "بیر کؤچورمه فایلی یوکلنمدی.",
     "importuploaderrorsize": "ایچه کؤچورولموش فایلین یوکلنمه‌سی اوغورسوز اولدو.\nفایل، ایجازه وئریلن یوکلمه اؤلچوسون‌دن بؤیوک.",
index 2aad5c1..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": "Күҙәтеү исемлегенән сығарырға",
index 15115d9..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",
index b3bd837..ce83999 100644 (file)
     "disclaimers": "Panyakalon",
     "disclaimerpage": "Project:Pamorsoon umum",
     "edithelp": "Pangurupion laho patotahon",
-    "helppage": "Help:Isi",
     "mainpage": "Pogu ni Alaman",
     "mainpage-description": "Pogu ni alaman",
     "portal": "Harbangan ni punguan",
index 974c0da..fefa486 100644 (file)
     "nowatchlist": "شما را هچ چیزی ته وتی لیست چارگ نیست.",
     "watchlistanontext": "لطفا  $1 په دیستن یا اصلاح ایتیمان ته وتی لیست چارگء",
     "watchnologin": "وارد نه بی تگیت",
-    "watchnologintext": "شما بایدن  [[Special:UserLogin|وارد بیت]] په تغییر داتن وتی لیست چارگء",
     "addedwatchtext": "صفحه  \"[[:$1]]\"  په شمی [[Special:Watchlist|watchlist]] هور بیت.\nدیمگی تغییرات په ای صفحه و آیاء صفحه گپ ادان لیست بنت، و صفحه پررنگ جاه کیت ته [[Special:RecentChanges|لیست نوکیت تغییرات]] په راحتر کتن شی که آی زورگ بیت.",
     "removedwatchtext": "صفحه\"[[:$1]]\"  چه [[Special:Watchlist|شمی لیست چارگ]]. دربیت.",
     "watch": "به چار",
index 7b3a1d7..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",
index d474807..675057d 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": "Выдаліць са сьпісу назіраньня",
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 fb7b70e..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": "Премахване от списъка за наблюдение",
index 71de8b2..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",
index 0a186c1..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": "নজরতালিকা থেকে অপসারণ",
index 2824dee..7af7f0d 100644 (file)
     "prefs-skin": "সরহান",
     "skin-preview": "আগচা",
     "datedefault": "পছন করাতা নেই",
-    "prefs-beta": "বেটার বৈশিষ্টহানি",
     "prefs-datetime": "তারিখ বারো সময়",
     "prefs-labs": "পরীক্ষাগারর বৈশিষ্টহানি",
     "prefs-rc": "হাদি এহানর পতানি",
index d2e6f1c..659ad50 100644 (file)
     "disclaimers": "انکار کننده ها",
     "disclaimerpage": "Project:انکار کاربران",
     "edithelp": "کمک برای اصلاح",
-    "helppage": "Help:محتوا",
     "mainpage": "صفحه اصلی",
     "mainpage-description": "صفحه اصلی",
     "policy-url": "Project:خط مشی",
index 3e60240..559be8c 100644 (file)
     "permalink": "Chomlec'h ar stumm-mañ",
     "print": "Moullañ",
     "view": "Gwelet",
+    "view-foreign": "Gwel war $1",
     "edit": "Kemmañ",
     "create": "Krouiñ",
     "editthispage": "Kemmañ ar bajenn-mañ",
     "accountcreatedtext": "Krouet eo bet kont implijer [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|kaozeal]]).",
     "createaccount-title": "Krouiñ ur gont war {{SITENAME}}",
     "createaccount-text": "Unan bennak en deus krouet ur gont gant ho chomlec'h postel war {{SITENAME}} ($4) zo e anv \"$2\" hag a ra gant ar ger-tremen \"$3\".\nMat e vefe deoc'h kevreañ ha cheñch ho ker-tremen bremañ.\n\nNa daolit ket evezh ouzh ar c'hemenn-mañ m'eo bet krouet ar gont dre fazi.",
-    "usernamehasherror": "N'haller ket ober gant an arouezenn # en anvioù an implijerien",
     "login-throttled": "Betek re oc'h heus klasket kevreañ en aner.\nGortozit $1, mar plij, a-raok esaeañ en-dro.",
     "login-abort-generic": "Dibosupl ho kevreañ - Dilezet",
     "loginlanguagelabel": "Yezh : $1",
     "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",
     "upload-permitted": "Seurtoù restroù aotreet : $1.",
     "upload-preferred": "Seurtoù restroù gwellañ : $1.",
     "upload-prohibited": "Seurtoù restroù berzet : $1.",
-    "uploadlog": "marilh ar pajennoù enporzhiet",
     "uploadlogpage": "Marilh ar pajennoù enporzhiet",
     "uploadlogpagetext": "Setu a-is marilh ar restroù diwezhañ bet karget war ar servijer.\nS.o [[Special:NewFiles|rann ar skeudennoù nevez]] evit kaout ur sell gwiroc'h",
     "filename": "Anv ar restr",
     "filereuploadsummary": "Kemmoù er restr :",
     "filestatus": "Statud a-fet gwirioù aozer :",
     "filesource": "Mammenn :",
-    "uploadedfiles": "Restroù karget",
     "ignorewarning": "Na ober van ouzh an evezhiadenn hag enrollañ ar restr forzh penaos",
     "ignorewarnings": "Na ober van ouzh ar c'hemennoù diwall",
     "minlength1": "Anv ar restroù a rank bezañ keit hag ul lizherenn da nebeutañ.",
     "overwroteimage": "enporzhiet ur stumm nevez eus \"[[$1]]\"",
     "uploaddisabled": "Ho tigarez, diweredekaet eo bet kas ar restr-mañ.",
     "copyuploaddisabled": "Diweredekaet eo bet ar pellgargañ dre URL.",
-    "uploadfromurl-queued": "Lakaet eo bet ho pellgargadenn er roll gortoz.",
     "uploaddisabledtext": "Diweredekaet eo an enporzhiañ restroù.",
     "php-uploaddisabledtext": "Diweredekaet eo bet ar pellgargañ e PHP. Gwiriit an dibarzh arventennoù file_uploads.",
     "uploadscripted": "Er restr-mañ ez eus kodoù HTML pe skriptoù a c'hallfe bezañ kammgomprenet gant ur merdeer Kenrouedad.",
     "upload-misc-error": "Fazi kargañ dianav",
     "upload-misc-error-text": "Ur fazi dianav zo bet e-ser kargañ.\nGwiriit eo reizh an URL hag e c'hall bezañ tizhet hag esaeit en-dro.\nMa talc'h ar gudenn, kit e darempred gant ur [[Special:ListUsers/sysop|merour]].",
     "upload-too-many-redirects": "Re a adkasoù zo en URL-mañ.",
-    "upload-unknown-size": "Ment dianav",
     "upload-http-error": "Ur fazi HTTP zo bet : $1",
     "upload-copy-upload-invalid-domain": "N'haller ket seveniñ enporzhiadennoù a-bell adalek an domani-mañ.",
     "backend-fail-stream": "Dibosupl eo lenn ar restr $1.",
     "img-auth-streaming": "O lenn en ur dremen \"$1\"",
     "img-auth-public": "Talvezout a ra an arc'hwel img_auth.php da ezvont restroù adalek ur wiki prevez.\nKefluniet eo bet ar wiki-mañ evel ur wiki foran.\nDiweredekaet eo bet img_auth.php evit ur surentez eus ar gwellañ",
     "img-auth-noread": "N'eo ket aotreet an implijer da lenn \"$1\"",
-    "img-auth-bad-query-string": "Un neudennad goulenn direizh zo gant an URL.",
     "http-invalid-url": "URL direizh : $1",
     "http-invalid-scheme": "N'eo ket skoret an URLoù gant ar patrom \"$1\"",
     "http-request-error": "Ur fazi dianavezet 'zo bet pa veze kaset ar reked.",
     "filehist-dimensions": "Mentoù",
     "filehist-filesize": "Ment ar restr",
     "filehist-comment": "Notenn",
-    "filehist-missing": "Restr diank",
     "imagelinks": "Implij ar restr",
     "linkstoimage": "Liammet eo {{PLURAL:$1|ar bajenn-mañ|an $1 pajenn-mañ}} ouzh ar restr-mañ :",
     "linkstoimage-more": "Ouzhpenn $1 {{PLURAL:$1|bajenn zo liammet ouzh|pajenn zo liammet ouzh}} ar restr-mañ.\nNe laka ar roll-mañ war wel nemet {{PLURAL:$1|ar bajenn gentañ liammet ouzh|an $1 pajenn gentañ liammet ouzh}} ar rest-mañ.\nUr [[Special:WhatLinksHere/$2|roll klok]] a c'haller da gaout.",
     "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-name": "Anv ar gemennadenn",
+    "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ñ",
     "emailuser-title-notarget": "Kas ur postel d'un implijer",
     "emailpage": "Postel implijer",
     "emailpagetext": "Gallout a rit ober gant ar furmskrid a-is a-benn kas ur postel d'an {{GENDER:$1|implijer|implijerez}}-mañ.\nE maezienn \"Kaser\" ho postel e vo merket ar chomlec'h postel resisaet ganeoc'h-c'hwi en ho [[Special:Preferences|Penndibaboù]], d'ar resever da c'hallout respont deoc'h war-eeun ma kar.",
-    "usermailererror": "Fazi postel :",
     "defemailsubject": "Postel kaset eus {{SITENAME}} gant an implijer \"$1\"",
     "usermaildisabled": "Diweredekaet eo ar c'has posteloù etre an implijerien.",
     "usermaildisabledtext": "Ne c'helloc'h ket kas posteloù da implijerien all er wiki-mañ",
     "noemailtitle": "Chomlec'h postel ebet",
     "noemailtext": "N'en deus ket an implijer-mañ resisaet chomlec'h postel reizh ebet.",
-    "nowikiemailtitle": "Berzet kas posteloù",
     "nowikiemailtext": "Dibabet ez eus bet gant an implijerien-mañ chom hep resev posteloù a-berzh implijerien all.",
     "emailnotarget": "N'eus ket eus ar c'haser-mañ pe faziek eo an anv implijer lakaet.",
     "emailtarget": "Merkañ anav implijer ar resever",
     "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ñ",
     "watching": "Heuliet...",
     "unwatching": "Paouez da evezhiañ...",
     "watcherrortext": "Ur gudenn zo bet en ur gemmañ arventennoù ho roll evezhiañ evit \"$1\".",
-    "enotif_mailer": "Posteler Kemenn {{SITENAME}}",
     "enotif_reset": "Merkañ an holl bajennoù evel gwelet",
     "enotif_impersonal_salutation": "implijer {{SITENAME}}",
     "enotif_subject_deleted": "Pajenn $1 {{SITENAME}} zo bet {{GENDER:$2|dilamet}} gant $2",
     "excontent": "endalc'had '$1'",
     "excontentauthor": "an danvez a oa : '$1' (ha '[[Special:Contributions/$2|$2]]' a oa bet an implijer nemetañ)",
     "exbeforeblank": "A-raok diverkañ e oa an endalc'had : '$1'",
-    "exblank": "pajenn c'houllo",
     "delete-confirm": "Diverkañ \"$1\"",
     "delete-legend": "Diverkañ",
     "historywarning": "'''Diwallit :''' Emaoc'h war-nes diverkañ ur bajenn dezhi un istor gant e-tro {{PLURAL:$1|adweladenn|adweladenn}} :",
     "importunknownsource": "Dianav eo seurt ar vammenn enporzhiañ",
     "importcantopen": "N'eus ket bet gallet digeriñ ar restr enporzhiet",
     "importbadinterwiki": "Liamm etrewiki fall",
-    "importnotext": "Goullo pe hep tamm testenn ebet",
     "importsuccess": "Deuet eo an enporzhiadenn da benn vat!",
-    "importhistoryconflict": "Divankadennoù zo er pennad istor ha tabut zo gant se (marteze eo bet enporzhiet ar bajenn araozoc'h)",
     "importnosources": "N'eus bet spisaet tamm mammenn etrewiki ebet ha diweredekaet eo enporzhiañ an Istor war-eeun.",
     "importnofile": "N'eus bet enporzhiet restr ebet.",
     "importuploaderrorsize": "C'hwitet eo bet enporzhiañ ar restr. Brasoc'h eo ar restr eget ar vent aotreet.",
     "tags": "Balizennoù ar c'hemmoù reizh",
     "tag-filter": "Silañ ar [[Special:Tags|balizennoù]] :",
     "tag-filter-submit": "Silañ",
+    "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|Balizenn}}]]: $2)",
     "tags-title": "Balizennoù",
     "tags-intro": "Rollañ a ra ar bajenn-mañ ar balizennoù a c'hall ar meziant implijout da verkañ kemmoù hag an dalvoudegezh anezho.",
     "tags-tag": "Anv ar valizenn",
index eef125a..c9c1cef 100644 (file)
     "disclaimers": "Dazkaşşík",
     "disclaimerpage": "Project:Las dazkaşşí",
     "edithelp": "Radbadal ráhşoní",
-    "helppage": "Help:Ridoband",
     "mainpage": "Monpanna",
     "mainpage-description": "Monpanna",
     "portal": "Cágiŕd bundar",
index 1bf747d..38c410e 100644 (file)
     "pool-errorunknown": "Nepoznata greška",
     "aboutsite": "O {{GRAMMAR:dativ|{{SITENAME}}}}",
     "aboutpage": "Project:O_projektu_{{SITENAME}}",
-    "copyright": "Sadržaj je dostupan pod licencom $1 osim ako je drugačije navedeno.",
+    "copyright": "Sadržaj je dostupan pod licencom $1 osim ako je navedeno drugačije.",
     "copyrightpage": "{{ns:project}}:Autorska_prava",
     "currentevents": "Trenutni događaji",
     "currentevents-url": "Project:Novosti",
     "createacct-yourpasswordagain": "Potvrdite šifru/lozinku",
     "createacct-yourpasswordagain-ph": "Unesite šifru/lozinku opet",
     "remembermypassword": "Zapamti moju šifru na ovom računaru (najviše $1 {{PLURAL:$1|dan|dana|dana}})",
-    "userlogin-remembermypassword": "Ostavi me prijavljen",
+    "userlogin-remembermypassword": "Ostavi me prijavljenog/-u",
     "userlogin-signwithsecure": "Koristite sigurnu konekciju",
     "yourdomainname": "Vaš domen:",
     "password-change-forbidden": "Ne možete da promjenite lozinku na ovom wikiju.",
     "gotaccount": "Već imate korisnički račun? $1.",
     "gotaccountlink": "Prijavi se",
     "userlogin-resetlink": "Zaboravili ste detalje vaše prijave?",
-    "userlogin-resetpassword-link": "Zaboravili ste šifru/lozinku?",
+    "userlogin-resetpassword-link": "Zaboravili ste lozinku?",
     "userlogin-loggedin": "Već ste prijavljeni kao {{GENDER:$1|$1}}.\nKoristite donji obrazac da biste se prijavili kao drugi korisnik.",
     "userlogin-createanother": "Napravi još jedan račun",
     "createacct-join": "Unesite svoje podatke ispod.",
     "passwordtooshort": "Šifra mora imati najmanje {{PLURAL:$1|1 znak|$1 znaka|$1 znakova}}.",
     "password-name-match": "Vaša šifra mora biti različita od Vašeg korisničkog imena.",
     "password-login-forbidden": "Korištenje ovih korisničkih imena i šifara je zabranjeo.",
-    "mailmypassword": "Poništi šifru/lozinku",
+    "mailmypassword": "Poništi lozinku",
     "passwordremindertitle": "Nova privremena šifra za {{SITENAME}}",
     "passwordremindertext": "Neko (vjerovatno Vi, sa IP adrese $1) je zahtjevao da vam pošaljemo novu šifru za {{SITENAME}}  ($4). Privremena šifra za korisnika \"$2\" je napravljena i glasi \"$3\". Ako ste to željeli, sad treba da se prijavite i promjenite šifru.\nVaša privremena šifra će isteči za {{PLURAL:$5|$5 dan|$5 dana}}.\n\nAko je neko drugi napravio ovaj zahtjev ili ako ste se sjetili vaše šifre i ne želite više da je promjenite, možete da ignorišete ovu poruku i da nastavite koristeći vašu staru šifru.",
     "noemail": "Ne postoji adresa e-pošte za korisnika \"$1\".",
     "noemailcreate": "Morate da navedete validnu e-mail adresu",
     "passwordsent": "Nova šifra je poslata na adresu e-pošte korisnika \"$1\".\nMolimo Vas da se prijavite pošto je primite.",
     "blocked-mailpassword": "Da bi se spriječila nedozvoljena akcija, Vašoj IP adresi je onemogućeno uređivanje stranica kao i mogućnost zahtijevanje nove šifre.",
-    "eauthentsent": "Na navedenu adresu poslana je e-poruka s potvrdom.\nPrije nego što pošaljemo daljnje poruke, pratite uputstva s e-pošte da biste potvrdili da je račun zaista Vaša.",
+    "eauthentsent": "Na navedenu adresu poslana je e-poruka s potvrdom.\nPrije nego što pošaljemo daljnje poruke, pratite uputstva s e-pošte da biste potvrdili da je račun zaista Vaš.",
     "throttled-mailpassword": "Već Vam je poslan e-mail za promjenu šifre u {{PLURAL:$1|zadnjih sat vremena|zadnja $1 sata|zadnjih $1 sati}}.\nDa bi se spriječila zloupotreba, može se poslati samo jedan e-mail za promjenu šifre {{PLURAL:$1|svakih sat vremena|svaka $1 sata|svakih $1 sati}}.",
     "mailerror": "Greška pri slanju e-pošte: $1",
     "acct_creation_throttle_hit": "Posjetioci na ovoj wiki koji koriste Vašu IP adresu su već napravili {{PLURAL:$1|$1 račun|$1 računa}} u zadnjih nekoliko dana, što je najveći broj dopuštenih napravljenih računa za ovaj period.\nKao rezultat, posjetioci koji koriste ovu IP adresu ne mogu trenutno praviti više računa.",
-    "emailauthenticated": "Vaša adresa e-pošte je potvrđena $2 u $3.",
-    "emailnotauthenticated": "Vaša adresa e-pošte još nije potvrđena.\nNijedna e-poruka neće biti poslana za bilo koju uslugu od slijedećih.",
+    "emailauthenticated": "Vaša adresa e-pošte potvrđena je $2 u $3.",
+    "emailnotauthenticated": "Vaša adresa e-pošte još nije potvrđena.\nNijedna e-poruka neće biti poslana za bilo koju uslugu od sljedećih.",
     "noemailprefs": "Unesite e-mail adresu za osposobljavanje slijedećih usluga.",
     "emailconfirmlink": "Potvrdite Vašu e-mail adresu",
     "invalidemailaddress": "Ova e-mail adresa ne može biti prihvaćena jer je u neodgovarajućem obliku.\nMolimo vas da unesete ispravnu adresu ili ostavite prazno polje.",
     "accountcreatedtext": "Korisnički račun za [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|razgovor]]) je napravljen.",
     "createaccount-title": "Pravljenje korisničkog računa za {{SITENAME}}",
     "createaccount-text": "Neko je napravio korisnički račun za vašu e-mail adresu na {{SITENAME}} ($4) sa imenom \"$2\", i sa šifrom \"$3\".\nTrebali biste se prijaviti i promjeniti šifru.\n\nMožete ignorisati ovu poruku, ako je korisnički račun napravljen greškom.",
-    "usernamehasherror": "Korisničko ime ne može sadržavati haš znakove",
     "login-throttled": "Previše puta ste se pokušali prijaviti.\nMolimo Vas da sačekate $1 prije nego što pokušate ponovo.",
     "login-abort-generic": "Vaša prijava nije bila uspješna – Prekinuto",
     "loginlanguagelabel": "Jezik: $1",
     "resetpass-abort-generic": "Promjenu šifre/lozinke je prekinula ekstenzija.",
     "passwordreset": "Poništavanje šifre",
     "passwordreset-text-one": "Ispunite ovaj obrazac da biste resetovali Vašu šifru/lozinku.",
-    "passwordreset-text-many": "{{PLURAL:$1|Ispunite jedno od polja kako bi ste dobili privremenu šifru/lozinku putem e-pošte.}}",
+    "passwordreset-text-many": "{{PLURAL:$1|Ispunite jedno od polja kako biste dobili privremenu lozinku putem e-pošte.}}",
     "passwordreset-legend": "Poništi šifru",
     "passwordreset-disabled": "Poništavanje šifre  je onemogućeno na ovoj wiki.",
     "passwordreset-emaildisabled": "E-pošta je onemogućena na ovom wikiju.",
     "passwordreset-emailtext-ip": "Neko (vjerovatno Vi, s IP adrese $1) je zatražio podsjetnik Vaših detalja računa za {{SITENAME}} ($4). Sljedeći {{PLURAL:$3|račun korisnika je|računi korisnika su}} povezani s ovom e-mail adresom:\n\n$2\n\n{{PLURAL:$3|Ova privremena šifra|Ove privremene šifre}} će isteći za {{PLURAL:$5|jedan dan|$5 dana}}.\nTrebate se prijaviti i odabrati novu šifru. Ako je neko drugi napravio ovaj zahtjev, ili ako ste se sjetili Vaše početne šifre, a ne želite je promijeniti, možete zanemariti ovu poruku i nastaviti koristiti staru šifru.",
     "passwordreset-emailtext-user": "Korisnik $1 na {{SITENAME}} je zatražio podsjetnik o detaljima Vašeg računa za {{SITENAME}} ($4). Sljedeći {{PLURAL:$3|korisnički račun je|korisnički računi su}} povezani s ovom e-mail adresom:\n\n$2\n\n{{PLURAL:$3|Ova privremena šifra|Ove privremene šifre}} će isteći za {{PLURAL:$5|jedan dan|$5 dana}}.\nTrebate se prijaviti i odabrati novu šifru. Ako je neko drugi napravio ovaj zahtjev, ili ako ste se sjetili Vaše originalne šifre, a ne želite je više promijeniti, možete zanemariti ovu poruku i nastaviti koristiti staru šifru.",
     "passwordreset-emailelement": "Korisničko ime: $1\nPrivremena šifra: $2",
-    "passwordreset-emailsent": "Podsjetnik o šifri/lozinci je poslat na Vašu E-mail adresu.",
-    "passwordreset-emailsent-capture": "Poslat je podsjetnik preko e-pošte (prikazan dole).",
-    "passwordreset-emailerror-capture": "E-poruka za resetiranje šifre/lozinke, prikazan ispod, je poslan, ali slanje {{GENDER:$2|korisniku|korisnici}} nije uspjelo: $1",
+    "passwordreset-emailsent": "Podsjetnik na lozinku poslan je na Vašu e-mail adresu.",
+    "passwordreset-emailsent-capture": "Poslan je podsjetnik preko e-pošte (prikazano ispod).",
+    "passwordreset-emailerror-capture": "E-poruka za resetiranje lozinke, prikazano ispod, poslana je, ali slanje {{GENDER:$2|korisniku|korisnici}} nije uspjelo: $1",
     "changeemail": "Promijeni e-mail adresu",
     "changeemail-header": "Promijeni e-mail adresu korisničkog računa",
     "changeemail-text": "Ispunite ovaj formular da biste promijenili svoju e-mail adresu. Morat ćete upisati svoj pasvord da potvrdite ovu promjenu.",
     "accmailtitle": "Šifra poslana.",
     "accmailtext": "Nasumično odabrana šifra za [[User talk:$1|$1]] je poslata na adresu $2.\n\nŠifra/lozinka za ovaj novi račun može biti promijenjena na stranici ''[[Special:ChangePassword|izmjene šifre]]'' nakon prijave.",
     "newarticle": "(Novi)",
-    "newarticletext": "Došli ste na stranicu koja još nema sadržaja.\n*Ako želite unijeti sadržaj, počnite tipkati u prozor ispod ovog teksta.\n*Ako vam treba pomoć, idite na [$1 stranicu za pomoć].\n*Ako ste ovamo dospjeli slučajno, kliknite dugme \"Nazad\" (''Back'') u svom internet pregledniku.",
+    "newarticletext": "Došli ste na stranicu koja još nema sadržaja.\n*Ako želite unijeti sadržaj, počnite tipkati u prozor ispod ovog teksta.\n*Ako Vam treba pomoć, idite na [$1 stranicu za pomoć].\n*Ako ste ovamo dospjeli slučajno, kliknite na dugme \"Nazad\" (''Back'') u Vašem internetskom pregledniku.",
     "anontalkpagetext": "----''Ovo je stranica za razgovor za anonimnog korisnika koji još nije napravio nalog ili ga ne koristi.\nZbog toga moramo da koristimo brojčanu IP adresu kako bismo identifikovali njega ili nju.\nTakvu adresu može dijeliti više korisnika.\nAko ste anonimni korisnik i mislite da su vam upućene nebitne primjedbe, molimo Vas da [[Special:UserLogin/signup|napravite nalog]] ili se [[Special:UserLogin|prijavite]] da biste izbjegli buduću zabunu sa ostalim anonimnim korisnicima.''",
     "noarticletext": "Na ovoj stranici trenutno nema teksta.\nMožete [[Special:Search/{{PAGENAME}}|tražiti naslov ove stranice]] na drugim stranicama.\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} tražiti u povezanim zapisima] ili [{{fullurl:{{FULLPAGENAME}}|action=edit}} urediti ovu stranicu]</span>.",
     "noarticletext-nopermission": "Trenutno nema teksta na ovoj stranici.\nMožete [[Special:Search/{{PAGENAME}}|tražiti ovaj naslov stranice]] na drugim stranicama ili <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} pretražiti povezane zapisnike]</span>, ali nemate dozvolu da napravite ovu stranicu.",
-    "missing-revision": "Uređivanje broj $1 na stranici \"{{FULLPAGENAME}}\" ne postoji.\n\nOvo se obično dešava kada pratite zastarjelu vezu na stranice koja je obrisana.\nViše informacija možete pronaći u [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} protokol brisanja].",
+    "missing-revision": "Uređivanje broj $1 na stranici \"{{FULLPAGENAME}}\" ne postoji.\n\nOvo se obično dešava kad pratite zastarjelu vezu na stranicu koja je obrisana.\nViše informacija možete pronaći u [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} protokolu brisanja].",
     "userpage-userdoesnotexist": "Korisnički račun \"<nowiki>$1</nowiki>\" nije registrovan.\nMolimo provjerite da li želite napraviti/izmijeniti ovu stranicu.",
     "userpage-userdoesnotexist-view": "Korisnički račun \"$1\" nije registrovan.",
     "blocked-notice-logextract": "Ovaj korisnik je trenutno blokiran.\nPosljednje stavke zapisnika blokiranja možete pogledati ispod:",
     "powersearch-togglenone": "Ništa",
     "search-external": "Vanjska pretraga",
     "searchdisabled": "<p>Izvinjavamo se!  Puno pretraga teksta je privremeno onemogućena.  U međuvremenu, možete koristiti Google za pretragu.  Indeks može biti stariji.",
-    "search-error": "Dogodila se greška prilikom pretraživanja: $1",
+    "search-error": "Desila se greška prilikom pretraživanja: $1",
     "preferences": "Postavke",
     "mypreferences": "Postavke",
     "prefs-edits": "Broj izmjena:",
     "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",
     "right-editmyusercss": "Uredite svoje vlastite korisničke CSS datoteke",
     "right-editmyuserjs": "Uredite vlastite korisničke JavaScript datoteke",
     "right-viewmywatchlist": "Pogledaj svoj spisak praćenih stranica",
-    "right-viewmyprivateinfo": "Vidite svoje privatne podatke (npr. adresa e-pošte, pravo ime)",
+    "right-viewmyprivateinfo": "Pogledajte Vaše privatne podatke (npr, adresa e-pošte, pravo ime)",
     "right-editmyprivateinfo": "Uredite svoje privatne podatke (npr. adresa e-pošte, pravo ime)",
     "right-editmyoptions": "Uredite svoje postavke",
     "right-rollback": "Brzo vraćanje izmjena na zadnjeg korisnika koji je uređivao određenu stranicu",
     "action-viewmyprivateinfo": "pogledajte svoje privatne informacije",
     "action-editmyprivateinfo": "uredite svoje privatne podatke",
     "nchanges": "$1 {{PLURAL:$1|promjena|promjene|promjena}}",
-    "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|izmjena od vaše posljedne posjete}}",
+    "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|izmjena od Vaše posljedne posjete}}",
     "enhancedrc-history": "historija",
     "recentchanges": "Nedavne izmjene",
     "recentchanges-legend": "Postavke nedavnih izmjena",
     "upload-permitted": "Podržane vrste datoteka: $1.",
     "upload-preferred": "Preferirane vrste datoteka: $1.",
     "upload-prohibited": "Zabranjene vrste datoteka: $1.",
-    "uploadlog": "log slanja",
     "uploadlogpage": "Protokol postavljanja",
     "uploadlogpagetext": "Ispod je spisak najskorijih slanja.",
     "filename": "Ime datoteke",
     "filereuploadsummary": "Izmjene datoteke:",
     "filestatus": "Status autorskih prava:",
     "filesource": "Izvor:",
-    "uploadedfiles": "Poslati fajlovi",
     "ignorewarning": "Zanemari upozorenja i sačuvaj datoteku",
     "ignorewarnings": "Zanemari sva upozorenja",
     "minlength1": "Ime datoteke mora imati barem jedno slovo.",
     "overwroteimage": "postavljena nova verzija datoteke \"[[$1]]\"",
     "uploaddisabled": "Slanje fajlova je isključeno",
     "copyuploaddisabled": "Postavljanje putem URL nije omogućeno.",
-    "uploadfromurl-queued": "Vaše postavljanje je na čekanju.",
     "uploaddisabledtext": "Postavljanje datoteka je onemogućeno.",
     "php-uploaddisabledtext": "Postavljanje datoteka preko PHP je onemogućeno. Molimo provjerite postavku file_uploads.",
     "uploadscripted": "Ova datoteka sadrži HTML ili skriptni kod koji može izazvati grešku kod internet preglednika.",
     "upload-misc-error": "Nepoznata greška pri postavljanju",
     "upload-misc-error-text": "Desila se nepoznata greška pri postavljanju.\nMolimo Vas provjerite da li je URL tačan i dostupan pa pokušajte ponovo.\nAko se problem ne riješi, kontaktirajte [[Special:ListUsers/sysop|administratora]].",
     "upload-too-many-redirects": "URL sadrži previše preusmjerenja",
-    "upload-unknown-size": "Nepoznata veličina",
     "upload-http-error": "Desila se HTTP greška: $1",
     "upload-copy-upload-invalid-domain": "Kopije postavljenih datoteka nisu dostupne sa ove domene.",
     "backend-fail-stream": "Ne mogu emitirati datoteku $1.",
     "img-auth-streaming": "Tok \"$1\".",
     "img-auth-public": "Funkcija img_auth.php služi za izlaz datoteka sa privatnih wikija.\nOva wiki je postavljena kao javna wiki.\nZa optimalnu sigurnost, img_auth.php je onemogućena.",
     "img-auth-noread": "Korisnik nema pristup za čitanje \"$1\".",
-    "img-auth-bad-query-string": "URL ima nevaljan izraz upita.",
     "http-invalid-url": "Nevaljan URL: $1",
     "http-invalid-scheme": "URLovi za koje šema \"$1\" nije podržana",
     "http-request-error": "Nepoznata greška pri slanju zahtjeva.",
     "filehist-dimensions": "Dimenzije",
     "filehist-filesize": "Veličina datoteke",
     "filehist-comment": "Komentar",
-    "filehist-missing": "Datoteka nedostaje",
     "imagelinks": "Upotreba datoteke",
     "linkstoimage": "{{PLURAL:$1|Slijedeća stranica koristi|Slijedećih $1 stranica koriste}} ovu sliku:",
     "linkstoimage-more": "Više od $1 {{PLURAL:$1|datoteke|datoteka}} je povezano s ovom datotekom.\nSlijedeći spisak pokazuje samo {{PLURAL:$1|prvu stranicu povezanu|prve $1 stranice povezane|prvih $1 stranica povezanih}} s ovom datotekom.\nOvdje je dostupan [[Special:WhatLinksHere/$2|potpuni spisak]].",
     "protectedpages-noredirect": "Sakrij preusmjerenja",
     "protectedpagesempty": "Trenutno nijedna stranica nije zaštićena s ovim parametrima.",
     "protectedpages-page": "Stranica",
-    "protectedpages-expiry": "Ističe",
+    "protectedpages-expiry": "Istječe",
     "protectedpages-reason": "Razlog",
     "protectedpages-unknown-timestamp": "Nepoznato",
     "protectedtitles": "Zaštićeni naslovi",
     "emailuser-title-notarget": "Pošalji e-mail korisniku",
     "emailpage": "Pošalji e-mail korisniku",
     "emailpagetext": "Možete korisiti formu ispod za slanje e-mail poruka {{GENDER:$1|ovom korisniku|ovoj korisnici|ovom korisniku}}.\nE-mail adresa koju ste unijeli u [[Special:Preferences|Vašim korisničkim postavkama]] će biti prikazana kao adresa pošiljaoca, tako da će primaoc poruke moći da Vam odgovori.",
-    "usermailererror": "Objekat pošte je vratio grešku:",
     "defemailsubject": "{{SITENAME}} e-pošta od {{GENDER:$1|korisnika|korisnice|korisnika}} $1",
     "usermaildisabled": "Korisnički e-mail onemogućen",
     "usermaildisabledtext": "Ne možete poslati e-mail drugim korisnicima na ovoj wiki",
     "noemailtitle": "Nema adrese e-pošte",
     "noemailtext": "Ovaj korisnik nije naveo ispravnu adresu e-pošte.",
-    "nowikiemailtitle": "E-mail nije dopušten",
     "nowikiemailtext": "Ovaj korisnik je odabrao da ne prima e-mail poštu od drugih korisnika.",
     "emailnotarget": "Neodgovarajuće ili nevaljano korisničko ime za primanje e-maillova.",
     "emailtarget": "Unesite korisnika za primanje e-mailova",
     "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",
     "watching": "Pratim...",
     "unwatching": "Ne pratim...",
     "watcherrortext": "Desila se greška pri promjeni postavki vašeg spiska praćenja za \"$1\".",
-    "enotif_mailer": "{{SITENAME}} obaviještenje o pošti",
     "enotif_reset": "Označi sve strane kao posjećene",
     "enotif_impersonal_salutation": "{{SITENAME}} korisnik",
     "enotif_subject_deleted": "{{gender:$2|Korisnik|Korisnica}} $2 je {{gender:$2|obrisao|obrisala}} stranicu $1 projekta {{SITENAME}}",
     "excontent": "sadržaj je bio: '$1'",
     "excontentauthor": "sadržaj je bio: '$1' (i jedini korisnik koji je mijenjao bio je '[[Special:Contributions/$2|$2]]')",
     "exbeforeblank": "sadržaj prije brisanja je bio: '$1'",
-    "exblank": "stranica je bila prazna",
     "delete-confirm": "Brisanje \"$1\"",
     "delete-legend": "Obriši",
     "historywarning": "'''Upozorenje''':  Stranica koju želite da obrišete ima historiju sa otprilike $1 {{PLURAL:$1|revizijom|revizije|revizija}}:",
     "cantrollback": "Ne može se vratiti izmjena; posljednji autor je ujedno i jedini.",
     "alreadyrolled": "Ne može se vratiti posljednja izmjena [[:$1]] od korisnika [[User:$2|$2]] ([[User talk:$2|razgovor]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]); neko drugi je već izmjenio ili vratio članak.\n\nPosljednja izmjena je bila od korisnika [[User:$3|$3]] ([[User talk:$3|razgovor]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
     "editcomment": "Sažetak izmjene je bio: \"''$1''\".",
-    "revertpage": "Vraćene izmjene korisnika [[Special:Contributions/$2|$2]] ([[User talk:$2|razgovor]]) na posljednju izmjenu koju je načinio [[User:$1|$1]]",
-    "revertpage-nouser": "Vraćene izmjene skrivenog korisnika na posljednju reviziju koju je {{GENDER:$1|načinio|načinila}} [[User:$1|$1]]",
+    "revertpage": "Vraćene izmjene korisnika [[Special:Contributions/$2|$2]] ([[User talk:$2|razgovor]]) na posljednju izmjenu koju je napravio [[User:$1|$1]]",
+    "revertpage-nouser": "Vraćene izmjene skrivenog korisnika na posljednju reviziju, koju je {{GENDER:$1|napravio|napravila}} [[User:$1|$1]]",
     "rollback-success": "Poništene izmjene korisnika $1;\nvraćeno na posljednju verziju koju je sačuvao $2.",
     "sessionfailure-title": "Greška u sesiji",
     "sessionfailure": "Izgleda da postoji problem sa vašom sesijom; ova akcija je otkazana kao prevencija protiv napadanja sesija. Kliknite \"back\" (''nazad'') i osvježite stranicu sa koje ste došli, i opet pokušajte.",
     "change-blocklink": "promijeni blokadu",
     "contribslink": "doprinosi",
     "emaillink": "pošalji e-mail",
-    "autoblocker": "Automatski ste blokirani jer dijelite IP adresu sa \"[[User:$1|$1]]\".\nRazlog za blokiranje korisnika $1 je ''$2''",
+    "autoblocker": "Automatski ste blokirani jer dijelite IP-adresu sa \"[[User:$1|$1]]\".\nRazlog za blokiranje korisnika $1 je ''$2''",
     "blocklogpage": "Evidencija blokiranja",
     "blocklog-showlog": "Ovaj korisnik je ranije blokiran. Zapisnik blokiranja je prikazan ispod kao referenca:",
     "blocklog-showsuppresslog": "Ovaj korisnik je ranije blokiran i sakriven. Zapisnik sakrivanja je prikazan ispod kao referenca:",
     "importunknownsource": "Nepoznat izvorni tip uvoza",
     "importcantopen": "Ne može se otvoriti uvozna datoteka",
     "importbadinterwiki": "Loš interwiki link",
-    "importnotext": "Stranica je prazna, ili bez teksta",
     "importsuccess": "Uspješno ste uvezli stranicu!",
-    "importhistoryconflict": "Postoji konfliktna historija revizija (možda je ova stranica ranije uvezena)",
     "importnosources": "Nije definisan međuwiki izvor za uvoz i direktna postavljanja historije su onemogućena.",
     "importnofile": "Uvozna datoteka nije postavljena.",
     "importuploaderrorsize": "Postavljanje uvozne datoteke nije uspjelo.\nDatoteka je veća nego što je dopušteno.",
     "pageinfo-edits": "Ukupan broj izmjena",
     "pageinfo-authors": "Ukupan broj različitih autora",
     "pageinfo-recent-edits": "Broj nedavnih izmjena (u poslednjih $1)",
-    "pageinfo-recent-authors": "Broj nedavnih specifičnih autora",
+    "pageinfo-recent-authors": "Broj nedavnih različitih autora",
     "pageinfo-magic-words": "{{PLURAL:$1|Čarobna riječ|Čarobne riječi}} ($1)",
     "pageinfo-hidden-categories": "{{PLURAL:$1|Sakrivena kategorija|Sakrivene kategorije}} ($1)",
     "pageinfo-templates": "{{PLURAL:$1|Uključeni šablon|Uključeni šabloni}} ($1)",
index bb509bf..b615e24 100644 (file)
     "currentevents-url": "Project:Accanjingeŋ kokkoro",
     "disclaimers": "Diseklaima",
     "edithelp": "Paŋinriŋ mapadécéŋ",
-    "helppage": "Help:Lise",
     "mainpage": "Leppa Indoë",
     "mainpage-description": "Leppa Indoë",
     "portal": "Portal komunitas",
index e76b42f..65888a7 100644 (file)
     "currentevents-url": "Project:Һонин мэдээн",
     "disclaimers": "Татагалзалнууд",
     "disclaimerpage": "Project:Ниитэ татагалзал",
-    "helppage": "Help:Агуулга",
     "mainpage": "Нюур хуудаһан",
     "mainpage-description": "Нюур хуудаһан",
     "portal": "Хурал",
index dbdb7de..e283545 100644 (file)
     "accountcreatedtext": "S'ha creat el compte d'usuari de [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|discussió]]).",
     "createaccount-title": "Creació d'un compte a {{SITENAME}}",
     "createaccount-text": "Algú ha creat un compte d'usuari anomenat $2 al projecte {{SITENAME}}\n($4) amb la vostra adreça de correu electrònic. La contrasenya per a l'usuari «$2» és «$3». Hauríeu d'accedir al compte i canviar-vos aquesta contrasenya quan abans millor.\n\nSi no hi teniu cap relació i aquest compte s'ha creat per error, simplement ignoreu el missatge.",
-    "usernamehasherror": "El nom d'usuari no pot contenir caràcters hash",
     "login-throttled": "Heu realitzat massa intents d'accés a la sessió.\nEspereu $1 abans de tornar-ho a provar.",
     "login-abort-generic": "L'entrada al compte d'usuari no ha reeixit - Abortada",
     "loginlanguagelabel": "Llengua: $1",
     "resetpass-abort-generic": "Una extensió ha interromput el canvi de contrasenya.",
     "resetpass-expired": "La contrasenya ha vençut. Definiu una contrasenya nova per iniciar la sessió.",
     "resetpass-expired-soft": "La contrasenya ha vençut i cal restablir-la. Trieu una contrasenya nova ara, o feu clic a «{{int:resetpass-submit-cancel}}» per a restablir-la més endavant.",
+    "resetpass-validity-soft": "La contrasenya no és vàlida: $1\n\nTrieu una nova contrasenya ara o cliqueu \"{{int:resetpass-submit-cancel}}\" per a restablir-la més endavant.",
     "passwordreset": "Restablir contrasenya",
     "passwordreset-text-one": "Cal completar aquest formulari per reiniciar la contrasenya",
     "passwordreset-text-many": "{{PLURAL:$1|Ompliu un dels camps per a rebre una contrasenya temporal al vostre correu electrònic.}}",
     "revdelete-no-file": "El fitxer especificat no existeix.",
     "revdelete-show-file-confirm": "Esteu segurs que voleu veure una revisió esborrada del fitxer «<nowiki>$1</nowiki>» de $2 a $3?",
     "revdelete-show-file-submit": "Sí",
+    "revdelete-selected-text": "{{PLURAL:$1|Versió seleccionada|Versions seleccionades}} de [[:$2]]:",
     "logdelete-selected": "{{PLURAL:$1|Esdeveniment del registre seleccionat|Esdeveniments del registre seleccionats}}:",
+    "revdelete-text-text": "Les versions suprimides encara apareixeran en la pàgina d'historial, però part del seu contingut serà inaccessible al públic.",
+    "revdelete-text-file": "Les versions suprimides encara apareixeran en l'historial del fitxer, però part del seu contingut serà inaccessible al públic.",
+    "logdelete-text": "Els esdeveniments suprimits encara apareixeran en els registres, però part del seu contingut serà inaccessible al públic.",
     "revdelete-confirm": "Si us plau, confirmeu que és això el que desitgeu fer, que enteneu les conseqüències, i que esteu fent-ho d'acord amb [[{{MediaWiki:Policy-url}}|les polítiques acordades]].",
     "revdelete-suppress-text": "Les supressions '''només''' han de ser portades a terme en els següents casos:\n* Informació potencialment difamatòria\n* Informació personal inapropiada\n*: ''adreces personals, números de telèfon, números d'identificació nacional, etc.''",
     "revdelete-legend": "Defineix restriccions en la visibilitat",
     "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",
     "upload-permitted": "Tipus de fitxer permesos: $1.",
     "upload-preferred": "Tipus de fitxer preferits: $1.",
     "upload-prohibited": "Tipus de fitxer prohibits: $1.",
-    "uploadlog": "registre de càrregues",
     "uploadlogpage": "Registre de càrregues",
     "uploadlogpagetext": "A sota hi ha una llista dels fitxers que s'han carregat més recentment.\nVegeu la [[Special:NewFiles|galeria de nous fitxers]] per a una presentació més visual.",
     "filename": "Nom de fitxer",
     "filereuploadsummary": "Canvis al fitxer:",
     "filestatus": "Situació dels drets d'autor:",
     "filesource": "Font:",
-    "uploadedfiles": "Fitxers carregats",
     "ignorewarning": "Ignora qualsevol avís i desa el fitxer igualment",
     "ignorewarnings": "Ignora qualsevol avís",
     "minlength1": "Els noms de fitxer han de ser de com a mínim d'una lletra.",
     "overwroteimage": "ha carregat una nova versió de «[[$1]]»",
     "uploaddisabled": "S'ha inhabilitat la càrrega",
     "copyuploaddisabled": "Càrrega per URL deshabilitada.",
-    "uploadfromurl-queued": "S'ha encuat la vostra càrrega.",
     "uploaddisabledtext": "S'ha inhabilitat la càrrega de fitxers.",
     "php-uploaddisabledtext": "La càrrega de fitxer està desactivada al PHP. Comproveu les opcions del fitxer file_uploads.",
     "uploadscripted": "Aquest fitxer conté codi HTML o de seqüències que pot ser interpretat equivocadament per un navegador.",
     "upload-misc-error": "S'ha produït un error de càrrega desconegut",
     "upload-misc-error-text": "S'ha produït un error desconegut durant la càrrega. Verifiqueu que l'URL és vàlid i accessible, i torneu-ho a provar. Si el problema persisteix, adreceu-vos a un [[Special:ListUsers/sysop|administrador]].",
     "upload-too-many-redirects": "La URL conté massa redireccions",
-    "upload-unknown-size": "Mida desconeguda",
     "upload-http-error": "Ha ocorregut un error HTTP: $1",
     "upload-copy-upload-invalid-domain": "Les càrregues de còpia no són disponibles des d'aquest domini.",
     "backend-fail-stream": "No s'ha pogut transmetre el fitxer $1.",
     "img-auth-streaming": "Lectura corrent de \"$1\".",
     "img-auth-public": "La funció de img_auth.php és de sortida de fitxers d'un lloc wiki privat.\nAquest wiki està configurat com a wiki públic.\nPer seguretat, img_auth.php està desactivat.",
     "img-auth-noread": "L'usuari no té accés a la lectura de \"$1\".",
-    "img-auth-bad-query-string": "La direcció té una cadena de consulta invàlid.",
     "http-invalid-url": "URL incorrecta: $1",
     "http-invalid-scheme": "Les URLs amb l'esquema \"$1\" no són compatibles.",
     "http-request-error": "La petició HTTP ha fallat per un error desconegut.",
     "filehist-dimensions": "Dimensions",
     "filehist-filesize": "Mida del fitxer",
     "filehist-comment": "Comentari",
-    "filehist-missing": "Fitxer que falta",
     "imagelinks": "Ús del fitxer",
     "linkstoimage": "{{PLURAL:$1|La següent pàgina enllaça|Les següents pàgines enllacen}} a aquesta imatge:",
     "linkstoimage-more": "Hi ha més de $1 {{PLURAL:$1|pàgina que enllaça|pàgines que enllaçen}} a aquest fitxer.\nLa següent llista només mostra {{PLURAL:$1|la primera d'elles|les primeres $1 d'aquestes pàgines}}.\nPodeu consultar la [[Special:WhatLinksHere/$2|llista completa]].",
     "download": "baixada",
     "unwatchedpages": "Pàgines desateses",
     "listredirects": "Llista de redireccions",
+    "listduplicatedfiles": "Llista de fitxers amb duplicats",
+    "listduplicatedfiles-entry": "[[:File:$1|$1]] té [[$3|{{PLURAL:$2|un duplicat|$2 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",
     "randompage": "Pàgina a l'atzar",
     "randompage-nopages": "No hi ha cap pàgina en {{PLURAL:$2|l'espai de noms següent|els espais de noms següents}}: $1.",
-    "randomincategory": "Pàgina aleatòria en la categoria",
+    "randomincategory": "Pàgina aleatòria en una categoria",
     "randomincategory-invalidcategory": "«$1» no és un nom de categoria vàlid.",
     "randomincategory-nopages": "No hi ha pàgines a la categoria [[:Category:$1|$1]].",
     "randomincategory-selectcategory": "Obté una pàgina a l'atzar de la categoria: $1 $2.",
     "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-summary": "Aquesta pàgina llista les categories de seguiment que s'omplen automàticament pel programari MediaWiki. Es poden canviar els seus noms modificant els missatges del sistema corresponents en l'espai de noms {{ns:8}}.",
+    "trackingcategories-msg": "Categoria de seguiment",
+    "trackingcategories-name": "Nom del missatge",
+    "trackingcategories-desc": "Criteris d'inclusió de categoria",
+    "noindex-category-desc": "La pàgina conté una paraula màgica <code><nowiki>__NOINDEX__</nowiki></code> (i és en un espai de noms on està permesa) i per tant no està indexada per robots.",
+    "index-category-desc": "La pàgina conté un <code><nowiki>__INDEX__</nowiki></code> (i és en un espai de noms on està permès) i per tant està indexat per robots quan normalment no ho seria.",
+    "post-expand-template-inclusion-category-desc": "Després d'expandir totes les plantilles, la mida de la pàgina és més gran que <code>$wgMaxArticleSize</code>, per tant algunes plantilles no s'han expandit.",
+    "post-expand-template-argument-category-desc": "Després d'expandir un argument de plantilla (alguna cosa entre claus triples, com <code>{{{Això}}}</code>), la pàgina és més gran que <code>$wgMaxArticleSize</code>.",
+    "expensive-parserfunction-category-desc": "Massa funcions d'analitzador costoses (com <code>#ifexist</code>) incloses en una pàgina. Vegeu [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+    "broken-file-category-desc": "Categoria afegida si la pàgina conté un enllaç de fitxer trencat (un enllaç per inserir un fitxer quan aquest fitxer no existeix).",
+    "hidden-category-category-desc": "Aquesta és una categoria que conté <code><nowiki>__HIDDENCAT__</nowiki></code>, que impedeix que aparegui en la caixa d'enllaços de categoria a les pàgines, per defecte.",
+    "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",
     "emailuser-title-notarget": "Enviar un correu electrònic a un usuari",
     "emailpage": "Correu electrònic a usuari",
     "emailpagetext": "Podeu usar el següent formulari per a enviar un missatge de correu electrònic a {{GENDER:$1|aquest usuari|aquesta usuària}}.\nL'adreça electrònica que vau indicar a [[Special:Preferences|les vostres preferències d'usuari]] apareixerà com a remitent del correu electrònic, de manera que el destinatari us podrà respondre directament.",
-    "usermailererror": "L'objecte de correu ha retornat un error:",
     "defemailsubject": "Correu electrònic de l'usuari \"$1\" de {{SITENAME}}",
     "usermaildisabled": "Correu electrònic d'usuaris deshabilitat",
     "usermaildisabledtext": "No podeu enviar correus electrònics a altres usuaris en aquest wiki",
     "noemailtitle": "No hi ha cap adreça electrònica",
     "noemailtext": "Aquest usuari no ha especificat una adreça electrònica vàlida.",
-    "nowikiemailtitle": "No es permet el correu electrònic",
     "nowikiemailtext": "Aquest usuari ha escollit no rebre missatges electrònics d'altres usuaris.",
     "emailnotarget": "Nom d'usuari inexistent o no vàlid per al destinatari.",
     "emailtarget": "Introduïu el nom d'usuari del destinatari",
     "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",
     "watching": "S'està vigilant...",
     "unwatching": "S'està desatenent...",
     "watcherrortext": "S'ha produït un error en canviar els paràmetres de la vostra llista de seguiment de «$1».",
-    "enotif_mailer": "Sistema de notificació per correl de {{SITENAME}}",
     "enotif_reset": "Marca totes les pàgines com a visitades",
     "enotif_impersonal_salutation": "usuari de la {{SITENAME}}",
     "enotif_subject_deleted": "La pàgina $1 de {{SITENAME}} ha estat suprimida per {{gender:$2|$2}}",
     "excontent": "el contingut era: «$1»",
     "excontentauthor": "el contingut era: «$1» (i l'únic coŀlaborador era [[Special:Contributions/$2|$2]])",
     "exbeforeblank": "el contingut abans de buidar era: '$1'",
-    "exblank": "la pàgina estava en blanc",
     "delete-confirm": "Elimina «$1»",
     "delete-legend": "Elimina",
     "historywarning": "'''Atenció:''' La pàgina que esteu a punt d'eliminar té un historial amb $1 {{PLURAL:$1|versió|versions}}, aproximadament:",
     "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",
     "importunknownsource": "No es reconeix el tipus de la font d'importació",
     "importcantopen": "No s'ha pogut obrir el fitxer a importar",
     "importbadinterwiki": "Enllaç d'interwiki incorrecte",
-    "importnotext": "Buit o sense text",
     "importsuccess": "Importació completada!",
-    "importhistoryconflict": "Hi ha un conflicte de versions en l'historial (la pàgina podria haver sigut importada abans)",
     "importnosources": "No s'ha definit cap font d'origen interwiki i s'ha inhabilitat la càrrega directa d'una còpia de l'historial",
     "importnofile": "No s'ha pujat cap fitxer d'importació.",
     "importuploaderrorsize": "La càrrega del fitxer d'importació ha fallat. El fitxer és més gran que la mida de càrrega permesa.",
index 5aa1f1e..a512613 100644 (file)
@@ -9,7 +9,7 @@
             "Умар"
         ]
     },
-    "tog-underline": "Кlел сиз хьака хьажориган:",
+    "tog-underline": "КӀел сиз хьакха хьажорган:",
     "tog-hideminor": "Къайладаха кигийра нисдарш оц могӀама керла хийцамехь",
     "tog-hidepatrolled": "Къайладаха гӀаролладина нисдарш оц могӀама керла нисдаршкахь",
     "tog-newpageshidepatrolled": "Къайлайаха гlароллайина агlонаш оц могlама керла агlонашкахь",
     "accountcreated": "Декъашхочун дӀаяздар кхоьллина",
     "accountcreatedtext": "Кхоьллина декъашхочун [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|дийцаре.]]) дӀаяздар.",
     "createaccount-title": "{{SITENAME}}: декъашхочун дӀаяздар кхоллар",
-    "usernamehasherror": "Декъашхочун цӀеран юкъахь хийла ца еза «цаца»",
     "login-throttled": "Хьо дукха гӀиртира.\nДехар до, собар де $1 юха гӀортале.",
     "login-abort-generic": "Сестемин довзийта тарцаделира",
     "loginlanguagelabel": "Мотт: $1",
     "prefs-skin": "Кечяран тема",
     "skin-preview": "Хьалха муха ю хьажа",
     "datedefault": "Iад йитарца",
-    "prefs-beta": "Бета-таронаш",
     "prefs-datetime": "Терахь а хан а",
     "prefs-labs": "Муха ю хьажарна таронаш",
     "prefs-user-pages": "Декъашхочун агӀо",
     "upload-permitted": "Магийна файлийн тайпанаш: $1.",
     "upload-preferred": "Магийна файлийн тайпанаш: $1.",
     "upload-prohibited": "Магийна доцу файлийн тайпанаш: $1.",
-    "uploadlog": "Чуяхаран тéптар",
     "uploadlogpage": "Чуяхаран тéптар",
     "uploadlogpagetext": "Лахахьа гойтуш бу тӀаьххьара чуяьхна файлийн могӀам.\nИшта хьажа [[Special:NewFiles|керлачу файлийн галерей]].",
     "filename": "Файлан цӀе",
     "filereuploadsummary": "Файлан хийцамаш:",
     "filestatus": "Яржоран хьал:",
     "filesource": "Хьост:",
-    "uploadedfiles": "Чуйаха файлаш",
     "ignorewarning": "ХӀума дац чуяккха файл",
     "ignorewarnings": "ДӀахедар тергал ца дан",
     "badfilename": "Файлан цӀе хийцина → $1.",
     "overwroteimage": "Чуяьккхина файлан керла верси «[[$1]]»",
     "uploaddisabled": "Чуяккхар магийна дац",
     "copyuploaddisabled": "URL тӀера чуяккхар дӀадайина ду.",
-    "uploadfromurl-queued": "Хьа чуяккхар рогӀехь ду.",
     "uploaddisabledtext": "Файлаш чуяхар дӀадайина ду.",
     "uploadscriptednamespace": "ХӀокху SVG-файлан цӀерийн меттиг нийса яц '$1'",
     "upload-source": "ДIайолалун файл",
     "upload-warning-msg": "Чуйоккхуш [$2] гӀалат даьлла. И нисдан юхагӀо [[Special:Upload/stash/$1|upload form]] чу.",
     "upload-proto-error": "Нийса йоцу протокол",
     "upload-file-error": "Чоьхьара гӀалат",
-    "upload-unknown-size": "Хууш доцу барам",
     "upload-http-error": "Даьлла гӀалат HTTP: $1",
     "backend-fail-stream": "ДӀаяккха цатарло файл «$1».",
     "backend-fail-backup": "Таро яц файлан $1 тӀаьхьалонан копиян.",
     "filehist-dimensions": "Файлан барам",
     "filehist-filesize": "Файлан барам",
     "filehist-comment": "Билгалдаккхар",
-    "filehist-missing": "Файл яц",
     "imagelinks": "Файл лелор",
     "linkstoimage": "{{PLURAL:$1|ТӀаьхьайогӀу $1 агӀо тӀетевжина|ТӀаьхьайогӀу $1 агӀонаш тӀетевжина}} хӀокху файлан:",
     "linkstoimage-more": "$1 дукха {{PLURAL:$1|агӀонаш}} чохь лелош ю хӀара файл.\nХӀокху могӀам чохь {{PLURAL:$1|гойтуш ю $1 хьажорг|гойтуш ю $1 хьажоргаш}} хӀокху файланца.\nКхин хьажа йиш ю [[Special:WhatLinksHere/$2|буьззина могӀаме]].",
     "excontent": "чуьраниг: «$1»",
     "excontentauthor": "чуьраниг: «$1» (дуьххьара кхоьллинарг [[Special:Contributions/$2|$2]])",
     "exbeforeblank": "чуьраниг дlацlанйале хьалха: «$1»",
-    "exblank": "агlо йаьсса йара",
     "delete-confirm": "$1 — дӀаяккхар",
     "delete-legend": "ДӀаяккхар",
     "historywarning": "'''Тергам:''' хӀокху агӀона герггарчу хьесапехь $1 {{PLURAL:$1|версеш|верси|верси}} ю:",
index 2ba438c..659b1d9 100644 (file)
     "mypreferencesprotected": "دەسەڵاتی دەستکارییکردنی هەڵبژاردنەکانی خۆتت نییە.",
     "ns-specialprotected": "تۆ ناتوانی لاپەڕە تایبەتەکان دەستکاریی بکەی.",
     "titleprotected": "ئەم سەرناوە پارێزراوە لە دروستکران لە لایەن [[User:$1|$1]].\nھۆکاری ئەمە بریتیە لە \"''$2''\".",
-    "invalidtitle-knownnamespace": "سەردێڕی نادروست لەگەڵ بە بۆشایی ناوی «$2» و دەقی «$3»",
+    "invalidtitle-knownnamespace": "سەردێڕی نادروست بە بۆشایی ناوی «$2» و دەقی «$3»",
     "invalidtitle-unknownnamespace": "سەردێڕی هەڵە لەگەڵ ناوەبۆشایی نەناسراوی ژمارە $1 و دەقی \"$2\"",
     "exception-nologin": "لەژوورەوە نیت",
     "exception-nologin-text": "تکایە [[Special:Userlogin|بچۆ ژوورەوە]] تا بتوانیت بچیتە نێو ئەم پەڕەیە یان ئەم کردەیە ئەنجام بدەیت.",
     "newpassword": "تێپەڕوشەی نوێ:",
     "retypenew": "تێپەڕوشەی نوێ دوبارە بنووسەوە:",
     "resetpass_submit": "تێپەڕوشە رێکخە و بچۆ ژوورەوە",
-    "changepassword-success": "تێپەروشەکەت بە سەرکەوتوویی گۆڕدرا. ئێستا چوونە ژوورەوەت...",
+    "changepassword-success": "تێپەروشەکەت بە سەرکەوتوویی گۆڕدرا!",
     "resetpass_forbidden": "تێپەڕوشەکە ناگۆڕدرێت",
     "resetpass-no-info": "بۆ گەیشتنی راستەوخۆ بەم پەڕە ئەشێ بچیتە ژوورەوە.",
     "resetpass-submit-loggedin": "تێپەڕوشە بگۆڕە",
     "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": "(ھەموو)",
     "upload-permitted": "جۆرە پەڕگە ڕێگەپێدراوەکان: $1.",
     "upload-preferred": "جۆرە پەڕگانەی بە باشتر دەزانرێن: $1.",
     "upload-prohibited": "جۆرە پەڕگانەی قەدەغە کراون: $1.",
-    "uploadlog": "لۆگی بارکردن",
     "uploadlogpage": "لۆگی بارکردن",
     "uploadlogpagetext": "لەخوارەوە لیستی دوایین بارکراوەکان دەبینی.\nبۆ ئەوەی چاوێکیان لێ بکەی، [[Special:NewFiles|گالەری پەڕگە نوێکان]] ببینە.",
     "filename": "ناوی پەڕگە",
     "filereuploadsummary": "گۆرانکارییەکانی پەڕگە:",
     "filestatus": "بارودۆخی مافی لەبەرگرتنەوە:",
     "filesource": "سەرچاوە:",
-    "uploadedfiles": "پەڕگە بارکراوەکان",
     "ignorewarning": "چاوپۆشان لە ئاگادارییەکان و پاشەکەوت کردن بە هەر شێوەیەک",
     "ignorewarnings": "گوێ مەدە بە ئاگادارییەکان",
     "minlength1": "ناوی پەڕگەکان دەبێ لانیکەم یەک پیت ببێت.",
     "upload-misc-error": "هەڵەیەکی نەناسراوی بارکردن",
     "upload-misc-error-text": "هەڵەیەکی نەناسراو لە کاتی بارکردن ڕووی‌دا.\nتکایە لە درووست‌بوون و دەست‌پێ گەیشتنی URL ئەرخەیان ببە و دیسان تاقی‌بکەوە.\nگەر کێشەکە هەر بەردەوام بوو پەیوەندی بکە بە [[Special:ListUsers/sysop|بەڕێوبەر]].",
     "upload-too-many-redirects": "URL ڕەوانەکەری زۆری لەخۆ گرتووە",
-    "upload-unknown-size": "قەبارەی نادیار",
     "upload-http-error": "هەڵەیەکی HTTP ڕووئ داوە: $1",
     "backend-fail-stream": "نەکرا پەڕگەی $1 بنێردرێت.",
     "backend-fail-notexists": "پەڕگەی $1 بوونی نییە.",
     "filehist-dimensions": "ئەندازە",
     "filehist-filesize": "قەبارەی پەڕگە",
     "filehist-comment": "تێبینی",
-    "filehist-missing": "ون‌بوونی پەڕه",
     "imagelinks": "بەکارھێنانی پەڕگە",
     "linkstoimage": "لەم {{PLURAL:$1|پەڕەی خوارەوە بەستەر دراوە|$1 پەڕەی خوارەوە بەستەر دراوە}} بۆ ئەم پەڕگە:",
     "linkstoimage-more": "زیاتر لە $1 {{PLURAL:$1|بەستەری لاپەڕە|بەستەری لاپەڕە}} بۆ ئەم پەڕگه.\nئەم لیستە {{PLURAL:$1|یەکەم لاپەڕەی بەستەرە|یەکەم لاپەڕە $1 بەستەرە}} بۆ تەنها یەم پەڕگە.\nهەروا [[Special:WhatLinksHere/$2|لیستی تەواو]] ئامادەی کەڵک وەرگرتنە.",
     "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": "پەڕەکان بە تایبەتمەندیی پەڕە",
     "usermaildisabled": "ئیمەیڵی بەکارهێنەر لەکاردانیە",
     "noemailtitle": "هیچ ناونیشانێکی ئی‌مەیل نییە",
     "noemailtext": "ئەم بەکارهێنەرە ناونێشانێکی بڕوا پێکراوی ئی‌مەیلی دانەناوە.",
-    "nowikiemailtitle": "ڕێگە بۆ ئی‌مەیل نەدراوە",
     "nowikiemailtext": "ئەم بەکارهێنەرە تایبەتمەندیی وەرنەگرتنی ئی‌مەیل لە بەکارهێنەرانی دیکەی هەلبژاردووە.",
     "emailtarget": "ناوی بەکارھێنەریی وەرگر بنووسە",
     "emailusername": "ناوی به‌كارھێنه‌ر:",
     "nowatchlist": "لە لیستی چاودێڕییەکانتدا ھیچ نیە.",
     "watchlistanontext": "بۆ دیتن و دەستکاریی بابەتەکانی  ناو پێرستی چاودێرییەکەتدا دەبێ $1.",
     "watchnologin": "لە ژوورەوە نیت.",
-    "watchnologintext": "دەبی لە [[Special:UserLogin|ژوورەوە]] بیت بۆ ئەوەی بتوانی گۆڕانکاری بکەیت لە لیستی چاودێریەکەت‌دا.",
     "addwatch": "بیخە سەر لیستی چاودێری",
     "addedwatchtext": "پەڕەی «[[:$1]]» خرایە ژێر [[Special:Watchlist|پێرستی چاودێری]]یەکەت.\nگۆڕانکارییەکانی داھاتووی ئەم پەڕەیە و پەڕەی وتووێژەکەی، لەوێدا پێرست دەکرێت.",
     "removewatch": "لەلیستی چاودێری لایبە",
     "watchlist-options": "ھەڵبژاردەکانی لیستی چاودێری",
     "watching": "چاودێری...",
     "unwatching": "لابردنی چاودێری...",
-    "enotif_mailer": "نامەی ڕاگەیاندنی {{SITENAME}}",
     "enotif_reset": "ھەموو پەڕەکان وەک بینراو دیاری بکە",
     "enotif_impersonal_salutation": "بەکارهێنەری \t{{SITENAME}}",
     "enotif_subject_deleted": "پەڕەی {{SITENAME}} $1 بە دەستی {{gender:$2|$2}} سڕایەوە.",
     "excontent": "ناوەرۆک ئەمە بوو: «$1»",
     "excontentauthor": "ناوەرۆک ئەمە بوو: «$1» (و تەنیا بەشداربوو «[[Special:Contributions/$2|$2]]» بوو)",
     "exbeforeblank": "ناوەرۆک بەر لە واڵاکردنەوە ئەمە بوو: «$1»",
-    "exblank": "پەڕە واڵا بوو",
     "delete-confirm": "سڕینەوەی «$1»",
     "delete-legend": "بیسڕەوە",
     "historywarning": "'''وشیار بە:''' پەڕەیەک کە دەتەوێ بیسڕیتەوە مێژوویەکی ھەیە بە نزیکەی $1 {{PLURAL:$1|پێداچوونەوە|پێداچوونەوە}}وە:",
     "delete-edit-reasonlist": "دەستکاری کردنی ھۆکارەکانی سڕینەوە",
     "delete-toobig": "ئەم لاپەڕە مێژوویەکی دەستکاری زۆر گەورەی هەیە، زیاتر لە $1 {{PLURAL:$1|پێداچوونەوە|پێداچوونەوە}}.\nبۆ بەرگری لە خراپ‌بوونی چاوەڕوان نەکراوی {{SITENAME}}، سڕینەوەی لاپەڕەی وا بەربەست‌کراوە.",
     "delete-warning-toobig": "ئەم لاپەڕە مێژوویەکی دەستکاری زۆر گەورەی هەیە، زیاتر لە $1 {{PLURAL:$1|پێداچوونەوە|پێداچوونەوە}}.\nسڕینەوی ئەوە لە وانەیە کارەکانی بنکەدراوی {{SITENAME}} تووشی کێشە بکات؛\nدوورنواڕانە جێ‌بەجێی بکە.",
-    "deleting-backlinks-warning": "'''ھۆشدار:''' پەڕەی تر بەم پەڕەیەی دەتەوێ بیسڕییەوە بەستەر دراوە.",
+    "deleting-backlinks-warning": "'''ھۆشدار:''' [[Special:WhatLinksHere/{{FULLPAGENAME}}|پەڕەکانی تر]] بەم پەڕەیەی دەتەوێ بیسڕییەوە بەستەر دراوە.",
     "rollback": "گەڕاندنەوەی دەستکارییەکان",
     "rollback_short": "گەڕاندنەوە",
     "rollbacklink": "گەڕاندنەوە",
     "alreadyrolled": "دوایین گۆڕانکاریەکانی لەسەر [[:$1]] لە لایەن [[User:$2|$2]] ناگەڕێندرێنەوە ([[User talk:$2|وتووێژ]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]])؛ کەسێکی دیکە لە پێش‌دا دەستکاری کردووە یان گەڕاندوویەتەوە.\n\nدوایین دەستکاری ئەم لاپەڕە [[User:$3|$3]] کردوویە ([[User talk:$3|وتووێژ]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
     "editcomment": "پوختەی دەستکاری \"''$1''\" بوو.",
     "revertpage": "گەڕاندنەوەی دەستکارییەکانی [[Special:Contributions/$2|$2]] ([[User talk:$2|لێدوان]]) بۆ دوایین پێداچوونەوەی [[User:$1|$1]]",
-    "revertpage-nouser": "دەستکارییەکانی (ناوی بەکارھێنەر سڕاوەتەوە) بۆ دوایین پێداچوونەوەی [[User:$1|$1]] گەڕێنراوە.",
+    "revertpage-nouser": "دەستکارییەکانی بەکارھێنەرێکی شاڕدراوە بۆ دوایین پێداچوونەوەی {{GENDER:$1|[[User:$1|$1]]}} گەڕێنرایەوە.",
     "rollback-success": "دەستکارییەکانی $1 وەرگێرایەوە؛<br />\nگۆڕدرا بۆ دوایین پێداچوونەوەی $2.",
     "sessionfailure": "لەوەدەچی کێشەیەک لە دانیشتنی چوونەژوورەوەت (login session)دا ببێت.\nئەم کردەوە هەڵوەشێندرایەوە بۆ بەرگری لە دزینی دراوەکانی دانیشتن.\nتکایە بگەڕێوە بۆ پەڕەی پێشوو و نوێی بکەوە، ئینجا دیسان تاقیی بکەوە.",
     "protectlogpage": "لۆگی پاراستن",
     "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»",
     "change-blocklink": "بەربەستن بگۆڕە",
     "contribslink": "بەشدارییەکان",
     "emaillink": "ناردنی ئیمەیل",
-    "autoblocker": "Ø®Û\86کار Ø¨Û\95ربÛ\95ستâ\80\8cکراÙ\88Û\95 Ù\84Û\95بÛ\95ر Ø¦Û\95Ù\88Û\95Û\8c Ù\86اÙ\88Ù\86Û\8cشاÙ\86Û\8c Ø¦Ø§Û\8câ\80\8cÙ¾Û\8c ØªÛ\86 Ù\84Û\95Ù\85 Ø¯Ù\88اÛ\8cÛ\8cاÙ\86Û\95دا Ù\84Û\95 Ù\84اÛ\8cÛ\95Ù\86 \"[[User:$1|$1]]\" Ø¨Û\95کار Ù\87اتÙ\88Ù\88Û\95.\nÙ\87Û\86کارÛ\8c Ø¨Û\95ربÛ\95ستâ\80\8cکراÙ\86Û\8c $1 Ø¦Û\95Ù\85Û\95Û\8cÛ\95: \"$2\"",
+    "autoblocker": "Ø®Û\86Ú¯Û\95Ú\95 Ø¨Û\95ربÛ\95ست Ú©Ø±Ø§ Ú\86Ù\88Ù\86 Ù\86اÙ\88Ù\86Û\8cشاÙ\86Û\8c Ø¦Ø§Û\8cÙ¾Û\8cÛ\8cÛ\95Ú©Û\95ت Ù\84Û\95Ù\85 Ø¯Ù\88اÛ\8cÛ\8cÛ\95دا Ù\84Û\95 Ù\84اÛ\8cÛ\95Ù\86 Â«[[User:$1|$1]]» Ø¨Û\95کارھاتÙ\88Ù\88Û\95.\nÚ¾Û\86کارÛ\8c Ø¨Û\95ربÛ\95ستÙ\86Û\8c $1 Ø¦Û\95Ù\85Û\95Û\8cÛ\95: Â«$2»",
     "blocklogpage": "لۆگی بەربەستن",
     "blocklog-showlog": "ئەم بەکارھێنەرە پێشتر بربەست کراوە.\nلۆگی بەربەستن لە ژێرەوە ھاتووە:",
     "blocklogentry": "[[$1]]ی بۆ ماوەی $2 بەربەست کرد $3",
     "importunknownsource": "جۆری سەرچاوەی هاوردن نەناسراوە",
     "importcantopen": "پەڕگەی ھاوردن ناکرێتەوە",
     "importbadinterwiki": "بەستەری نێوانویکیی خراپ",
-    "importnotext": "واڵا یان بێ‌دەق",
     "importsuccess": "ھاوردن تەواو بوو!",
-    "importhistoryconflict": "کێشە لەو مێژووی پێداچوونەوانە وا هەیە (لەوانەیە ئەم پەڕەیە پێشتر ھاوردە کرابێ)",
     "importnosources": "ھیچ سەرچاوەیەکی ھاوردنی ناوویکی دیاری نەکراوە و بارکردنی ڕاستەوخۆی مێژوو ناچالاکە.",
     "importnofile": "ھیچ پەڕگەیەکی ھاوردن بار نەکراوە.",
     "importuploaderrorsize": "بارکردنی پەڕگەی ھاوردن سەرکەوتوو نەبوو.\nپەڕگەکە لەو قەبارەیەی بۆ بارکردن ڕێگەدراوە گەورەترە.",
     "pageinfo-length": "قەبارەی پەڕە (بایت)",
     "pageinfo-article-id": "زنجیرەی پەڕە",
     "pageinfo-language": "زمانی ناوەرۆکی پەڕە",
-    "pageinfo-robot-policy": "چۆنێتیی مۆتۆڕی گەڕان",
+    "pageinfo-robot-policy": "پێرستکردن بە بۆتەکان",
     "pageinfo-robot-index": "ڕێ پێدراو",
     "pageinfo-robot-noindex": "ڕێ پێنەدراوه",
     "pageinfo-views": "ژمارەی بینینەکان",
index f85f0b0..bfeba72 100644 (file)
     "nowatchlist": "Сизинъ козетюв джедвелинъиз боштыр.",
     "watchlistanontext": "Козетюв джедвелини бакъмакъ я да денъиштирмек ичюн $1 борджлусынъыз.",
     "watchnologin": "Отурым ачмакъ керек",
-    "watchnologintext": "Озь козетюв джедвелинъизни денъиштирмек ичюн [[Special:UserLogin|отурым ачынъыз]]",
     "addedwatchtext": "\"[[:$1]]\" саифеси [[Special:Watchlist|козетюв джевделинъизге]] кирсетильди.\nБундан сонъ, бу саифеде ве онынъ музакере саифесинде япыладжакъ денъиштирмелер анда косьтериледжек.",
     "removedwatchtext": "\"[[:$1]]\" саифеси [[Special:Watchlist|козетюв джедвелинъизден]] ёкъ этильди.",
     "watch": "Козет",
index cd1e1b4..098cc5b 100644 (file)
     "accountcreatedtext": "$1 içün bir qullanıcı esabı açıldı.",
     "createaccount-title": "{{SITENAME}} saytında yañı bir esap yaratıluvı",
     "createaccount-text": "Birev siziñ e-mail adresini bildirip {{SITENAME}} saytında ($4) \"$2\" adlı bir esap yarattı.\nŞu esap içün parol budır: \"$3\".\nSiz şimdi oturım açıp paroliñizni deñiştirmek kereksiñiz.\n\nŞu esap hata olaraq yaratılğan olsa bu mektüpke qulaq asmayıp olasıñız.",
-    "usernamehasherror": "Qullanıcı adında # işareti olamaz",
     "login-throttled": "Yaqın zamanda pek çoq kere kirmege tırıştıñız.\nLütfen, qayta kirmezden evel biraz bekleñiz.",
     "loginlanguagelabel": "Til: $1",
     "suspicious-userlogout": "Çıqış istegeniñiz red etildi, çünki bozuq bir brauzer ya da keşleyici proksi tarafından yollanğan kibi körüne.",
     "upload-permitted": "İzinli fayl çeşitleri: $1.",
     "upload-preferred": "İstenilgen fayl çeşitleri: $1.",
     "upload-prohibited": "Yasaqlı fayl çeşitleri: $1.",
-    "uploadlog": "yükleme jurnalı",
     "uploadlogpage": "Fayl yükleme jurnalı",
     "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",
     "filereuploadsummary": "Faylnıñ deñiştirilmeleri:",
     "filestatus": "Tarqatuv şartları:",
     "filesource": "Menba:",
-    "uploadedfiles": "Yüklengen fayllar",
     "ignorewarning": "Tenbige qulaq asmayıp faylnı yükle.",
     "ignorewarnings": "Tenbilerge qulaq asma",
     "minlength1": "Faylnıñ adı eñ azdan bir ariften ibaret olmalı.",
     "filehist-dimensions": "En × boy",
     "filehist-filesize": "Fayl büyükligi",
     "filehist-comment": "İzaat",
-    "filehist-missing": "Fayl yoq",
     "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.",
     "emailuser": "Qullanıcığa mektüp",
     "emailpage": "Qullanıcığa elektron mektüp yolla",
     "emailpagetext": "Aşağıdaki formanı toldurıp bu qullanıcığa mektüp yollap olursıñız.\n[[Special:Preferences|Öz sazlamalarıñızda]] yazğan elektron adresiñiz mektüpniñ \"Kimden\" satırında yazılacaq, bunıñ içün mektüp alıcı doğrudan-doğru siziñ adresiñizge cevap yollap olur.",
-    "usermailererror": "E-mail beyanatı yollanğan vaqıtta hata olıp çıqtı",
     "defemailsubject": "{{SITENAME}} e-mail",
     "noemailtitle": "E-mail adresi yoqtır",
     "noemailtext": "Bu qullanıcı uyğun elektron poçta adresini bildirmegen.",
     "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",
     "watchlist-options": "Közetüv cedveli sazlamaları",
     "watching": "Közetüv cedveline kirsetilmekte...",
     "unwatching": "Közetüv cedvelinden yoq etilmekte...",
-    "enotif_mailer": "{{SITENAME}} poçta vastasınen haber bergen hızmet",
     "enotif_reset": "Cümle saifelerni baqılğan olaraq işaretle",
     "enotif_impersonal_salutation": "{{SITENAME}} qullanıcısı",
     "enotif_lastvisited": "Soñki ziyaretiñizden berli yapılğan deñiştirmelerni körmek içün $1 baqıñız.",
     "excontent": "eski metin: '$1'",
     "excontentauthor": "eski metin: '$1' ('$2' isse qoşqan tek bir qullanıcı)",
     "exbeforeblank": "Yoq etilmegen evelki metin: '$1'",
-    "exblank": "saife metini boş",
     "delete-confirm": "\"$1\" saifesini yoq etmektesiñiz",
     "delete-legend": "Yoq etüv",
     "historywarning": "'''Tenbi:''' Siz yoq etmege istegen saifeñizniñ qararnen $1 {{PLURAL:$1|versiyalı|versiyalı}} keçmişi bardır:",
index f8bd301..a7484e2 100644 (file)
@@ -31,7 +31,7 @@
     "tog-underline": "Podtrhávat odkazy:",
     "tog-hideminor": "Skrýt malé editace v posledních změnách",
     "tog-hidepatrolled": "Skrýt patrolované editace v posledních změnách",
-    "tog-newpageshidepatrolled": "Skrýt patrolované stránky ze seznamu nových stránek",
+    "tog-newpageshidepatrolled": "Skrýt patrolované stránky v seznamu nových stránek",
     "tog-extendwatchlist": "Na seznamu sledovaných stránek zobrazovat všechny změny, ne jen tu poslední",
     "tog-usenewrc": "V posledních změnách a sledovaných stránkách seskupovat změny podle stránek",
     "tog-numberheadings": "Automaticky číslovat nadpisy",
@@ -43,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 editace implicitně jako malé editace",
+    "tog-minordefault": "Označovat editace implicitně jako malé",
     "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",
     "permalink": "Trvalý odkaz",
     "print": "Vytisknout",
     "view": "Zobrazit",
+    "view-foreign": "Prohlédnout na {{grammar:6sg|$1}}",
     "edit": "Editovat",
+    "edit-local": "Editovat místní popis",
     "create": "Vytvořit",
+    "create-local": "Přidat místní popis",
     "editthispage": "Editovat stránku",
     "create-this-page": "Vytvořit tuto stránku",
     "delete": "Smazat",
     "badaccess": "Nedostatečná oprávnění",
     "badaccess-group0": "Nemáte oprávnění k provedení požadované činnosti.",
     "badaccess-groups": "Požadovanou činnost smějí provádět jen uživatelé ve {{PLURAL:$2|skupině|skupinách}} $1.",
-    "versionrequired": "Vyžadováno MediaWiki verze $1",
+    "versionrequired": "Vyžadována MediaWiki verze $1",
     "versionrequiredtext": "Pro použití této stránky je vyžadováno MediaWiki verze $1. Vizte [[Special:Version|stránku verze]].",
     "ok": "OK",
     "pagetitle": "$1 – {{SITENAME}}",
     "nstab-help": "Nápověda",
     "nstab-category": "Kategorie",
     "nosuchaction": "Neznámý úkon",
-    "nosuchactiontext": "Činnost („action“) uvedená v URL je neplatná.\nZřejmě jste se překlepli při zadávání adresy nebo jste klikli na chybný odkaz.\nMůže se ale jednat také o chybu {{GRAMMAR:2sg|{{SITENAME}}}}.",
+    "nosuchactiontext": "Činnost („action“) uvedená v URL je neplatná.\nZřejmě jste se při zadávání adresy překlepli nebo jste klikli na chybný odkaz.\nMůže se ale jednat také o chybu {{GRAMMAR:2sg|{{SITENAME}}}}.",
     "nosuchspecialpage": "Neexistující speciální stránka",
     "nospecialpagetext": "<strong>Zadali jste neplatnou speciální stránku.</strong>\n\nZkuste se podívat na [[Special:SpecialPages|seznam všech existujících speciálních stránek]].",
     "error": "Chyba",
     "fileexistserror": "Nelze uložit do souboru „$1“: soubor existuje",
     "unexpected": "Neočekávaná hodnota: \"$1\"=\"$2\".",
     "formerror": "Chyba: nebylo možné odeslat formulář",
-    "badarticleerror": "Tento úkon nelze použít na tuto stránku.",
+    "badarticleerror": "Tuto činnost nelze na této stránce provést.",
     "cannotdelete": "Nebylo možné smazat stránku nebo soubor „$1“.\nMožná už byl(a) smazán(a) někým jiným.",
     "cannotdelete-title": "Stránku „$1“ nelze smazat",
     "delete-hook-aborted": "Smazání bylo bez bližšího vysvětlení zrušeno přípojným bodem.",
     "viewyourtext": "Můžete si prohlédnout a zkopírovat zdrojový kód '''vašich změn''' této stránky:",
     "protectedinterface": "Tato stránka obsahuje text softwarového rozhraní a je zamčena kvůli prevenci zneužití.\nPro přidávání a změny překladů pro všechny wiki použijte [//translatewiki.net/ translatewiki.net], projekt pro lokalizaci MediaWiki.",
     "editinginterface": "'''Upozornění:''' Editujete stránku, která definuje texty rozhraní.\nZměny této stránky ovlivní vzhled uživatelského rozhraní všem uživatelům této wiki.\nPro přidávání a změny překladů pro všechny wiki použijte [//translatewiki.net/ translatewiki.net], projekt pro lokalizaci MediaWiki.",
-    "cascadeprotected": "Tato stránka je zamčena, neboť je vložena do {{PLURAL:$1|následující stránky zamčené|následujících stránek zamčených|následujících stránek zamčených}} kaskádovým zámkem:\n$2",
+    "cascadeprotected": "Tato stránka je zamčena, neboť je vložena do {{PLURAL:$1|následující stránky, zamčené|následujících stránek, zamčených|následujících stránek, zamčených}} kaskádovým zámkem:\n$2",
     "namespaceprotected": "Nemáte povoleno editovat stránky ve jmenném prostoru '''$1'''.",
     "customcssprotected": "Nemáte povoleno editovat tuto stránku s CSS, protože obsahuje osobní nastavení jiného uživatele.",
     "customjsprotected": "Nemáte povoleno editovat tuto stránku s JavaScriptem, protože obsahuje osobní nastavení jiného uživatele.",
     "virus-badscanner": "Špatná konfigurace: neznámý antivirový program: ''$1''",
     "virus-scanfailed": "prověřování selhalo (kód $1)",
     "virus-unknownscanner": "neznámý antivirus:",
-    "logouttext": "'''Nyní jste odhlášeni.'''\n\nUvědomte si, že některé stránky se mohou i nadále zobrazovat, jako byste byli dosud přihlášeni, pokud nevymažete cache prohlížeče.",
+    "logouttext": "'''Nyní jste odhlášeni.'''\n\nUvědomte si, že některé stránky se mohou i nadále zobrazovat, jako byste byli dosud přihlášeni, dokud nevymažete cache prohlížeče.",
     "welcomeuser": "Vítejte, uživateli $1!",
     "welcomecreation-msg": "Váš účet byl vytvořen.\nNezapomeňte si upravit své [[Special:Preferences|nastavení {{grammar:2sg|{{SITENAME}}}}]].",
     "yourname": "Uživatelské jméno:",
     "wrongpasswordempty": "Bylo zadáno prázdné heslo. Zkuste to znovu.",
     "passwordtooshort": "Heslo musí být dlouhé nejméně $1 {{PLURAL:$1|znak|znaky|znaků}}.",
     "password-name-match": "Vaše heslo nesmí být stejné jako uživatelské jméno.",
-    "password-login-forbidden": "Použití tohoto uživatelského jména a hesla byla zakázáno.",
+    "password-login-forbidden": "Použití tohoto uživatelského jména a hesla bylo zakázáno.",
     "mailmypassword": "Poslat nové heslo",
     "passwordremindertitle": "Nové dočasné heslo na {{grammar:4sg|{{SITENAME}}}}",
-    "passwordremindertext": "Někdo (patrně vy, z IP adresy $1) požádal, abychom o nové heslo\npro přihlášení do {{grammar:2sg|{{SITENAME}}}} ($4). Uživateli „$2“ bylo\nproto nastaveno dočasné heslo „$3“. Pokud jste to byl(a) vy, můžete se\nnyní přihlásit a zvolit si nové heslo. Platnost tohoto dočasného hesla\nvyprší za {{PLURAL:$5|jeden den|$5 dny|$5 dní}}.\n\nPokud jste o změnu hesla nežádal(a) nebo jste si na původní heslo již\nvzpomněl(a) a už ho změnit nechcete, můžete tuto zprávu ignorovat\na používat staré heslo.",
+    "passwordremindertext": "Někdo (patrně vy, z IP adresy $1) požádal o nové heslo\npro přihlášení do {{grammar:2sg|{{SITENAME}}}} ($4). Uživateli „$2“ bylo\nproto nastaveno dočasné heslo „$3“. Pokud jste to byl(a) vy, můžete se\nnyní přihlásit a zvolit si nové heslo. Platnost tohoto dočasného hesla\nvyprší za {{PLURAL:$5|jeden den|$5 dny|$5 dní}}.\n\nPokud jste o změnu hesla nežádal(a) nebo jste si na původní heslo již\nvzpomněl(a) a už ho změnit nechcete, můžete tuto zprávu ignorovat\na používat staré heslo.",
     "noemail": "Uživatel „$1“ nemá zaregistrovanou e-mailovou adresu.",
     "noemailcreate": "Musíte uvést platnou e-mailovou adresu",
     "passwordsent": "Dočasné heslo bylo zasláno na e-mailovou adresu registrovanou pro „$1“. Přihlaste se, prosím, znovu, jakmile ho obdržíte.",
     "eauthentsent": "Na zadanou adresu byl zaslán potvrzovací e-mail.\nŽádné další zprávy vám však na tuto adresu nebudou odeslány, dokud podle instrukcí v e-mailu nepotvrdíte, že tato adresa skutečně patří vám.",
     "throttled-mailpassword": "Během {{PLURAL:$1|poslední hodiny|posledních $1 hodin}} již bylo heslo jednou zasláno.\nKvůli prevenci zneužívání lze heslo zaslat jen jednou za $1 {{PLURAL:$1|hodinu|hodiny|hodin}}.",
     "mailerror": "Chyba při zasílání e-mailu: $1",
-    "acct_creation_throttle_hit": "Uživatelé přicházející z vaší IP adresy už dnes vytvořili $1 {{PLURAL:$1|účet|účty|účtů}}, což je dovolené maximum. Proto v tuto chvíli není dovoleno z této IP adresy další účty zakládat.",
+    "acct_creation_throttle_hit": "Uživatelé používající vaši IP adresu už dnes vytvořili $1 {{PLURAL:$1|účet|účty|účtů}}, což je dovolené maximum. Proto není v tuto chvíli dovoleno z této IP adresy zakládat další účty.",
     "emailauthenticated": "Vaše e-mailová adresa byla ověřena $2 v $3.",
     "emailnotauthenticated": "Vaše e-mailová adresa dosud nebyla ověřena.\nU následujících funkcí nebudou zasílány žádné e-maily.",
     "noemailprefs": "Pro zprovoznění následujících možností musíte zadat svou e-mailovou adresu.",
     "accountcreated": "Účet vytvořen",
     "accountcreatedtext": "Uživatelský účet [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|diskuse]]) byl vytvořen.",
     "createaccount-title": "Vytvoření účtu na {{grammar:6sg|{{SITENAME}}}}",
-    "createaccount-text": "Někdo vytvořil na {{grammar:6sg|{{SITENAME}}}} ($4) účet s vaší e-mailovou adresou.\nJméno účtu: „$2“\nHeslo: „$3“\nMěli byste se co nejdřív přihlásit a změnit si heslo.\n\nPokud byl účet vytvořen omylem, považujte tuto zprávu za bezpředmětnou.",
-    "usernamehasherror": "Uživatelské jméno nemůže obsahovat znak mřížka (#)",
+    "createaccount-text": "Někdo na {{grammar:6sg|{{SITENAME}}}} ($4) vytvořil účet s vaší e-mailovou adresou.\nJméno účtu: „$2“\nHeslo: „$3“\nMěli byste se co nejdřív přihlásit a změnit si heslo.\n\nPokud byl účet vytvořen omylem, považujte tuto zprávu za bezpředmětnou.",
     "login-throttled": "Provedli jste příliš mnoho pokusů o přihlášení.\nNež to zkusíte znovu, musíte počkat na vypršení lhůty $1.",
     "login-abort-generic": "Vaše přihlášení se nezdařilo – přerušeno",
     "loginlanguagelabel": "Jazyk: $1",
     "resetpass-submit-cancel": "Storno",
     "resetpass-wrong-oldpass": "Nesprávné dočasné nebo aktuální heslo.\nMožná jste si již úspěšně heslo změnili, nebo jste si vyžádali nové dočasné heslo.",
     "resetpass-recycled": "Jako nové heslo si prosím nastavte něco jiného než stávající heslo.",
-    "resetpass-temp-emailed": "Přihlašujete se dočasným heslem zaslaným e-mailem.\nAbyste dokončili přihlášení, nastavte si zde nové heslo:",
+    "resetpass-temp-emailed": "Přihlašujete se dočasným heslem, zaslaným e-mailem.\nAbyste dokončili přihlášení, nastavte si zde nové heslo:",
     "resetpass-temp-password": "Dočasné heslo:",
     "resetpass-abort-generic": "Změna hesla byla zablokována rozšířením.",
     "resetpass-expired": "Platnost vašeho hesla vypršela. Pro přihlášení si nastavte nové heslo.",
     "passwordreset-capture-help": "Pokud zaškrtnete toto políčko, bude e-mail (s dočasným heslem) kromě zaslání uživateli zobrazen i vám.",
     "passwordreset-email": "E-mailová adresa:",
     "passwordreset-emailtitle": "Informace k účtu na {{grammar:6sg|{{SITENAME}}}}",
-    "passwordreset-emailtext-ip": "Někdo (patrně vy, z IP adresy $1) zažádal o nastavení nového hesla k vašemu účtu na {{grammar:6sg|{{SITENAME}}}} ($4). K této adrese {{PLURAL:$3|je přiřazen následující účet|jsou přiřazeny následující účty}}:\n\n$2\n\n{{PLURAL:$3|Toto dočasné heslo|Tato dočasná hesla}} vyprší {{PLURAL:$5|za jeden den|za $5 dny|za $5 dnů}}.\nNyní byste se měl(a) přihlásit a zvolit si nové heslo. Pokud tento požadavek\nposlal někdo jiný nebo jste si na své staré heslo vzpomněl(a), a nechcete ho\ntedy změnit, můžete tuto zprávu ignorovat a nadále používat původní heslo.",
-    "passwordreset-emailtext-user": "{{gender:$1|Uživatel|Uživatelka}} $1 na {{grammar:6sg|{{SITENAME}}}} {{gender:$1|zažádal|zažádala}} o nastavení nového hesla k vašemu\núčtu na {{grammar:6sg|{{SITENAME}}}} ($4). K této adrese {{PLURAL:$3|je přiřazen následující účet|jsou přiřazeny následující účty}}:\n\n$2\n\n{{PLURAL:$3|Toto dočasné heslo|Tato dočasná hesla}} vyprší {{PLURAL:$5|za jeden den|za $5 dny|za $5 dnů}}.\nNyní byste se měl(a) přihlásit a zvolit si nové heslo. Pokud tento požadavek\nposlal někdo jiný nebo jste si na své staré heslo vzpomněl(a), a nechcete ho\ntedy změnit, můžete tuto zprávu ignorovat a nadále používat původní heslo.",
+    "passwordreset-emailtext-ip": "Někdo (patrně vy, z IP adresy $1) zažádal na {{grammar:6sg|{{SITENAME}}}} ($4) o nastavení nového hesla k vašemu účtu. K této adrese {{PLURAL:$3|je přiřazen následující účet|jsou přiřazeny následující účty}}:\n\n$2\n\n{{PLURAL:$3|Toto dočasné heslo|Tato dočasná hesla}} vyprší {{PLURAL:$5|za jeden den|za $5 dny|za $5 dnů}}.\nNyní byste se měl(a) přihlásit a zvolit si nové heslo. Pokud tento požadavek\nposlal někdo jiný nebo jste si na své staré heslo vzpomněl(a), a nechcete ho\ntedy změnit, můžete tuto zprávu ignorovat a nadále používat původní heslo.",
+    "passwordreset-emailtext-user": "{{gender:$1|Uživatel|Uživatelka}} $1 na {{grammar:6sg|{{SITENAME}}}} {{gender:$1|zažádal|zažádala}} na {{grammar:6sg|{{SITENAME}}}} ($4) o nastavení nového hesla k vašemu\núčtu. K této adrese {{PLURAL:$3|je přiřazen následující účet|jsou přiřazeny následující účty}}:\n\n$2\n\n{{PLURAL:$3|Toto dočasné heslo|Tato dočasná hesla}} vyprší {{PLURAL:$5|za jeden den|za $5 dny|za $5 dnů}}.\nNyní byste se měl(a) přihlásit a zvolit si nové heslo. Pokud tento požadavek\nposlal někdo jiný nebo jste si na své staré heslo vzpomněl(a), a nechcete ho\ntedy změnit, můžete tuto zprávu ignorovat a nadále používat původní heslo.",
     "passwordreset-emailelement": "Uživatelské jméno: $1\nDočasné heslo: $2",
     "passwordreset-emailsent": "E-mail pro získání nového hesla byl odeslán.",
     "passwordreset-emailsent-capture": "Byl odeslán e-mail pro získání nového hesla, který je zobrazen níže.",
-    "passwordreset-emailerror-capture": "Byl vygenerován e-mail pro získání nového hesla, který je zobrazen níže, ale nepodařilo se ho odeslat {{GENDER:$2|uživateli|uživatelce}}: $1",
+    "passwordreset-emailerror-capture": "Byl vygenerován e-mail pro získání nového hesla, který je zobrazen níže, ale {{GENDER:$2|uživateli|uživatelce}} se ho nepodařilo odeslat: $1",
     "changeemail": "Změna e-mailové adresy",
     "changeemail-header": "Změna e-mailové adresy k účtu",
     "changeemail-text": "Vyplněním tohoto formuláře si změníte e-mailovou adresu. Pro potvrzení změny budete muset zadat své heslo.",
     "anontalkpagetext": "----''Toto je diskusní stránka anonymního uživatele, který si dosud nevytvořil účet nebo ho nepoužívá. K&nbsp;jeho identifikaci proto musíme používat číselnou IP adresu. Takovou IP adresu může sdílet několik uživatelů. Pokud jste anonymní uživatel a&nbsp;máte za to, že jsou vám adresovány irelevantní komentáře, prosíme, [[Special:UserLogin/signup|vytvořte si účet]] nebo [[Special:UserLogin|se přihlaste]], vyhnete se tím budoucí záměně s&nbsp;jinými anonymními uživateli.''",
     "noarticletext": "Tato stránka zatím neobsahuje žádný text.\nMůžete [[Special:Search/{{PAGENAME}}|zkusit tento název vyhledat]] na jiných stránkách, <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} prohlédnout si příslušné protokolovací záznamy] nebo [{{fullurl:{{FULLPAGENAME}}|action=edit}} tuto stránku založit]</span>.",
     "noarticletext-nopermission": "Tato stránka zatím neobsahuje žádný text.\nMůžete [[Special:Search/{{PAGENAME}}|zkusit tento název vyhledat]] na jiných stránkách nebo <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} si prohlédnout příslušné protokolovací záznamy]</span>, ale na založení této stránky nemáte oprávnění.",
-    "missing-revision": "Revize #$1 stránky s názvem „{{FULLPAGENAME}}“ neexistuje.\n\nToto je obvykle způsobeno tím, že jste následovali zastaralý odkaz historickou verzi stránky, jež byla smazána.\nPodrobnosti mohou být uvedeny v [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} knize smazaných stránek].",
+    "missing-revision": "Revize #$1 stránky s názvem „{{FULLPAGENAME}}“ neexistuje.\n\nToto je obvykle způsobeno tím, že jste následovali zastaralý odkaz na historickou verzi stránky, jež byla smazána.\nPodrobnosti mohou být uvedeny v [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} knize smazaných stránek].",
     "userpage-userdoesnotexist": "Uživatelský účet „<nowiki>$1</nowiki>“ není zaregistrován. Zkontrolujte zda skutečně chcete vytvořit či editovat tuto stránku.",
     "userpage-userdoesnotexist-view": "Uživatelský účet „$1“ není zaregistrován.",
     "blocked-notice-logextract": "Tento uživatel je momentálně zablokován.\nZde je pro přehled zobrazen nejnovější záznam z knihy zablokování:",
     "previewconflict": "Tento náhled ukazuje text tak, jak bude vypadat po uložení stránky.",
     "session_fail_preview": "'''Váš požadavek se nepodařilo zpracovat kvůli ztrátě dat z relace.\nZkuste to prosím znovu.\nPokud se tento problém bude opakovat, zkuste se [[Special:UserLogout|odhlásit]] a znovu přihlásit.'''",
     "session_fail_preview_html": "'''Váš požadavek se nepodařilo zpracovat kvůli ztrátě dat z relace.'''\n\n''Jelikož má {{SITENAME}} zapnuto používání neomezeného HTML, náhled se kvůli prevenci proti útokům JavaScriptem nezobrazuje.''\n\n'''Pokud jde o zamýšlenou editaci, zkuste to prosím znovu. Pokud se tento problém bude opakovat, zkuste se [[Special:UserLogout|odhlásit]] a znovu přihlásit.'''",
-    "token_suffix_mismatch": "'''Vaše editace byla odmítnuta, protože Váš prohlížeč komolí některé znaky v editovaném textu.\nEditace byla odmítnuta, aby se zabránilo poškození textu stránky.\nToto se může někdy stát pokud používáte chybující webový anonymizér.'''",
+    "token_suffix_mismatch": "'''Vaše editace byla odmítnuta, protože Váš prohlížeč komolí některé znaky v editovaném textu.\nEditace byla odmítnuta, aby se zabránilo poškození textu stránky.\nToto se někdy může někdy stát, používáte-li chybující webový anonymizér.'''",
     "edit_form_incomplete": "'''Část editačního formuláře nedorazila na server; překontrolujte úplnost změn a zkuste to znovu.'''",
     "editing": "Editace stránky $1",
     "creating": "Vytváření $1",
     "editingold": "'''VAROVÁNÍ: Nyní editujete zastaralou verzi této stránky. Když ji uložíte, všechny pozdější změny se ztratí.'''",
     "yourdiff": "Rozdíly",
     "copyrightwarning": "Všechny příspěvky do {{grammar:2sg|{{SITENAME}}}} jsou zveřejňovány podle $2 (podrobnosti najdete na $1).\nPokud si nepřejete, aby váš text byl nemilosrdně upravován a volně šířen, pak ho do {{grammar:2sg|{{SITENAME}}}} neukládejte.<br />\nUložením příspěvku se zavazujete, že je vaším dílem nebo je zkopírován ze zdrojů, které nejsou chráněny autorským právem (tzv. <em>public domain</em>).\n'''NEVKLÁDEJTE DÍLA CHRÁNĚNÁ AUTORSKÝM PRÁVEM BEZ DOVOLENÍ!'''",
-    "copyrightwarning2": "Uvědomte si, že všechny příspěvky do {{grammar:2sg|{{SITENAME}}}} mohou být ostatními uživateli upraveny, pozměněny či odstraněny. Pokud si nepřejete, aby váš text byl nemilosrdně upravován, pak ho do {{grammar:2sg|{{SITENAME}}}} neukládejte.<br />\nUložením příspěvku se zavazujete, že je vaším dílem nebo je zkopírován ze zdrojů, které nejsou chráněny autorským právem (tzv. <em>public domain</em>), podrobnosti najdete na $1. '''Nekopírujte díla chráněná autorským právem bez dovolení!'''",
+    "copyrightwarning2": "Uvědomte si, že všechny příspěvky do {{grammar:2sg|{{SITENAME}}}} mohou být ostatními uživateli upraveny, pozměněny či odstraněny. Pokud si nepřejete, aby váš text byl nemilosrdně upravován, pak ho do {{grammar:2sg|{{SITENAME}}}} neukládejte.<br />\nUložením příspěvku se zavazujete, že je vaším dílem nebo je zkopírován ze zdrojů, které nejsou chráněny autorským právem (tzv. <em>public domain</em>); podrobnosti najdete na $1. '''Nekopírujte díla chráněná autorským právem bez dovolení!'''",
     "longpageerror": "'''Chyba: Pokoušíte se uložit text o velikosti {{PLURAL:$1|$1 KiB}}, přičemž dovolené maximum je {{PLURAL:$2|$2 KiB}}.'''\nVaše změna nemůže být uložena.",
-    "readonlywarning": "'''Varování: Databáze byla uzamčena kvůli údržbě, takže momentálně nebudete moci uložit své změny.'''\nMůžete si okopírovat text do souboru a uložit ho na později.\n\nSprávce serveru, který databázi zamkl, poskytl toto zdůvodnění: $1",
+    "readonlywarning": "<strong>Varování: Databáze byla uzamčena kvůli údržbě, takže momentálně nebudete moci uložit své změny.</strong>\nMůžete si okopírovat text do souboru a uložit si ho na později.\n\nSprávce serveru, který databázi zamkl, poskytl toto zdůvodnění: $1",
     "protectedpagewarning": "'''Varování: Tato stránka byla zamčena, takže ji mohou editovat pouze správci.'''\nNíže je pro přehled zobrazen nejnovější protokolovací záznam:",
     "semiprotectedpagewarning": "'''Poznámka:''' Tato stránka byla zamčena, takže ji mohou editovat pouze registrovaní uživatelé.\nNíže je pro přehled zobrazen nejnovější protokolovací záznam:",
     "cascadeprotectedwarning": "'''Varování:''' Tato stránka byla zamčena, takže ji mohou editovat pouze správci. Je vložena na následující, kaskádním zámkem  {{PLURAL:$1|zamčenou, stránku|zamčené, stránky|zamčené, stránky}}:",
     "revdelete-radio-set": "Skrytý",
     "revdelete-radio-unset": "Viditelný",
     "revdelete-suppress": "Utajit data i před správci",
-    "revdelete-unsuppress": "Odstranit omezení na vrácené verze",
+    "revdelete-unsuppress": "Odstranit omezení na obnovených revizích",
     "revdelete-log": "Důvod:",
     "revdelete-submit": "Aplikovat na {{PLURAL:$1|zvolenou revizi|zvolené revize}}",
     "revdelete-success": "'''Viditelnost revize úspěšně nastavena.'''",
     "revdelete-modify-missing": "Chyba při změně položky s ID $1: položka nenalezena v databázi!",
     "revdelete-no-change": "'''Upozornění:''' položka z $1 $2 už měla viditelnost nastavenou tak, jak bylo požadováno.",
     "revdelete-concurrent-change": "Chyba při změně položky z $1 $2: zdá se, že mezitím její stav změnil někdo jiný.\nProhlédněte si protokolovací záznamy.",
-    "revdelete-only-restricted": "Chyba skrývání položky z $2 $1: Nemůžete položky pouze skrýt před správci, aniž byste současně vybrali i některou z dalších možností utajení.",
+    "revdelete-only-restricted": "Chyba skrývání položky z $2 $1: Položky před správci nemůžete skrýt, aniž byste současně vybrali i některou z dalších možností utajení.",
     "revdelete-reason-dropdown": "*Obvyklé důvody smazání\n** Porušení autorských práv\n** Nevhodné komentáře nebo osobní údaje\n** Nevhodné uživatelské jméno\n** Potenciálně pomlouvačné údaje",
     "revdelete-otherreason": "Jiný/další důvod:",
     "revdelete-reasonotherlist": "Jiný důvod",
     "showhideselectedversions": "Zobrazit/skrýt vybrané revize",
     "editundo": "zrušit editaci",
     "diff-empty": "(Žádný rozdíl)",
-    "diff-multi-sameuser": "({{PLURAL:$1|Není zobrazena 1 mezilehlá verze|Nejsou zobrazeny $1 mezilehlé verze|Není zobrazeno $1 mezilehlých verzí}} od stejného uživatele.)",
-    "diff-multi-otherusers": "({{PLURAL:$1|Není zobrazena 1 mezilehlá verze|Nejsou zobrazeny $1 mezilehlé verze|Není zobrazeno $1 mezilehlých verzí}} od {{PLURAL:$2|1 dalšího uživatele|$2 dalších uživatelů}}.)",
-    "diff-multi-manyusers": "(Není zobrazeno $1 mezilehlých verzí od více než $2 {{PLURAL:$2|uživatele|uživatelů}}.)",
-    "difference-missing-revision": "{{PLURAL:$2|Jedna z revizí|$2 revize|$2 revizí}} k požadovanému porovnání ($1) {{PLURAL:$2|neexistuje|neexistují|neexistuje}}.\n\nToto je obvykle způsobeno tím, že jste následovali zastaralý odkaz historickou verzi stránky, jež byla smazána.\nPodrobnosti mohou být uvedeny v [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} knize smazaných stránek].",
+    "diff-multi-sameuser": "({{PLURAL:$1|Není zobrazena jedna mezilehlá verze|Nejsou zobrazeny $1 mezilehlé verze|Není zobrazeno $1 mezilehlých verzí}} od stejného uživatele.)",
+    "diff-multi-otherusers": "({{PLURAL:$1|Není zobrazena jedna mezilehlá verze|Nejsou zobrazeny $1 mezilehlé verze|Není zobrazeno $1 mezilehlých verzí}} od {{PLURAL:$2|jednoho dalšího uživatele|$2 dalších uživatelů}}.)",
+    "diff-multi-manyusers": "({{PLURAL:$1|Není zobrazena 1 mezilehlá verze|Nejsou zobrazeny $1 mezilehlé verze|Není zobrazeno $1 mezilehlých verzí}} od více než {{PLURAL:$2|1 uživatele|$2 uživatelů}}.)",
+    "difference-missing-revision": "{{PLURAL:$2|Jedna z revizí|$2 revize|$2 revizí}} k požadovanému porovnání ($1) {{PLURAL:$2|neexistuje|neexistují|neexistuje}}.\n\nToto je obvykle způsobeno tím, že jste následovali zastaralý odkaz na historickou verzi stránky, jež byla smazána.\nPodrobnosti mohou být uvedeny v [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} knize smazaných stránek].",
     "searchresults": "Výsledky hledání",
     "searchresults-title": "Výsledky hledání „$1“",
     "toomanymatches": "Požadavku odpovídá příliš mnoho záznamů, zkuste jiný dotaz.",
     "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",
     "right-suppressredirect": "Nevytváření přesměrování po přesunu stránky",
     "right-upload": "Nahrávání souborů",
     "right-reupload": "Přepisování existujících souborů",
-    "right-reupload-own": "Přepisování souborů nahraných sám sebou",
+    "right-reupload-own": "Přepisování souborů nahraných sebou samotným",
     "right-reupload-shared": "Nahrávání lokálních souborů k potlačení těch ve sdíleném úložišti",
     "right-upload_by_url": "Nahrávání souborů z URL adres",
     "right-purge": "Vyčištění vyrovnávací paměti stránky bez potvrzovacího dialogu",
     "right-editusercssjs": "Editace CSS a JS souborů jiných uživatelů",
     "right-editusercss": "Editace CSS souborů jiných uživatelů",
     "right-edituserjs": "Editace JavaScriptových souborů jiných uživatelů",
-    "right-editmyusercss": "Editace vašich uživatelských CSS souborů",
-    "right-editmyuserjs": "Editace vašich uživatelských JavaScriptových souborů",
+    "right-editmyusercss": "Editace vlastních uživatelských CSS souborů",
+    "right-editmyuserjs": "Editace vlastních uživatelských JavaScriptových souborů",
     "right-viewmywatchlist": "Prohlížení vlastního seznamu sledovaných stránek",
     "right-editmywatchlist": "Editace vlastního seznamu sledovaných stránek. Uvědomte si, že některé akce do něj mohou přidat stránky i bez tohoto oprávnění.",
     "right-viewmyprivateinfo": "Prohlížení vlastních soukromých údajů (např. e-mailová adresa, skutečné jméno)",
     "action-browsearchive": "hledat smazané stránky",
     "action-undelete": "obnovit tuto stránku",
     "action-suppressrevision": "zkontrolovat a obnovit tuto skrytou revizi",
-    "action-suppressionlog": "prohlížet si tento skrytý protokolovací záznam",
+    "action-suppressionlog": "prohlédnout si tento skrytý protokolovací záznam",
     "action-block": "znemožnit tomuto uživateli editování",
     "action-protect": "změnit úrovně ochrany této stránky",
     "action-rollback": "rychle revertovat úpravy posledního uživatele editujícího danou stránku",
     "enhancedrc-history": "historie",
     "recentchanges": "Poslední změny",
     "recentchanges-legend": "Možnosti posledních změn",
-    "recentchanges-summary": "Sledujte poslední změny na {{grammar:6sg|{{SITENAME}}}} na této stránce.",
+    "recentchanges-summary": "Sledujte poslední změny {{grammar:2sg|{{SITENAME}}}} na této stránce.",
     "recentchanges-noresult": "V daném období neodpovídaly zadaným kritériím žádné změny.",
     "recentchanges-feed-description": "Na tomto kanále sledujte poslední změny na {{grammar:6sg|{{SITENAME}}}}.",
     "recentchanges-label-newpage": "Touto editací byla založena nová stránka",
     "upload_directory_read_only": "Do adresáře pro načítané soubory ($1) nemá webserver právo zápisu.",
     "uploaderror": "Při načítání došlo k chybě",
     "upload-recreate-warning": "'''Upozornění: Soubor pod tímto názvem byl dříve smazán či přejmenován.'''\n\nZde je pro přehled zobrazen soupis mazání a přesunů této stránky:",
-    "uploadtext": "Níže uvedený formulář slouží k načtení souborů. Již načtené soubory si můžete prohlížet a hledat pomocí [[Special:FileList|seznamu načtených souborů]], každé načtení se také zaznamenává do [[Special:Log/upload|knihy načtení]], smazání jsou v [[Special:Log/delete|knize smazaných stránek]].\n\nPro vložení obrázku do stránky použijte jeden z následujících způsobů zápisu:\n* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:Soubor.jpg]]</nowiki></code>''' do stránky vloží celý obrázek,\n* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:Soubor.png|thumb|left|Popisek]]</nowiki></code>''' vloží náhled v rámečku zarovnaném na levý okraj, s popiskem „Popisek“,\n* '''<code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:Soubor.ogg]]</nowiki></code>''' vloží přímý odkaz na soubor, aniž by se zobrazoval ve stránce.",
+    "uploadtext": "Níže uvedený formulář slouží k načtení souborů. Již načtené soubory si můžete prohlížet a hledat pomocí [[Special:FileList|seznamu načtených souborů]], každé načtení se také zaznamenává do [[Special:Log/upload|knihy nahrávek]], smazání jsou v [[Special:Log/delete|knize smazaných stránek]].\n\nPro vložení obrázku do stránky použijte jeden z následujících způsobů zápisu:\n* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:Soubor.jpg]]</nowiki></code>''' do stránky vloží celý obrázek,\n* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:Soubor.png|thumb|left|Popisek]]</nowiki></code>''' vloží náhled v rámečku zarovnaném na levý okraj, s popiskem „Popisek“,\n* '''<code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:Soubor.ogg]]</nowiki></code>''' vloží přímý odkaz na soubor, aniž by se ten na stránce zobrazoval.",
     "upload-permitted": "Povolené formáty souborů: $1.",
     "upload-preferred": "Upřednostňované formáty souborů: $1.",
     "upload-prohibited": "Zakázané formáty souborů: $1.",
-    "uploadlog": "kniha nahrávek",
     "uploadlogpage": "Kniha nahrávek",
     "uploadlogpagetext": "Níže najdete seznam nejnovějších souborů.",
     "filename": "Soubor",
     "filereuploadsummary": "Změny v souboru:",
     "filestatus": "Autorská práva:",
     "filesource": "Zdroj:",
-    "uploadedfiles": "Načtené soubory",
     "ignorewarning": "Ignorovat varování a načíst soubor.",
     "ignorewarnings": "Ignorovat všechna varování",
     "minlength1": "Jméno souboru musí mít alespoň jeden znak.",
     "overwroteimage": "načtena nová verze \"[[$1]]\"",
     "uploaddisabled": "Načítání souborů vypnuto.",
     "copyuploaddisabled": "Načítání souborů prostřednictvím URL je vypnuto.",
-    "uploadfromurl-queued": "Váš požadavek na načtení souboru byl uložen do fronty.",
     "uploaddisabledtext": "Načítání souborů je vypnuto.",
     "php-uploaddisabledtext": "V PHP je vypnuto načítání souborů. Prosím, zkontrolujte nastavení file_uploads.",
     "uploadscripted": "Tento soubor obsahuje HTML nebo kód skriptu, který by mohl být prohlížečem chybně interpretován.",
     "upload-options": "Možnosti načtení",
     "watchthisupload": "Sledovat tento soubor",
     "filewasdeleted": "Soubor stejného jména byl již dříve načten a posléze smazán. Podrobnosti obsahuje $1.",
-    "filename-bad-prefix": "Jméno souboru, který naÄ\8dítáte, zaÄ\8díná na '''â\80\9e$1â\80\9c''', což je nevhodné jméno, obvykle automaticky pÅ\99\99azované digitálním fotoaparátem. Zvolte jméno, která váš soubor lépe popíše.",
+    "filename-bad-prefix": "Jméno souboru, který naÄ\8dítáte, zaÄ\8díná na '''â\80\9e$1â\80\9c''', což je nevhodné jméno, obvykle automaticky pÅ\99\99azované digitálním fotoaparátem. Zvolte jméno, které váš soubor popíše lépe.",
     "filename-prefix-blacklist": " #<!-- tuto řádku ponechte beze změny --> <pre>\n# Používá se následující syntaxe:\n#   * Cokoli od znaku „#“ až do konce řádky je komentář\n#   * Každá neprázdná řádka je prefix typických jmen souborů automaticky generovaných digitálními fotoaparáty\nCIMG # Casio\nDSC_ # Nikon\nDSCF # Fuji\nDSCN # Nikon\nDUW # některé mobilní telefony\nIMG # obecné\nJD # Jenoptik\nMGP # Pentax\nPICT # různé\n #</pre> <!-- tuto řádku ponechte beze změny -->",
     "upload-success-subj": "Načtení úspěšně provedeno!",
     "upload-success-msg": "Soubor vámi načtený z [$2] je dostupný na [[:{{ns:file}}:$1]]",
     "upload-misc-error": "Neznámá chyba",
     "upload-misc-error-text": "Neznámá chyba se vyskytla během nahrávání souboru.  Zkontrolujte zda je URL platná a přístupné a zkuste to znovu.  Pokud se chyba znovu objeví, kontaktuje [[Special:ListUsers/sysop|správce]].",
     "upload-too-many-redirects": "URL obsahovalo příliš mnoho přesměrování",
-    "upload-unknown-size": "Neznámá velikost",
     "upload-http-error": "Došlo k chybě HTTP: $1",
     "upload-copy-upload-invalid-domain": "Načítání kopírováním není dostupné z této domény.",
     "backend-fail-stream": "Soubor $1 nelze streamovat.",
     "img-auth-streaming": "Přenáší se „$1“.",
     "img-auth-public": "Pomocí img_auth.php se poskytují soubory na soukromých wiki.\nTato wiki je nastavena jako veřejná.\nZ bezpečnostních důvodů je img_auth.php vypnuto.",
     "img-auth-noread": "Uživatel nemá oprávnění ke čtení „$1“.",
-    "img-auth-bad-query-string": "URL obsahuje neplatný dotaz.",
     "http-invalid-url": "Neplatné URL: $1",
     "http-invalid-scheme": "URL používající schéma „$1“ nejsou podporována",
     "http-request-error": "Neznámá chyba při odesílání požadavku.",
     "http-curl-error": "Chyba při čtení z URL: $1",
     "http-bad-status": "Při provádění HTTP požadavku nastal problém: $1 $2",
     "upload-curl-error6": "Z URL nelze číst",
-    "upload-curl-error6-text": "Ze zadané URL nelze číst.  Zkontrolujte ža URL je správně napsané a server je dostupný",
+    "upload-curl-error6-text": "Ze zadané URL nelze číst. Zkontrolujte, zda je URL správně napsané a server je dostupný",
     "upload-curl-error28": "Čas pro nahrání vypršel",
-    "upload-curl-error28-text": "Serveru dlouho neodpovídá. Zkontrolujte, že server je dostupný, počkejte chvíli a zkuste to znovu.",
+    "upload-curl-error28-text": "Server dlouho neodpovídá. Zkontrolujte, zda je dostupný, chvíli počkejte a zkuste to znovu.",
     "license": "Licence:",
     "license-header": "Licence",
     "nolicense": "Bez udání licence",
     "filehist-dimensions": "Rozměry",
     "filehist-filesize": "Velikost souboru",
     "filehist-comment": "Komentář",
-    "filehist-missing": "Soubor chybí",
     "imagelinks": "Využití souboru",
     "linkstoimage": "Na soubor {{PLURAL:$1|odkazuje tato stránka|odkazují tyto $1 stránky|odkazuje těchto $1 stránek}}:",
     "linkstoimage-more": "Na tento soubor {{PLURAL:$1|odkazuje více stránek|odkazují více než $1 stránky|odkazuje více než $1 stránek}}.\nNásledující seznam zobrazuje pouze {{PLURAL:$1|tu první|první $1|prvních $1}}.\nMůžete si prohlédnout [[Special:WhatLinksHere/$2|úplný seznam]].",
     "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",
+    "listgrouprights-namespaceprotection-header": "Omezení jmenných prostorů",
+    "listgrouprights-namespaceprotection-namespace": "Jmenný prostor",
+    "listgrouprights-namespaceprotection-restrictedto": "Oprávnění umožňující uživateli editovat",
     "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.",
+    "noindex-category-desc": "Stránka není indexována roboty, protože obsahuje kouzelné slovo <code><nowiki>__NOINDEX__</nowiki></code> a je ve jmenném prostoru, ve kterém je tento příznak dovolen.",
+    "index-category-desc": "Stránka obsahuje kouzelné slovo <code><nowiki>__INDEX__</nowiki></code> (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ž <code>$wgMaxArticleSize</code>, 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ř. <code>{{{Foo}}})</code> je stránka větší než <code>$wgMaxArticleSize</code>.",
     "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.",
+    "hidden-category-category-desc": "Toto je kategorie, která obsahuje <code><nowiki>__HIDDENCAT__</nowiki></code>, 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",
     "emailuser-title-notarget": "Poslat e-mail uživateli",
     "emailpage": "Poslat e-mail",
     "emailpagetext": "Pomocí níže zobrazeného formuláře můžete {{GENDER:$1|tomuto uživateli|této uživatelce}} poslat zprávu e-mailem.\nE-mailová adresa, kterou máte uvedenu v [[Special:Preferences|nastavení]], se objeví jako adresa odesílatele pošty, aby vám adresát mohl odpovědět přímo.",
-    "usermailererror": "Chyba poštovního programu:",
     "defemailsubject": "E-mail z {{grammar:2sg|{{SITENAME}}}} od {{gender:$1|uživatele|uživatelky|uživatele}} „$1“",
     "usermaildisabled": "Posílání e-mailů je vypnuto",
     "usermaildisabledtext": "Nemáte oprávnění odesílat e-maily ostatním uživatelům této wiki",
     "noemailtitle": "Bez e-mailové adresy",
     "noemailtext": "Tento uživatel nezadal platnou e-mailovou adresu.",
-    "nowikiemailtitle": "E-mail není povolen",
     "nowikiemailtext": "Tento uživatel si nepřeje dostávat e-maily od ostatních uživatelů.",
     "emailnotarget": "Neexistující nebo neplatné uživatelské jméno příjemce.",
     "emailtarget": "Zadejte uživatelské jméno příjemce",
     "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",
     "watching": "Přidávám na seznam sledovaných stránek…",
     "unwatching": "Odebírám ze seznamu sledovaných stránek…",
     "watcherrortext": "Při změně sledování stránky „$1“ došlo k chybě.",
-    "enotif_mailer": "Zasílač hlášení {{grammar:2sg|{{SITENAME}}}}",
     "enotif_reset": "Označit vše jako navštívené",
     "enotif_impersonal_salutation": "Uživatel {{grammar:2sg|{{SITENAME}}}}",
     "enotif_subject_deleted": "$2 {{gender:$2|smazal|smazala}} stránku $1 na {{grammar:6sg|{{SITENAME}}}}",
     "excontent": "obsah byl: „$1“",
     "excontentauthor": "obsah byl: „$1“ (a jediným přispěvatelem byl „[[Special:Contributions/$2|$2]]“)",
     "exbeforeblank": "obsah před vyprázdněním byl: „$1“",
-    "exblank": "stránka byla prázdná",
     "delete-confirm": "Smazání stránky „$1“",
     "delete-legend": "Smazat",
     "historywarning": "'''Varování:''' Stránka, kterou chcete smazat, má historii se zhruba $1 {{PLURAL:$1|revizí|revizemi}}:",
     "importunknownsource": "Neznámý typ zdroje importu",
     "importcantopen": "Nepodařilo se otevřít importní soubor",
     "importbadinterwiki": "Neplatný interwiki odkaz",
-    "importnotext": "Prázdný nebo žádný text",
     "importsuccess": "Import skončil!",
-    "importhistoryconflict": "Existuje konflikt mezi historiemi verzí. Možná, že tato stránka byla již importována dříve.",
     "importnosources": "Nebyly definovány žádné zdroje pro import mezi wiki a přímé načítání historie je vypnuto.",
     "importnofile": "Nebyl načten importní soubor.",
     "importuploaderrorsize": "Nepodařilo se načíst importní soubor. Soubor je větší než povolená velikost.",
index aedeea9..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",
index 13a6e69..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",
index 66cb615..2aa2fc1 100644 (file)
     "permalink": "Permanenter Link",
     "print": "Drucken",
     "view": "Lesen",
+    "view-foreign": "Auf $1 ansehen",
     "edit": "Bearbeiten",
+    "edit-local": "Lokale Beschreibung bearbeiten",
     "create": "Erstellen",
+    "create-local": "Lokale Beschreibung hinzufügen",
     "editthispage": "Seite bearbeiten",
     "create-this-page": "Seite erstellen",
     "delete": "Löschen",
     "accountcreatedtext": "Das Benutzerkonto für [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|Diskussion]]) wurde eingerichtet.",
     "createaccount-title": "Erstellung eines Benutzerkontos für {{SITENAME}}",
     "createaccount-text": "Es wurde für dich ein Benutzerkonto „$2“ auf {{SITENAME}} ($4) erstellt. Das automatisch generierte Passwort für „$2“ ist „$3“. Du solltest dich nun anmelden und das Passwort ändern.\n\nFalls das Benutzerkonto irrtümlich angelegt wurde, kannst du diese Nachricht ignorieren.",
-    "usernamehasherror": "Benutzernamen dürfen kein Rautenzeichen enthalten",
     "login-throttled": "Du hast zu oft versucht, dich anzumelden.\nBitte warte $1, bevor du es erneut probierst.",
     "login-abort-generic": "Deine Anmeldung war nicht erfolgreich – Abgebrochen",
     "loginlanguagelabel": "Sprache: $1",
     "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",
     "upload-permitted": "Erlaubte Dateitypen: $1.",
     "upload-preferred": "Bevorzugte Dateitypen: $1.",
     "upload-prohibited": "Nicht erlaubte Dateitypen: $1.",
-    "uploadlog": "Datei-Logbuch",
     "uploadlogpage": "Datei-Logbuch",
     "uploadlogpagetext": "Dies ist das Logbuch der hochgeladenen Dateien, siehe auch die [[Special:NewFiles|Galerie neuer Dateien]] für einen visuellen Überblick.",
     "filename": "Dateiname",
     "filereuploadsummary": "Dateiänderungen:",
     "filestatus": "Copyright-Status:",
     "filesource": "Quelle:",
-    "uploadedfiles": "Hochladen",
     "ignorewarning": "Warnung ignorieren und Datei speichern",
     "ignorewarnings": "Warnungen ignorieren",
     "minlength1": "Dateinamen müssen mindestens einen Buchstaben lang sein.",
     "overwroteimage": "lud eine neue Version von „[[$1]]“ hoch",
     "uploaddisabled": "Hochladen deaktiviert",
     "copyuploaddisabled": "Das Hochladen von URLs ist deaktiviert",
-    "uploadfromurl-queued": "Dein Upload befindet sich nun in der Warteschlange.",
     "uploaddisabledtext": "Das Hochladen von Dateien ist deaktiviert.",
     "php-uploaddisabledtext": "Das Hochladen von Dateien wurde in PHP deaktiviert.\nBitte überprüfe die <code>file_uploads</code>-Einstellung.",
     "uploadscripted": "Diese Datei enthält HTML- oder Scriptcode, der irrtümlich von einem Webbrowser ausgeführt werden könnte.",
     "upload-misc-error": "Unbekannter Fehler beim Hochladen",
     "upload-misc-error-text": "Beim Hochladen ist ein unbekannter Fehler aufgetreten.\nPrüfe die URL auf Fehler, den Online-Status der Seite und versuche es erneut.\nWenn das Problem weiter besteht, informiere einen [[Special:ListUsers/sysop|Administrator]].",
     "upload-too-many-redirects": "Die URL beinhaltete zu viele Weiterleitungen",
-    "upload-unknown-size": "Unbekannte Größe",
     "upload-http-error": "Ein HTTP-Fehler ist aufgetreten: $1",
     "upload-copy-upload-invalid-domain": "Als Kopie hochladbare Dateien sind über diese Domain nicht verfügbar.",
     "backend-fail-stream": "Die Datei $1 konnte nicht übertragen werden.",
     "img-auth-streaming": "Lade „$1“.",
     "img-auth-public": "img_auth.php gibt Dateien von einem privaten Wiki aus.\nDieses Wiki wurde als ein öffentliches Wiki konfiguriert.\nAus Sicherheitsgründen ist img_auth.php deaktiviert.",
     "img-auth-noread": "Benutzer hat keine Berechtigung, „$1“ zu lesen.",
-    "img-auth-bad-query-string": "Die URL weist eine ungültige Abfragezeichenfolge auf.",
     "http-invalid-url": "Ungültige URL: $1",
     "http-invalid-scheme": "URLs mit dem Schema „$1“ werden nicht unterstützt",
     "http-request-error": "Fehler beim Senden der Anfrage.",
     "filehist-dimensions": "Maße",
     "filehist-filesize": "Dateigröße",
     "filehist-comment": "Kommentar",
-    "filehist-missing": "Datei fehlt",
     "imagelinks": "Dateiverwendung",
     "linkstoimage": "Die {{PLURAL:$1|folgende Seite verwendet|folgenden $1 Seiten verwenden}} diese Datei:",
     "linkstoimage-more": "Mehr als {{PLURAL:$1|eine Seite verlinkt|$1 Seiten verlinken}} auf diese Datei.\nDie folgende Liste zeigt nur {{PLURAL:$1|den ersten Link|die ersten $1 Links}} auf diese Datei.\nEine [[Special:WhatLinksHere/$2|vollständige Liste]] ist verfügbar.",
     "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",
+    "listgrouprights-namespaceprotection-header": "Namensraumbeschränkungen",
+    "listgrouprights-namespaceprotection-namespace": "Namensraum",
+    "listgrouprights-namespaceprotection-restrictedto": "Rechte, die dem Benutzer die Bearbeitung erlauben",
     "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.",
+    "noindex-category-desc": "Die Seite wird nicht von Bots indexiert, da sie das magische Wort <code><nowiki>__NOINDEX__</nowiki></code> enthält und sich in einem Namensraum befindet, wo dieses Flag erlaubt ist.",
+    "index-category-desc": "Die Seite enthält ein <code><nowiki>__INDEX__</nowiki></code> 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 <code>$wgMaxArticleSize</code>, 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. <code>{{{Foo}}})</code> ist die Seite größer als <code>$wgMaxArticleSize</code>.",
     "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.",
+    "hidden-category-category-desc": "Dies ist eine Kategorie mit <code><nowiki>__HIDDENCAT__</nowiki></code>, 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",
     "emailuser-title-notarget": "E-Mail an Benutzer",
     "emailpage": "E-Mail an Benutzer",
     "emailpagetext": "Du kannst {{GENDER:$1|dem Benutzer|der Benutzerin}} mit dem unten stehenden Formular eine E-Mail senden.\nAls Absender wird die E-Mail-Adresse aus deinen [[Special:Preferences|Einstellungen]] eingetragen, damit {{GENDER:$1|der Benutzer|die Benutzerin}} dir direkt antworten kann.",
-    "usermailererror": "Das E-Mail-Objekt gab einen Fehler zurück:",
     "defemailsubject": "{{SITENAME}} – E-Mail von Benutzer „$1“",
     "usermaildisabled": "E-Mail-Empfang deaktiviert",
     "usermaildisabledtext": "Du kannst in diesem Wiki keine E-Mails an andere Benutzer senden",
     "noemailtitle": "Keine E-Mail-Adresse",
     "noemailtext": "Dieser Benutzer hat keine gültige E-Mail-Adresse angegeben.",
-    "nowikiemailtitle": "E-Mail-Versand nicht möglich",
     "nowikiemailtext": "Dieser Benutzer möchte keine E-Mails von anderen Benutzern erhalten.",
     "emailnotarget": "Nicht vorhandener oder ungültiger Benutzername für den Empfang einer E-Mail.",
     "emailtarget": "Benutzernamen des Empfängers eingeben",
     "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",
     "watching": "Beobachten …",
     "unwatching": "Nicht mehr beobachten …",
     "watcherrortext": "Beim Ändern der Beobachtungslisteneinstellungen für „$1“ ist ein Fehler aufgetreten.",
-    "enotif_mailer": "{{SITENAME}}-E-Mail-Benachrichtigungsdienst",
     "enotif_reset": "Alle Seiten als besucht markieren",
     "enotif_impersonal_salutation": "{{SITENAME}}-Benutzer",
     "enotif_subject_deleted": "{{SITENAME}}-Seite $1 wurde von {{GENDER:$2|$2}} gelöscht",
     "excontent": "Inhalt war: „$1“",
     "excontentauthor": "Inhalt war: „$1“ (einziger Bearbeiter: [[Special:Contributions/$2|$2]])",
     "exbeforeblank": "Inhalt vor dem Leeren der Seite: „$1“",
-    "exblank": "Seite war leer",
     "delete-confirm": "Löschen von „$1“",
     "delete-legend": "Löschen",
     "historywarning": "'''Achtung:''' Die Seite, die du löschen möchtest, hat eine Versionsgeschichte mit ungefähr $1 {{PLURAL:$1|Version|Versionen}}:",
     "importunknownsource": "Unbekannte Importquelle",
     "importcantopen": "Importdatei konnte nicht geöffnet werden",
     "importbadinterwiki": "Falscher Interwiki-Link",
-    "importnotext": "Leer oder kein Text",
     "importsuccess": "Import abgeschlossen.",
-    "importhistoryconflict": "Es existieren bereits ältere Versionen, welche mit diesen kollidieren. Möglicherweise wurde die Seite bereits vorher importiert.",
     "importnosources": "Für den Transwiki-Import sind keine Quellen definiert. Das direkte Hochladen von Versionen ist gesperrt.",
     "importnofile": "Es ist keine Importdatei ausgewählt worden.",
     "importuploaderrorsize": "Das Hochladen der Importdatei ist fehlgeschlagen. Die Datei ist größer als die maximal erlaubte Dateigröße.",
index 8df565f..c2f023b 100644 (file)
@@ -16,7 +16,9 @@
             "Olvörg",
             "Reedy",
             "Sahim",
-            "Xoser"
+            "Xoser",
+            "Geitost",
+            "Microchip08"
         ]
     },
     "tog-underline": "Bınê gırey de xete bance:",
     "pool-queuefull": "Rêza hewze pırra",
     "pool-errorunknown": "Xeta nêzanıtiye",
     "aboutsite": "Heqa {{SITENAME}} de",
-    "aboutpage": "Project:Heqa  de",
+    "aboutpage": "Project:Heqa {{SITENAME}} de",
     "copyright": "Zerrekacı $1 bındı not biya.",
     "copyrightpage": "{{ns:project}}:Heqa telifi",
     "currentevents": "Veng u vac",
     "accountcreatedtext": "Qandê [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|talk]]) hesabê karberi vıraziyayo.",
     "createaccount-title": "Qandé  {{SITENAME}} hesabé karberi iycat kerdış",
     "createaccount-text": "Kesê, be e-posteyê şıma ra {{SITENAME}} ($4) de, ebe nameyê \"$2\" u parola \"$3\" ra yew hesab vıraşto.\nŞıma gani cı kewê u parola xo nıka bıvurnê.",
-    "usernamehasherror": "Namey karberi de karakteri gani têmiyan ra mebê",
     "login-throttled": "Demekê $1 cıwa ver de şıma zah teşebbusê hesab akerdış kerd.\nBıne vındere u newe ra dest pê bıkere.",
     "login-abort-generic": "Dekewtışê şıma xırabo-terkneyayo",
     "loginlanguagelabel": "Zıwan: $1",
     "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": "$1 vuriyeno",
+    "creating": "$1 vıraziyeno",
     "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",
+    "editconflict": "Têverabiyayışê vurnayışi: $1",
     "explainconflict": "Wexta ke şıma pel vurneyene yewna ten zi pel vurna.\nNuşteyo corin; halê pelo nıkayin mocneno.\nVurnayişê şıma cêr de mocya ( musya).\nVurnayişanê peyinan şıma gani qayd bıkeri.\nWexta ke şıma butonê \"{{int:savearticle}}\" tıkna '''teyna''' nuşteyo corin qayd beno.",
     "yourtext": "nuşteyê şıma",
     "storedversion": "Nuşteyo qaydbiyaye",
     "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": "Têverabiyayışê vurnayışi.",
     "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",
     "upload-permitted": "Tipanê dosyayi ke izin ey estê: $1.",
     "upload-preferred": "Tipanê dosyayi ke tercihe ey estê: $1",
     "upload-prohibited": "Babetê dosyayanê tometebiyayeyan: $1.",
-    "uploadlog": "cıkewtışê barkerdışi",
     "uploadlogpage": "Cıkewtışê bar-kerdışi",
     "uploadlogpagetext": "cêr de [[Special:NewFiles|listeyê dosyayan]] estî.",
     "filename": "Namey Dosya",
     "filereuploadsummary": "Vurnayîşê dosyayî:",
     "filestatus": "Weziyetê heqa telifi:",
     "filesource": "Çıme:",
-    "uploadedfiles": "Dosyayê ke bar biye",
     "ignorewarning": "Îkazi kebul meke u dosya reyna bar bike",
     "ignorewarnings": "Îkazi kebul meke",
     "minlength1": "Nameyanê dosyayî de gani bî ezamî yew herf est biyê.",
     "overwroteimage": "yew versiyonê newvî ye \"[[$1]]\"î bar bike",
     "uploaddisabled": "bar kerdişî iptal biyo",
     "copyuploaddisabled": "URL bar kerdiş kefiliyeyo.",
-    "uploadfromurl-queued": "Bar kerdişê tu ha sira de vindeno.",
     "uploaddisabledtext": "Bar kerdişê dosyayî iptal biyo",
     "php-uploaddisabledtext": "barkerdışê dosyayê PHP nıka çino. kerem kere eyarê file_uploads korol bıkerê.",
     "uploadscripted": "Ena dosya de yew HTML ya zi kodê scriptî este ke belki browserê webî fam nikeno.",
     "upload-misc-error": "Ğeletê bar kerdişî nizanyeno",
     "upload-misc-error-text": "wextê barkerdişî de yew xetayo mechul vırazîya.\nkonrol bıkeri şıma besteyi? Ya zi şıma karo raşt keni?\nEke problem dewam kerd [[Special:ListUsers/sysop|serkari]] de irtibat kewe.",
     "upload-too-many-redirects": "Eno URL de zaf redireksiyonî esto.",
-    "upload-unknown-size": "Ebat nizanyeno",
     "upload-http-error": "Yew ğeletê HTTPî biyo: $1",
     "upload-copy-upload-invalid-domain": "Na domain ra kopyayê barkerdışanê nêbenê.",
     "backend-fail-stream": "$1 nê vırazeyê",
     "img-auth-streaming": "\"$1\" stream keno.",
     "img-auth-public": "img_auth.php'nin fonksiyonê ney; wiki ra dosyaya xususiyan vetışo.\nno wiki bı umumi eyar biyo.\nqey pawıtışi, img_auth.php battal verdiyayo.",
     "img-auth-noread": "Heqqa karberanî çino ke \"$1\" biwendi",
-    "img-auth-bad-query-string": "URL'dı ratnayışo nêravêrde esto.",
     "http-invalid-url": "URL raşt niya: $1",
     "http-invalid-scheme": "URLan ke pê şablonê \"$1\"i rê destek cini ya.",
     "http-request-error": "Waştişê tu HTTP de xeta biya seba yew xetayê ke nizanyeno.",
     "filehist-dimensions": "Ebati",
     "filehist-filesize": "Ebatê dosyayî",
     "filehist-comment": "Vacayış",
-    "filehist-missing": "Dosya nieseno",
     "imagelinks": "Gurenayışê dosya",
     "linkstoimage": "Ena {{PLURAL:$1|pela|$1 pela}} gıreye ena dosya:",
     "linkstoimage-more": "$1 ra ziyed {{PLURAL:$1|pel|pel}} re gırey dano.\nlisteya ke ha ver a têna na {{PLURAL:$1|dosyaya ewwili|dosyaya $1 ewwili}} mocnena.\n[[Special:WhatLinksHere/$2|pêroyê liste]] mevcud o.",
     "emailuser-title-notarget": "E-postaya karberi",
     "emailpage": "karberi re e-posta bırışê",
     "emailpagetext": "Şıma şenê nê formê cêrêni nê {{GENDER:$1|karber}}i rê e-poste rıştış de bıgurenê.\n[[Special:Preferences|Tercihanê şımayê karberi]] de adresa e-posteya ke şıma daya, na adrese qısmê adresa e-postey de \"kami ra\" asena, no sebeb ra gırewtoğ şeno direkt cewab bıdero şıma.",
-    "usermailererror": "xizmetê e-postayi xeta da:",
     "defemailsubject": "\"$1\" ra e-postay {{SITENAME}} amê",
     "usermaildisabled": "E-mailê karberani kafiliyeya",
     "usermaildisabledtext": "Ti nieşkena ena wiki de karberanê binan rê e-mail bişave",
     "noemailtitle": "adresa e-postayi çina",
     "noemailtext": "no/na karber yew e-postayo meqbul nêdawa/o",
-    "nowikiemailtitle": "E-postayan re destur çino",
     "nowikiemailtext": "no/na karber/e, karberanê binani ra gırewtışê e-postayi tercih nêkerd.",
     "emailnotarget": "Qandê Gêreninamey karberiyo wuna çınyo yana xırabo.",
     "emailtarget": "Namey Karberi defiyê de.",
     "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",
     "watching": "Seyr ke...",
     "unwatching": "Seyr meke...",
     "watcherrortext": "Sazanê listeda seyri vurnayış de pox ta \"$1\" xırabey vıcyê .",
-    "enotif_mailer": "postaya xeberdayişi {{SITENAME}}",
     "enotif_reset": "Pela pêro ziyaret kerde deye mor ke",
     "enotif_impersonal_salutation": "{{SITENAME}} karber",
     "enotif_subject_deleted": "{{SITENAME}} de pera $1 {{gender:$2|$2}} esterıt.",
     "excontent": "Zerreko verén: '$1'",
     "excontentauthor": "Zerrey cı: '$1' no/na ('[[Special:Contributions/$2|$2]]'  teyna iştıraq kerdo)",
     "exbeforeblank": "behsê verê esteriyayişi: '$1'",
-    "exblank": "zerreyê peli vengo",
     "delete-confirm": "\"$1\" bestere",
     "delete-legend": "Bestere",
     "historywarning": "'''Teme:''' Pela ke şıma esterenê tede yew viyarte be teqriben $1 {{PLURAL:$1|versiyon esto|versiyoni estê}}:",
     "importunknownsource": "Çimeyê tip ê împortî nizanyano",
     "importcantopen": "Nieşkenî dosyayê împortî a bike",
     "importbadinterwiki": "Linkê înterwîkîyî nihebitiyeno",
-    "importnotext": "Veng o ya zi tede nuşte çini yo",
     "importsuccess": "Împort qediya!",
-    "importhistoryconflict": "verê revizyon ê ke pêverdiyaye yê tiya de mewcud o (no pel, belka cıwa ver kırışiyayo zerreyi)",
     "importnosources": "çımeyê kırıştışê zerredayişi nidiyo şınasnayişi u barbiyayişê verıni battal verdiyo.",
     "importnofile": "Yew zi dosyayê împortî bar nibiyo.",
     "importuploaderrorsize": "barbiyayişê kırıştışê zerredayişi nibı.\ngırdiyê dosyayi, gırdî yo ke musa'ade biyo ıney gırdıyî ra gırd o.",
index c2e25a7..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ś",
index 37bdff9..7954bf2 100644 (file)
     "disclaimers": "ཁས་མི་ལེན་པ།",
     "disclaimerpage": "Project: སྤྱིར་བཏང་ཁས་མི་ལེན་པ།",
     "edithelp": "ཞུན་དག་གྲོགས་རམ།",
-    "helppage": "Help:ནང་དོན།",
     "mainpage": "མ་ཤོག།",
     "mainpage-description": "མ་ཤོག།",
     "portal": "མི་སྡེའི་སྒོ་ར།",
index 1cd5053..511790c 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.",
     "accountcreatedtext": "È stê fât 'n'utèisa per [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|msg]]).",
     "createaccount-title": "Per fêr un inscrisiòun a {{SITENAME}}",
     "createaccount-text": "Quelchidûn l'à fât un inscrisiòun a  {{SITENAME}} ($4) a nòm ed $2 coleghê a cl'indirés ed pôsta eletrônica ché. La cêva 'd ingrès per l'utèint \"$2\" l'é  impustêda a \"$3\". \nÉ necesâri fêr un ingrès préma ch' es pôl e cambiêr subét la cêva 'd ingrès. \nSe l'inscrisiòun l'é stêda fâta per şbâli, es pōl scanşlêr sté mesâg.",
-    "usernamehasherror": "Al nòm utèint al pōl mìa avèir i carâter hash",
     "login-throttled": "În stê fât trôp tentatîv 'd ingrès in pôch tèimp. Spèta $1 e pó tōrna pruvêr.",
     "login-abort-generic": "An t'é mìa stê arcgnusû - Scanşlê",
     "loginlanguagelabel": "Léngva: $1",
     "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.",
     "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 fc87c0f..e044a54 100644 (file)
     "prefs-skin": "Οπτική οργάνωση (skin)",
     "skin-preview": "Προεπισκόπηση",
     "datedefault": "Χωρίς προτίμηση",
-    "prefs-beta": "Λειτουργίες της Beta",
     "prefs-datetime": "Ημερομηνία και ώρα",
     "prefs-labs": "Λειτουργίες των Labs",
     "prefs-user-pages": "Σελίδες του χρήστη",
     "nowatchlist": "Δεν υπάρχουν εγγραφές στη λίστα παρακολούθησης.",
     "watchlistanontext": "Παρακαλώ $1 για να δείτε ή να επεξεργαστείτε στοιχεία στη λίστα παρακολούθησής σας.",
     "watchnologin": "Δεν έχετε συνδεθεί.",
-    "watchnologintext": "Για να κάνετε αλλαγές στη λίστα παρακολούθησης πρέπει να [[Special:UserLogin|συνδεθείτε]].",
     "addwatch": "Προσθήκη στη λίστα παρακολούθησης",
     "addedwatchtext": "Η σελίδα «[[:$1]]» έχει προστεθεί στη [[Special:Watchlist|λίστα παρακολούθησής σας]].\nΜελλοντικές αλλαγές σε αυτή τη σελίδα και στη συσχετισμένη σελίδα συζήτησής της θα εμφανίζονται εδώ.",
     "removewatch": "Αφαίρεση από τη λίστα παρακολούθησης",
index a821207..646727b 100644 (file)
@@ -40,7 +40,6 @@
     "jumptosearch": "Sèirca",
     "currentevents": "Fât e prugèt ed tót",
     "currentevents-url": "Project:Prugèt_ed_tót",
-    "helppage": "Help:Introdusiòun",
     "portal": "Discóter e quistiunêr",
     "portal-url": "Project:Bar",
     "nstab-main": "Artécol",
index dc23318..18cabc5 100644 (file)
     "permalink": "Permanent link",
     "print": "Print",
     "view": "View",
+    "view-foreign": "View on $1",
     "edit": "Edit",
+    "edit-local": "Edit local description",
     "create": "Create",
+    "create-local": "Add local description",
     "editthispage": "Edit this page",
     "create-this-page": "Create this page",
     "delete": "Delete",
     "accountcreatedtext": "The user account for [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|talk]]) has been created.",
     "createaccount-title": "Account creation for {{SITENAME}}",
     "createaccount-text": "Someone created an account for your email 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": "Username cannot contain hash characters",
     "login-throttled": "You have made too many recent login attempts.\nPlease wait $1 before trying again.",
     "login-abort-generic": "Your login was unsuccessful - Aborted",
     "loginlanguagelabel": "Language: $1",
     "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",
     "upload-prohibited": "Prohibited file types: $1.",
     "uploadfooter": "-",
     "upload-default-description": "-",
-    "uploadlog": "upload log",
     "uploadlogpage": "Upload log",
     "uploadlogpagetext": "Below is a list of the most recent file uploads.\nSee the [[Special:NewFiles|gallery of new files]] for a more visual overview.",
     "filename": "Filename",
     "filereuploadsummary": "File changes:",
     "filestatus": "Copyright status:",
     "filesource": "Source:",
-    "uploadedfiles": "Uploaded files",
     "ignorewarning": "Ignore warning and save file anyway",
     "ignorewarnings": "Ignore any warnings",
     "minlength1": "Filenames must be at least one letter.",
     "overwroteimage": "uploaded a new version of \"[[$1]]\"",
     "uploaddisabled": "Uploads disabled.",
     "copyuploaddisabled": "Upload by URL disabled.",
-    "uploadfromurl-queued": "Your upload has been queued.",
     "uploaddisabledtext": "File uploads are disabled.",
     "php-uploaddisabledtext": "File uploads are disabled in PHP.\nPlease check the file_uploads setting.",
     "uploadscripted": "This file contains HTML or script code that may be erroneously interpreted by a web browser.",
     "upload-misc-error": "Unknown upload error",
     "upload-misc-error-text": "An unknown error occurred during the upload.\nPlease verify that the URL is valid and accessible and try again.\nIf the problem persists, contact an [[Special:ListUsers/sysop|administrator]].",
     "upload-too-many-redirects": "The URL contained too many redirects",
-    "upload-unknown-size": "Unknown size",
     "upload-http-error": "An HTTP error occurred: $1",
     "upload-copy-upload-invalid-domain": "Copy uploads are not available from this domain.",
     "backend-fail-stream": "Could not stream file \"$1\".",
     "img-auth-streaming": "Streaming \"$1\".",
     "img-auth-public": "The function of img_auth.php is to output files from a private wiki.\nThis wiki is configured as a public wiki.\nFor optimal security, img_auth.php is disabled.",
     "img-auth-noread": "User does not have access to read \"$1\".",
-    "img-auth-bad-query-string": "The URL has an invalid query string.",
     "http-invalid-url": "Invalid URL: $1",
     "http-invalid-scheme": "URLs with the \"$1\" scheme are not supported.",
     "http-request-error": "HTTP request failed due to unknown error.",
     "filehist-dimensions": "Dimensions",
     "filehist-filesize": "File size",
     "filehist-comment": "Comment",
-    "filehist-missing": "File missing",
     "imagelinks": "File usage",
     "linkstoimage": "The following {{PLURAL:$1|page links|$1 pages link}} to this file:",
     "linkstoimage-more": "More than $1 {{PLURAL:$1|page links|pages link}} to this file.\nThe following list shows the {{PLURAL:$1|first page link|first $1 page links}} to this file only.\nA [[Special:WhatLinksHere/$2|full list]] is available.",
     "listgrouprights-removegroup-self": "Remove {{PLURAL:$2|group|groups}} from own account: $1",
     "listgrouprights-addgroup-self-all": "Add all groups to own account",
     "listgrouprights-removegroup-self-all": "Remove all groups from own account",
+    "listgrouprights-namespaceprotection-header": "Namespace restrictions",
+    "listgrouprights-namespaceprotection-namespace": "Namespace",
+    "listgrouprights-namespaceprotection-restrictedto": "Right(s) allowing user to edit",
     "trackingcategories": "Tracking categories",
     "trackingcategories-summary": "This page lists tracking categories which are automatically populated by the MediaWiki software. Their names can be changed by altering the relevant system messages in the {{ns:8}} namespace.",
-    "trackingcategories-msg": "Tracking Category",
+    "trackingcategories-msg": "Tracking category",
     "trackingcategories-name": "Message name",
     "trackingcategories-desc": "Category inclusion criteria",
-    "noindex-category-desc": "The page has a <nowiki>__NOINDEX__</nowiki> magic word on it (and is in a namespace where that flag is allowed), and hence is not indexed by robots.",
-    "index-category-desc": "The page has a <nowiki>__INDEX__</nowiki> on it (and is in a namespace where that flag is allowed), and hence is indexed by robots where it normally wouldn't be.",
-    "post-expand-template-inclusion-category-desc": "After expanding all the templates, the page size is bigger than $wgMaxArticleSize, so some templates weren't expanded.",
-    "post-expand-template-argument-category-desc": "After expanding a template argument (something in triple braces, like {{{Foo}}}), the page is bigger than $wgMaxArticleSize.",
+    "noindex-category-desc": "The page is not indexed by robots because it has the magic word <code><nowiki>__NOINDEX__</nowiki></code> on it and is in a namespace where that flag is allowed.",
+    "index-category-desc": "The page has a <code><nowiki>__INDEX__</nowiki></code> on it (and is in a namespace where that flag is allowed), and hence is indexed by robots where it normally wouldn't be.",
+    "post-expand-template-inclusion-category-desc": "After expanding all the templates, the page size is bigger than <code>$wgMaxArticleSize</code>, so some templates weren't expanded.",
+    "post-expand-template-argument-category-desc": "After expanding a template argument (something in triple braces, like <code>{{{Foo}}}</code>), the page is bigger than <code>$wgMaxArticleSize</code>.",
     "expensive-parserfunction-category-desc": "Too many expensive parser functions (like <code>#ifexist</code>) included on a page. See [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
     "broken-file-category-desc": "Category added if the page contains a broken file link (a link to embed a file when the file does not exist).",
-    "hidden-category-category-desc": "This is a category with <nowiki>__HIDDENCAT__</nowiki> on it, which prevents it from showing up in the category links box on pages, by default.",
+    "hidden-category-category-desc": "This is a category with <code><nowiki>__HIDDENCAT__</nowiki></code> on it, which prevents it from showing up in the category links box on pages, by default.",
     "trackingcategories-nodesc": "No description available.",
     "trackingcategories-disabled": "Category is disabled",
     "mailnologin": "No send address",
     "emailuser-summary": "",
     "emailpage": "Email user",
     "emailpagetext": "You can use the form below to send an email message to this {{GENDER:$1|user}}.\nThe email address you entered in [[Special:Preferences|your user preferences]] will appear as the \"From\" address of the email, so the recipient will be able to reply directly to you.",
-    "usermailererror": "Mail object returned error:",
     "defemailsubject": "{{SITENAME}} email from user \"$1\"",
     "usermaildisabled": "User email disabled",
     "usermaildisabledtext": "You cannot send email to other users on this wiki",
     "noemailtitle": "No email address",
     "noemailtext": "This user has not specified a valid email address.",
-    "nowikiemailtitle": "No email allowed",
     "nowikiemailtext": "This user has chosen not to receive email from other users.",
     "emailnotarget": "Non-existent or invalid username for recipient.",
     "emailtarget": "Enter username of recipient",
     "watching": "Watching...",
     "unwatching": "Unwatching...",
     "watcherrortext": "An error occurred while changing your watchlist settings for \"$1\".",
-    "enotif_mailer": "{{SITENAME}} notification mailer",
     "enotif_reset": "Mark all pages visited",
     "enotif_impersonal_salutation": "{{SITENAME}} user",
     "enotif_subject_deleted": "{{SITENAME}} page $1 has been {{GENDER:$2|deleted}} by $2",
     "excontent": "content was: \"$1\"",
     "excontentauthor": "content was: \"$1\" (and the only contributor was \"[[Special:Contributions/$2|$2]]\")",
     "exbeforeblank": "content before blanking was: \"$1\"",
-    "exblank": "page was empty",
     "delete-confirm": "Delete \"$1\"",
     "delete-legend": "Delete",
     "historywarning": "<strong>Warning:</strong> The page you are about to delete has a history with approximately $1 {{PLURAL:$1|revision|revisions}}:",
     "importunknownsource": "Unknown import source type",
     "importcantopen": "Could not open import file",
     "importbadinterwiki": "Bad interwiki link",
-    "importnotext": "Empty or no text",
     "importsuccess": "Import finished!",
-    "importhistoryconflict": "Conflicting history revision exists (may have imported this page before)",
     "importnosources": "No transwiki import sources have been defined and direct history uploads are disabled.",
     "importnofile": "No import file was uploaded.",
     "importuploaderrorsize": "Upload of import file failed.\nThe file is bigger than the allowed upload size.",
index a0a7239..7cf96e1 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",
     "accountcreatedtext": "La uzanto-konto por [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|diskuto]])  estas kreita.",
     "createaccount-title": "Konto-kreado por {{SITENAME}}",
     "createaccount-text": "Iu kreis konton por via retadreso en {{SITENAME}} ($4) nomata \"$2\", kun pasvorto \"$3\". Vi ensalutu kaj ŝanĝu vian pasvorton nun.\n\nVi povas ignori ĉi tiun mesaĝon, se ĉi tiu konto estis kreita erare.",
-    "usernamehasherror": "Salutnomo ne povas enhavi signojn de kriptaj haketaĵoj",
     "login-throttled": "Vi ĵus tro ofte provis ensaluti.\nBonvolu ĝisatendi $1 antaŭ reprovi.",
     "login-abort-generic": "Via ensaluto malsukcesis - Ĉesigita",
     "loginlanguagelabel": "Lingvo: $1",
     "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",
     "upload-permitted": "Permesitaj dosiertipoj: $1.",
     "upload-preferred": "Preferitaj dosiertipoj: $1.",
     "upload-prohibited": "Malpermesitaj dosiero-tipoj: $1.",
-    "uploadlog": "protokolo de alŝutoj",
     "uploadlogpage": "Protokolo de alŝutoj",
     "uploadlogpagetext": "Jen la plej laste alŝutitaj dosieroj.\nĈiuj tempoj montriĝas laŭ la horzono UTC.",
     "filename": "Dosiernomo",
     "filereuploadsummary": "Dosieraj ŝanĝoj:",
     "filestatus": "Aŭtorrajta statuso:",
     "filesource": "Fonto:",
-    "uploadedfiles": "Alŝutitaj dosieroj",
     "ignorewarning": "Ignori averton kaj konservi dosieron ĉiukaze",
     "ignorewarnings": "Ignori ĉiajn avertojn",
     "minlength1": "Nomoj de dosieroj nepre havas almenaŭ unu literon.",
     "overwroteimage": "alŝutis novan version de \"[[$1]]\"",
     "uploaddisabled": "Alŝutado estas malŝaltita",
     "copyuploaddisabled": "Alŝuto de URL malfunkciigita.",
-    "uploadfromurl-queued": "Via alŝuto estis vicatendigata.",
     "uploaddisabledtext": "Alŝutado de dosieroj estas malebligita.",
     "php-uploaddisabledtext": "Dosiera alŝutado estas malŝalta en PHP. Bonvolu kontroli la preferon file_uploads.",
     "uploadscripted": "HTML-aĵo aŭ skriptokodaĵo troviĝas en tiu ĉi tiu dosiero, kiun TTT-foliumilo eble interpretus erare.",
     "upload-misc-error": "Nekonata eraro pri alŝutado.",
     "upload-misc-error-text": "Nekonata eraro okazis dum la alŝuto.\nBonvolu kontroli ke la URL-o estas valida kaj atingebla tiam reprovu.\nSe la problemo kontinuas, kontaku [[Special:ListUsers/sysop|administranton]].",
     "upload-too-many-redirects": "La URL-o enhavis tro multajn alidirektilojn",
-    "upload-unknown-size": "Nekonata grandeco",
     "upload-http-error": "HTTP-eraro okazis: $1",
     "upload-copy-upload-invalid-domain": "Kopio-alŝutoj ne disponiĝas el ĉi tiu domajno.",
     "backend-fail-stream": "Ne povis fluigi dosieron $1.",
     "img-auth-streaming": "Elsendfluante \"$1\".",
     "img-auth-public": "La funkcio de img_auth.php estas eligi dosierojn de privata vikio.\nĈi tiu vikio estas konfigurita kiel publika vikio.\nPor optimuma sekureco, img_auth.php estas malŝalta.",
     "img-auth-noread": "Uzanto ne havas atingon por legi \"$1\".",
-    "img-auth-bad-query-string": "La URL-o havas malvalidan mendan signoĉenon.",
     "http-invalid-url": "Malvalida URL-o: $1",
     "http-invalid-scheme": "URL-oj kun la skemo \"$1\" ne estas subtenata.",
     "http-request-error": "HTTP-peto malsukcesis pro nekonata eraro.",
     "filehist-dimensions": "Dimensioj",
     "filehist-filesize": "Grando de dosiero",
     "filehist-comment": "Komento",
-    "filehist-missing": "Dosiero mankas",
     "imagelinks": "Dosiera uzado",
     "linkstoimage": "La {{PLURAL:$1|jena paĝo|jenaj paĝoj}} ligas al ĉi tiu dosiero:",
     "linkstoimage-more": "Pli ol $1 {{PLURAL:$1|paĝo|paĝoj}} ligas ĉi tiun dosieron.\nLa jena listo montras la {{PLURAL:$1|unua paĝligilo|unuaj $1 paĝligiloj}} al nur ĉi tiu dosiero.\n[[Special:WhatLinksHere/$2|Plena listo]] estas atingebla.",
     "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",
     "emailuser-title-notarget": "Retpoŝti uzanton",
     "emailpage": "Retpoŝti uzanton",
     "emailpagetext": "Vi povas uzi la jenan paĝon por sendi retpoŝtan mesaĝon al ĉi tiu {{GENDER:$1|uzanto|uzantino}}.\nLa retadreso kiun vi enigis en [[Special:Preferences|viaj preferoj]] aperos kiel la \"De\" adreso de la retpoŝto, do la ricevonto eblos respondi rekte al vi.",
-    "usermailererror": "Resendita retmesaĝa erarsubjekto:",
     "defemailsubject": "{{SITENAME}} retmesaĝo de uzanto \"$1\"",
     "usermaildisabled": "Retpoŝto de uzantoj estas malŝaltita",
     "usermaildisabledtext": "Vi ne povas sendi retpoŝton al aliaj uzantoj en ĉi tiu vikio",
     "noemailtitle": "Neniu retpoŝtadreso",
     "noemailtext": "Ĉi tiu uzanto ne donis validan retadreson.",
-    "nowikiemailtitle": "Retpoŝto ne permesita",
     "nowikiemailtext": "Ĉi tiu uzanto elektis ne ricevi retpoŝton de aliaj uzantoj.",
     "emailnotarget": "Neekzistanta aŭ malvalida salutnomo por ricevanto.",
     "emailtarget": "Enigi salutnomon de ricevonto",
     "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",
     "watching": "Aldonante al la atentaro...",
     "unwatching": "Malatentante...",
     "watcherrortext": "Eraro okazis ŝanĝinte vian agordojn de atentaro por \"$1\".",
-    "enotif_mailer": "Averta retmesaĝo de {{SITENAME}}",
     "enotif_reset": "Marki ĉiujn paĝojn vizititaj",
     "enotif_impersonal_salutation": "Uzanto de {{SITENAME}}",
     "enotif_subject_deleted": "La paĝon $1 de {{SITENAME}} forigis {{gender:$2|$2}}",
     "excontent": "enhavis: '$1'",
     "excontentauthor": "la enteno estis : '$1' (kaj la sola kontribuinto estis '$2')",
     "exbeforeblank": "antaŭ malplenigo enhavis: '$1'",
-    "exblank": "estis malplena",
     "delete-confirm": "Forigi \"$1\"",
     "delete-legend": "Forigi",
     "historywarning": "'''Averto:''' La forigota paĝo havas historion kun pli-malpli $1 {{PLURAL:$1|revizio|revizioj}}:",
     "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\"",
     "importunknownsource": "Nekonata fonta speco de alŝuto",
     "importcantopen": "Ne povas malfermi import-dosieron",
     "importbadinterwiki": "Malbona intervikia ligilo",
-    "importnotext": "Malplena aŭ senteksta",
     "importsuccess": "La importo sukcesis!",
-    "importhistoryconflict": "Malkongrua historia versio ekzistas (eble la paĝo importiĝis antaŭe)",
     "importnosources": "Neniu transvikia importfonto estis difinita kaj rekta historio de alŝutoj estas malaktivigita.",
     "importnofile": "Neniu import-dosiero estis alŝutita.",
     "importuploaderrorsize": "Alŝuto de import-dosiero malsukcesis. La dosiero estas pli granda ol la permesita alŝut-grando.",
     "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 564d002..2715793 100644 (file)
             "Wilfredor",
             "XalD",
             "XanaG",
-            "לערי ריינהארט"
+            "לערי ריינהארט",
+            "Chocolate con galleta"
         ]
     },
     "tog-underline": "Subrayar los enlaces:",
     "tog-showhiddencats": "Mostrar las categorías escondidas",
     "tog-norollbackdiff": "Omitir la diferencia después de revertir",
     "tog-useeditwarning": "Advertirme cuando abandone una página editada con cambios sin grabar",
-    "tog-prefershttps": "Utiliza una conexión segura siempre que haya iniciado una sesión",
+    "tog-prefershttps": "Utilizar una conexión segura siempre que haya iniciado una sesión",
     "underline-always": "Siempre",
     "underline-never": "Nunca",
     "underline-default": "Aspecto (skin) o valor predeterminado del navegador",
     "permalink": "Enlace permanente",
     "print": "Imprimir",
     "view": "Ver",
+    "view-foreign": "Ver en $1",
     "edit": "Editar",
+    "edit-local": "Editar descripción local",
     "create": "Crear",
+    "create-local": "Añadir descripción local",
     "editthispage": "Editar esta página",
     "create-this-page": "Crear esta página",
     "delete": "Borrar",
     "accountcreatedtext": "La cuenta de usuario de [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|talk]]) ha sido creada.",
     "createaccount-title": "Creación de cuenta para {{SITENAME}}",
     "createaccount-text": "Alguien creó en {{SITENAME}} ($4) una cuenta asociada a este correo electrónico con el nombre «$2».\nLa contraseña asignada automáticamente es «$3». Por favor entra ahora y cambia tu contraseña.\n\nPuedes ignorar este mensaje si esta cuenta fue creada por error.",
-    "usernamehasherror": "El nombre de usuario no puede contener símbolos de almohadilla/numeral",
     "login-throttled": "Has intentado demasiadas veces iniciar sesión. Por favor espera $1 antes de intentarlo nuevamente.",
     "login-abort-generic": "Tu inicio de sesión no fue exitoso - Cancelado",
     "loginlanguagelabel": "Idioma: $1",
     "newpassword": "Contraseña nueva:",
     "retypenew": "Confirmar la contraseña nueva:",
     "resetpass_submit": "Establecer contraseña e iniciar sesión",
-    "changepassword-success": "La contraseña ha sido cambiada con éxito.",
+    "changepassword-success": "La contraseña se modificó correctamente.",
     "changepassword-throttled": "Has intentado acceder demasiadas veces.\nEspera $1 antes de intentarlo de nuevo.",
     "resetpass_forbidden": "No se pueden cambiar las contraseñas",
     "resetpass-no-info": "Debes iniciar sesión para acceder directamente a esta página.",
     "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",
     "upload-permitted": "Tipos de archivo permitidos: $1.",
     "upload-preferred": "Tipos de archivo preferidos: $1.",
     "upload-prohibited": "Tipos de archivo prohibidos: $1.",
-    "uploadlog": "registro de subidas",
     "uploadlogpage": "Subidas de archivos",
     "uploadlogpagetext": "Abajo hay una lista de los últimos archivos subidos.\nMira la [[Special:NewFiles|galería de archivos nuevos]] para una descripción visual",
     "filename": "Nombre del archivo",
     "filereuploadsummary": "Cambios de archivo:",
     "filestatus": "Estado de copyright:",
     "filesource": "Fuente:",
-    "uploadedfiles": "Archivos subidos",
     "ignorewarning": "Ignorar aviso y guardar de todos modos",
     "ignorewarnings": "Ignorar cualquier aviso",
     "minlength1": "Los nombres de archivo deben tener al menos una letra.",
     "overwroteimage": "subió una nueva versión de «[[$1]]»",
     "uploaddisabled": "Subida de archivos deshabilitada",
     "copyuploaddisabled": "Carga por URL deshabilitada.",
-    "uploadfromurl-queued": "Tu carga ha sido enviada a la cola.",
     "uploaddisabledtext": "No es posible subir archivos.",
     "php-uploaddisabledtext": "La subida de archivos está deshabilitada en PHP. Por favor compruebe <code>file_uploads</code> en php.ini.",
     "uploadscripted": "Este archivo contiene script o código HTML que puede ser interpretado erróneamente por un navegador web.",
     "upload-misc-error": "Error desconocido en la subida",
     "upload-misc-error-text": "Ha ocurrido un error durante la subida. Por favor verifica que la URL es válida y accesible e inténtalo de nuevo. Si el problema persiste, contacta con un [[Special:ListUsers/sysop|administrador]].",
     "upload-too-many-redirects": "La URL contenía demasiadas redirecciones",
-    "upload-unknown-size": "Tamaño desconocido",
     "upload-http-error": "Ha ocurrido un error HTTP: $1",
     "upload-copy-upload-invalid-domain": "No se pueden realizar cargas remotas desde este dominio.",
     "backend-fail-stream": "No se pudo transmitir el archivo «$1».",
     "img-auth-streaming": "Streaming «$1».",
     "img-auth-public": "La función de img_auth.php es mostrar archivos desde una wiki privada.\nEsta wiki está configurada como pública.\nPara óptima seguridad, img_auth.php está desactivado.",
     "img-auth-noread": "El usuario no tiene acceso para leer «$1».",
-    "img-auth-bad-query-string": "La dirección URL tiene una cadena de consulta no válida.",
     "http-invalid-url": "URL inválida: $1",
     "http-invalid-scheme": "Las URLs con el esquema «$1» no son compatibles.",
     "http-request-error": "La solicitud HTTP falló debido a un error desconocido.",
     "filehist-dimensions": "Dimensiones",
     "filehist-filesize": "Tamaño",
     "filehist-comment": "Comentario",
-    "filehist-missing": "No se encuentra el archivo",
     "imagelinks": "Usos del archivo",
     "linkstoimage": "{{PLURAL:$1|La siguiente página enlaza|Las siguientes páginas enlazan}} a este archivo:",
     "linkstoimage-more": "Hay más de {{PLURAL:$1|una página que enlaza|$1 páginas que enlazan}} con este archivo.\n\nLa lista siguiente sólo muestra {{PLURAL:$1|la primera página que enlaza|las primeras $1 páginas que enlazan}} con este archivo.\nTambién puedes consultar la [[Special:WhatLinksHere/$2|lista completa]].",
     "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 <code><nowiki>__NOINDEX__</nowiki></code> (y está en un espacio de nombres donde la función está activada); y por ello los robots no la indizan.",
+    "post-expand-template-inclusion-category-desc": "Después de expandir todas las plantillas, el tamaño de la página es más grande que <code>$wgMaxArticleSize</code>, así que algunas plantillas no se expandieron.",
+    "post-expand-template-argument-category-desc": "Después de expandir un argumento de plantilla (algunos en tres llaves, como <code>{{{Foo}}})</code>, la página es más grande que <code>$wgMaxArticleSize</code>.",
+    "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}}",
     "emailuser-title-notarget": "Enviar un correo electrónico al usuario",
     "emailpage": "Enviar un correo electrónico a un usuario",
     "emailpagetext": "Puedes usar el formulario de abajo para enviar un correo electrónico a {{GENDER:$1|este usuario|esta usuaria}}.\nLa dirección de correo electrónico que indicaste en [[Special:Preferences|tus preferencias de usuario]] aparecerá en el campo \"Remitente\" o \"De\" para que el destinatario pueda responderte.",
-    "usermailererror": "El sistema de correo devolvió un error:",
     "defemailsubject": "Correo electrónico enviado por el usuario «$1» desde {{SITENAME}}",
     "usermaildisabled": "Correo electrónico del usuario deshabilitado",
     "usermaildisabledtext": "No puedes enviar correos electrónicos a otros usuarios en esta wiki",
     "noemailtitle": "No hay dirección de correo electrónico",
     "noemailtext": "Este usuario no ha especificado una dirección de correo electrónico válida.",
-    "nowikiemailtitle": "correos electrónicos no permitidos",
     "nowikiemailtext": "Este usuario ha elegido no recibir correos electrónicos de otros usuarios.",
     "emailnotarget": "Nombre de usuario no existente o no válido para el destinatario.",
     "emailtarget": "Introduce el nombre de usuario del destinatario",
     "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",
     "watching": "Vigilando...",
     "unwatching": "Eliminando de la lista de seguimiento...",
     "watcherrortext": "Ocurrió un error al cambiar la configuración de tu lista de seguimiento para «$1».",
-    "enotif_mailer": "Notificación por correo de {{SITENAME}}",
     "enotif_reset": "Marcar todas las páginas como visitadas",
     "enotif_impersonal_salutation": "usuario de {{SITENAME}}",
     "enotif_subject_deleted": "$2 ha borrado la página $1 de {{SITENAME}}",
     "excontent": "el contenido era: «$1»",
     "excontentauthor": "el contenido era: «$1» (y el único autor fue «[[Special:Contributions/$2|$2]]»)",
     "exbeforeblank": "El contenido antes de blanquear era: «$1»",
-    "exblank": "la página estaba vacía",
     "delete-confirm": "Borrar «$1»",
     "delete-legend": "Borrar",
     "historywarning": "'''Aviso:''' La página que estás a punto de borrar tiene un historial de aproximadamente $1 {{PLURAL:$1|revisión|revisiones}}:",
     "importunknownsource": "Tipo de fuente de importación desconocida",
     "importcantopen": "No se pudo importar el archivo",
     "importbadinterwiki": "Enlace interwiki anómalo",
-    "importnotext": "Vacío o sin texto",
     "importsuccess": "¡La importación se ha realizado con éxito!",
-    "importhistoryconflict": "Existen revisiones en conflicto en el historial (puede que se haya importado esta página antes)",
     "importnosources": "No hay fuentes de importación transwiki y no está permitido subir directamente el historial.",
     "importnofile": "No se subieron archivos de importación.",
     "importuploaderrorsize": "Falló la carga del archivo de importaciones.\nSu tamaño es superior al máximo permitido.",
     "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 13cc1b4..58b269b 100644 (file)
     "permalink": "Püsilink",
     "print": "Prindi",
     "view": "Vaata",
+    "view-foreign": "Vaata asukohas $1",
     "edit": "Muuda",
+    "edit-local": "Redigeeri kohalikku kirjeldust",
     "create": "Loo",
+    "create-local": "Lisa kohalik kirjeldus",
     "editthispage": "Redigeeri seda lehekülge",
     "create-this-page": "Loo see lehekülg",
     "delete": "Kustuta",
     "accountcreatedtext": "Kasutaja [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|talk]]) konto on loodud.",
     "createaccount-title": "{{GRAMMAR:illative|{{SITENAME}}}} konto loomine",
     "createaccount-text": "Keegi on loonud {{GRAMMAR:illative|{{SITENAME}}}} ($4) sinu e-posti aadressile vastava kasutajatunnuse \"$2\". Parooliks seati \"$3\". Logi sisse ja muuda oma parool.\n\nKui kasutajakonto loomine on eksitus, võid käesolevat sõnumit lihtsalt eirata.",
-    "usernamehasherror": "Kasutajanimi ei või sisaldada trellimärke (\"#\").",
     "login-throttled": "Oled lühikese aja jooksul proovinud liiga palju kordi sisse logida.\nPalun oota $1, enne kui uuesti proovid.",
     "login-abort-generic": "Sisselogimine ebaõnnestus – Katkestatud",
     "loginlanguagelabel": "Keel: $1",
     "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",
     "upload-permitted": "Lubatud failitüübid: $1.",
     "upload-preferred": "Eelistatud failitüübid: $1.",
     "upload-prohibited": "Keelatud failitüübid: $1.",
-    "uploadlog": "üleslaadimislogi",
     "uploadlogpage": "Üleslaadimislogi",
     "uploadlogpagetext": "Allpool on loend viimastest failide üleslaadimistest. Visuaalsema esituse nägemiseks vaata [[Special:NewFiles|uute failide galeriid]].",
     "filename": "Faili nimi",
     "filereuploadsummary": "Faili muudatused:",
     "filestatus": "Autoriõiguse staatus:",
     "filesource": "Allikas:",
-    "uploadedfiles": "Üleslaaditud failid",
     "ignorewarning": "Ignoreeri hoiatust ja salvesta fail hoiatusest hoolimata",
     "ignorewarnings": "Ignoreeri hoiatusi",
     "minlength1": "Faili nimes peab olema vähemalt üks kirjamärk.",
     "overwroteimage": "laadis üles faili \"[[$1]]\" uue versiooni",
     "uploaddisabled": "Üleslaadimine hetkel keelatud",
     "copyuploaddisabled": "Internetiaadressilt üleslaadimine on keelatud.",
-    "uploadfromurl-queued": "Üleslaadimine on järjekorras.",
     "uploaddisabledtext": "Faili üleslaadimine on keelatud.",
     "php-uploaddisabledtext": "Failide üleslaadmine on PHP seadetes keelatud.\nPalun vaata <code>file_uploads</code> sätet.",
     "uploadscripted": "See fail sisaldab HTML- või skriptikoodi, mida veebilehitseja võib valesti kuvada.",
     "upload-misc-error": "Tundmatu viga üleslaadimisel",
     "upload-misc-error-text": "Üleslaadimisel ilmnes tundmatu tõrge.\nPalun veendu, et internetiaadress on õige ja ligipääsetav ning proovi uuesti.\nKui probleem ei kao, võta ühendust [[Special:ListUsers/sysop|administraatoriga]].",
     "upload-too-many-redirects": "URL sisaldas liiga palju ümbersuunamisi",
-    "upload-unknown-size": "Tundmatu suurus",
     "upload-http-error": "HTTP-viga: $1",
     "upload-copy-upload-invalid-domain": "Sellest domeenist pole kopeerimise teel üleslaadimine võimalik.",
     "backend-fail-stream": "Faili $1 ei saanud edastada.",
     "img-auth-streaming": "Faili \"$1\" voogedastus.",
     "img-auth-public": "img_auth.php on ette nähtud failide väljastamiseks privaatses vikis.\nSee viki on seadistatud kui avalik viki.\nTurvakaalutlustel on img_auth.php kasutus keelatud.",
     "img-auth-noread": "Faili \"$1\" lugemiseks vajalik juurdepääs puudub.",
-    "img-auth-bad-query-string": "URL-is on vigane päringusõne.",
     "http-invalid-url": "Vigane internetiaadress: $1",
     "http-invalid-scheme": "Aadressid, mis algavad eesliitega \"$1\", ei ole toetatud.",
     "http-request-error": "HTTP-päring nurjus tundmatu tõrke tõttu.",
     "filehist-dimensions": "Mõõtmed",
     "filehist-filesize": "Faili suurus",
     "filehist-comment": "Kommentaar",
-    "filehist-missing": "Fail puudub",
     "imagelinks": "Failikasutus",
     "linkstoimage": "Sellele pildile {{PLURAL:$1|viitab järgmine lehekülg|viitavad järgmised leheküljed}}:",
     "linkstoimage-more": "Sellele failile viitab enam kui {{PLURAL:$1|üks lehekülg|$1 lehekülge}}.\nJärgmises loendis on näidatud ainult {{PLURAL:$1|esimene viitav lehekülg|esimesed $1 viitavat lehekülge}}.\n[[Special:WhatLinksHere/$2|Kogu loetelu]] on saadaval.",
     "listgrouprights-removegroup-self": "Eemaldada enda konto {{PLURAL:$2|rühmast|rühmadest}}: $1",
     "listgrouprights-addgroup-self-all": "Oma konto kõigisse rühmadesse lisada",
     "listgrouprights-removegroup-self-all": "Eemaldada ennast kõigist rühmadest",
+    "trackingcategories": "Süsteemikategooriad",
+    "trackingcategories-summary": "Siin leheküljel on loetletud süsteemikategooriad, millesse MediaWiki tarkvara ise lehekülgi arvab. Nende kategooriate nimesid saab muuta, kui vahetada {{ns:8}}-nimeruumis vastavaid süsteemisõnumeid.",
+    "trackingcategories-msg": "Süsteemikategooria",
+    "trackingcategories-name": "Sõnumi nimi",
+    "trackingcategories-desc": "Kategooriasse arvamise kriteeriumid",
+    "noindex-category-desc": "Robotid ei indekseeri lehekülge, sest sellel on võlusõna <code><nowiki>__NOINDEX__</nowiki></code> ja lehekülg on nimeruumis, kus see silt on lubatud.",
+    "index-category-desc": "Leheküljel on <code><nowiki>__INDEX__</nowiki></code> ja lehekülg on nimeruumis, kus see silt on lubatud ning seetõttu indekseerivad robotid lehekülge seal, kus nad muidu seda ei teeks.",
+    "post-expand-template-inclusion-category-desc": "Kõigi mallide hõrendamise järel on lehekülg suurem kui <code>$wgMaxArticleSize</code>, mistõttu jäid mõned mallid hõrendamata.",
+    "post-expand-template-argument-category-desc": "Malli argumendi (midagi kolmekordsete looksulgude vahel, näiteks <code>{{{Foo}}})</code> hõrendamise järel on lehekülg suurem kui <code>$wgMaxArticleSize</code>.",
+    "expensive-parserfunction-category-desc": "Leheküljel on liiga palju kulukaid parserifunktsioone nagu <code>#ifexist</code>. Vaata [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit dokumentatsiooni].",
+    "broken-file-category-desc": "Kategooria lisatakse, kui leheküljel on katkine pildilink, millega manustatakse fail, mida pole olemas.",
+    "hidden-category-category-desc": "Selle kategooria leheküljel on <code><nowiki>__HIDDENCAT__</nowiki></code>, mis vaikimisi ei lase näidata seda kategooriat lehekülgedel kategoorialinkide kastis.",
+    "trackingcategories-nodesc": "Kirjeldus puudub.",
+    "trackingcategories-disabled": "Kategooria on keelatud.",
     "mailnologin": "Saatja aadress puudub",
     "mailnologintext": "Pead olema [[Special:UserLogin|sisse logitud]] ja sul peab [[Special:Preferences|eelistustes]] olema kehtiv e-posti aadress, et saata teistele kasutajatele e-kirju.",
     "emailuser": "Saada sellele kasutajale e-kiri",
     "emailuser-title-notarget": "Kasutajale e-kirja saatmine",
     "emailpage": "Saada kasutajale e-kiri",
     "emailpagetext": "Alloleva vormi kaudu saad sellele {{GENDER:$1|kasutajale}} e-kirja saata. Et kasutaja saaks vastata, täidetakse kirja saatja väli e-posti aadressiga, mille oled sisestanud [[Special:Preferences|oma eelistuste leheküljel]].",
-    "usermailererror": "Saatmise viga:",
     "defemailsubject": "E-kiri {{GRAMMAR:genitive|{{SITENAME}}}} kasutajalt $1",
     "usermaildisabled": "Kasutajatele e-kirjade saatmine keelatud",
     "usermaildisabledtext": "Selles vikis ei saa teistele kasutajatele e-kirju saata.",
     "noemailtitle": "E-posti aadressi pole",
     "noemailtext": "See kasutaja pole määranud kehtivat e-posti aadressi.",
-    "nowikiemailtitle": "E-kirja saatmine ei ole lubatud",
     "nowikiemailtext": "See kasutaja ei soovi e-posti teistelt kasutajatelt.",
     "emailnotarget": "Saaja kasutajanimi on olematu või vigane.",
     "emailtarget": "Saaja kasutajanime sisestamine",
     "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",
     "watching": "Jälgimine...",
     "unwatching": "Jälgimise lõpetamine...",
     "watcherrortext": "Lehekülje \"$1\" jaoks jälgimisloendi sätete muutmisel ilmnes tõrge.",
-    "enotif_mailer": "{{GRAMMAR:genitive|{{SITENAME}}}} lehekülje muutmise teavitaja",
     "enotif_reset": "Märgi kõik lehed loetuks",
     "enotif_impersonal_salutation": "{{GRAMMAR:genitive|{{SITENAME}}}} kasutaja",
     "enotif_subject_deleted": "{{GENDER:$2|$2}} kustutas {{GRAMMAR:genitive|{{SITENAME}}}} lehekülje $1",
     "excontent": "sisu oli: '$1'",
     "excontentauthor": "sisu oli: '$1' (ja ainuke kirjutaja oli '[[Special:Contributions/$2|$2]]')",
     "exbeforeblank": "sisu enne lehekülje tühjendamist: '$1'",
-    "exblank": "lehekülg oli tühi",
     "delete-confirm": "Lehekülje \"$1\" kustutamine",
     "delete-legend": "Kustutamine",
     "historywarning": "'''Hoiatus:''' Kustutataval leheküljel on ligikaudu {{PLURAL:$1|ühe redaktsiooniga|$1 redaktsiooniga}} ajalugu:",
     "importunknownsource": "Tundmatut tüüpi impordiallikas",
     "importcantopen": "Ei saa imporditavat faili avada",
     "importbadinterwiki": "Vigane vikidevaheline link",
-    "importnotext": "Tühi või ilma tekstita",
     "importsuccess": "Importimine edukalt lõpetatud!",
-    "importhistoryconflict": "Konfliktne muudatuste ajalugu (võimalik, et seda lehekülge juba varem imporditud)",
     "importnosources": "Ühtegi vikidevahelist impordiallikat pole määratletud ja otsene ajaloo üleslaadimine on keelatud.",
     "importnofile": "Ühtegi imporditavat faili ei laaditud üles.",
     "importuploaderrorsize": "Üleslaaditava faili import ebaõnnestus.\nFail on lubatust suurem.",
index 62e6075..5b43754 100644 (file)
     "accountcreatedtext": "[[{{ns:User}}:$1|$1]] lankidearentzat ([[{{ns:User talk}}:$1|eztabaida]]) kontua sortu da.",
     "createaccount-title": "{{SITENAME}}-rako kontua sortu",
     "createaccount-text": "Norbaitek zure e-postarekin kontu bat sortu du {{SITENAME}}(e)n ($4) \"$2\" izenarekin eta \"$3\" pasahitzarekin.\nOrain bertan sar zaitezke eta zure pasahitza aldatu.\n\nKontu honen sorrera akats bat dela uste baduzu mezu honi ez diozu zertan jaramonik egin.",
-    "usernamehasherror": "Erabiltzaile-izenak ezin du kuxin-karaktererik eduki",
     "login-throttled": "Saioa hasteko saiakera gehiegi egin berri dituzu.\nBerriro saiatu aurretik $1 itxoin, mesedez.",
     "login-abort-generic": "Zure sarrera ez da arrakastatsua izan - Abortatua",
     "loginlanguagelabel": "Hizkuntza: $1",
     "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",
     "upload-permitted": "Baimendutako fitxategi motak: $1.",
     "upload-preferred": "Fitxategi mota hobetsiak: $1.",
     "upload-prohibited": "Debekatutako fitxategi motak: $1.",
-    "uploadlog": "igoera erregistroa",
     "uploadlogpage": "Igoera erregistroa",
     "uploadlogpagetext": "Jarraian, igotako azken fitxategien zerrenda ageri da.\nIkus ezazu [[Special:NewFiles|fitxategi berrien galeria]], irudizkoagoa den ikuspegi orokor bat izateko.",
     "filename": "Fitxategi izena",
     "filereuploadsummary": "Fitxategi aldaketak:",
     "filestatus": "Copyright egoera:",
     "filesource": "Jatorria:",
-    "uploadedfiles": "Igotako fitxategiak",
     "ignorewarning": "Oharra ezikusi eta fitxategia gorde.",
     "ignorewarnings": "Edozein ohar ezikusi.",
     "minlength1": "Fitxategi izenek letra bat izan behar dute gutxienez.",
     "overwroteimage": "\"[[$1]]\"ren bertsio berri bat igo",
     "uploaddisabled": "Igoerak ezgaituta daude",
     "copyuploaddisabled": "URL bidezko igoera desaktibatuta.",
-    "uploadfromurl-queued": "Zure igoera ilaran jarri da.",
     "uploaddisabledtext": "Fitxategiak igotzea ezgaituta dago.",
     "php-uploaddisabledtext": "Fitxategi igoerak PHP-n ezinduta daude. Ikusi fitxategi_igoerak mesedez.",
     "uploadscripted": "Fitxategi honek web zerbitzariak modu ezegokian interpretatu lezakeen HTML edo script kodea dauka.",
     "upload-misc-error": "Errore ezezaguna igotzerakoan",
     "upload-misc-error-text": "Errore ezezagun bat gertatu da fitxategia igotzen ari zenean. Mesedez, egiaztatu URLa baliozkoa eta eskuragarria dela eta berriz saiatu. Arazoak jarraitzen badu, jar zaitez [[Special:ListUsers/sysop|administratzailearekin]] harremanetan.",
     "upload-too-many-redirects": "URLak birbideratze gehiegi zituen",
-    "upload-unknown-size": "Tamaina ezezaguna",
     "upload-http-error": "HTTP errorea gertatu da: $1",
     "upload-copy-upload-invalid-domain": "Domeinu honetan ezin dira igoerak kopiatu.",
     "backend-fail-stream": "Ezin izan da \"$1\" fitxategiaren stream egin.",
     "img-auth-isdir": "\"$1\" direktorio batera iristen saiatzen ari zara.\nFitxategien sarbidea baino ez da onartzen.",
     "img-auth-streaming": "\"$1\" sekuentziatzen.",
     "img-auth-noread": "Erabiltzaileak ez du \"$1\" irakurtzeko sarbiderik.",
-    "img-auth-bad-query-string": "URLan query esaldi baliogabea dago.",
     "http-invalid-url": "URL baliogabea: $1",
     "http-invalid-scheme": "\"$1\" eskema duten URLak ez dira baliagarriak.",
     "http-request-error": "HTTP eskariak akatsa izan du errore ezezagun bat dela eta.",
     "filehist-dimensions": "Neurriak",
     "filehist-filesize": "Tamaina",
     "filehist-comment": "Iruzkina",
-    "filehist-missing": "Fitxategia falta da",
     "imagelinks": "Fitxategiaren erabilera",
     "linkstoimage": "Hurrengo {{PLURAL:$1|orrialdeak du|$1 orrialdeek dute}} fitxategi honetarako lotura:",
     "linkstoimage-more": "$1 {{PLURAL:$1|orri lotura|orri lotura}} baino gehiago daude fitxategira.\nOndorengo zerrendak fitxategira dauden {{PLURAL:$1|lehen lotura|lehen $1 loturak}} erakusten ditu bakarrik.\n[[Special:WhatLinksHere/$2|Zerrenda osoa]] ere eskuragarri dago.",
     "emailuser-title-notarget": "Erabiltzaileari e-maila bidali",
     "emailpage": "Erabiltzaileari e-posta bidali",
     "emailpagetext": "{{GENDER:$1|Erabiltzaile}} honek baliozko e-posta helbide bat ezarri badu bere hobespenetan, beheko formularioa erabiliz mezu bat bidal dakioke.\n[[Special:Preferences|Hobespenetan]] daukazun e-posta helbidea azalduko da mezuaren bidaltzaile bezala eta beraz erantzun ahal izango dizu.",
-    "usermailererror": "Mail objektuak errore hau itzuli du:",
     "defemailsubject": "{{SITENAME}} e-posta \"$1\" lankideak",
     "usermaildisabled": "Erabiltzailearen e-maila desaktibatuta",
     "usermaildisabledtext": "Wiki honetan ezin diezu beste erabiltzaileei posta elektronikorik bidali",
     "noemailtitle": "Posta helbiderik ez",
     "noemailtext": "Erabiltzaile honek ez du baliozko e-posta helbiderik zehaztu.",
-    "nowikiemailtitle": "Ezin da e-postarik bidali",
     "nowikiemailtext": "Erabiltzaile honek beste erabiltzaileengandik e-postak ez jasotzea hautatu du.",
     "emailnotarget": "Jasotzailearentzat lankide izen ez-egokia edo ezezaguna.",
     "emailtarget": "Sartu jasolearen erabiltzaile izena",
     "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",
     "watchlist-options": "Jarraitze-zerrendaren aukerak",
     "watching": "Zerrendan gehitzen...",
     "unwatching": "Zerrendatik kentzen...",
-    "enotif_mailer": "{{SITENAME}}(e)ko Oharpen Postaria",
     "enotif_reset": "Orrialde guztiak bisitatu bezala markatu",
     "enotif_impersonal_salutation": "{{SITENAME}} erabiltzailea",
     "enotif_subject_deleted": "{{SITENAME}}(e)ko $1 orrialdea {{GENDER:$2|ezabatu}} du $2 erabiltzaileak",
     "excontent": "edukia hau zen: '$1'",
     "excontentauthor": "edukia hau zen: \"$1\" (parte hartu duen lankide bakarra: \"[[Special:Contributions/$2|$2]]\")",
     "exbeforeblank": "hustu aurreko edukiera: '$1'",
-    "exblank": "orrialdea hutsik zegoen",
     "delete-confirm": "\"$1\" ezabatu",
     "delete-legend": "Ezabatu",
     "historywarning": "'''Oharra:''' Ezabatzera zoazen orrialdeak $1 {{PLURAL:$1|berrikuspen du|berrikuspen ditu}} gutxi gorabehera:",
     "importunknownsource": "Inportazio iturri mota ezezaguna",
     "importcantopen": "Ezin izan da inportazio fitxategia ireki",
     "importbadinterwiki": "Interwiki lotura ezegokia",
-    "importnotext": "Hutsik dago edo testurik gabe",
     "importsuccess": "Inportazioa burutu da!",
-    "importhistoryconflict": "Gatazka sortzen ari den berrikuspen historia dago (baliteke orrialdea lehenago inportatu izana)",
     "importnosources": "Ez dago wikien arteko inportazio iturririk definituta, eta historialak zuzenean igotzea ezgaituta dago.",
     "importnofile": "Ez da inportazio fitxategirik igo.",
     "importuploaderrorsize": "Inportatutako artxiboaren igoera-porrota.\nArtxiboa onartutako igoera-tamaina baino handiagoa da.",
index ae9a5ed..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",
index caf555b..1949be9 100644 (file)
     "permalink": "پیوند پایدار",
     "print": "چاپ",
     "view": "نمایش",
+    "view-foreign": "مشاهده در $1",
     "edit": "ویرایش",
+    "edit-local": "ویرایش توضیحات محلی",
     "create": "ایجاد",
+    "create-local": "افزودن توضیحات محلی",
     "editthispage": "ویرایش این صفحه",
     "create-this-page": "ایجاد این صفحه",
     "delete": "حذف",
     "pool-timeout": "اتمام مهلت انتظار برای قفل",
     "pool-queuefull": "صف مخزن پر است",
     "pool-errorunknown": "خطای ناشناخته",
+    "pool-servererror": "پول سنتر سرویس در دسترس نیست ( $1 ).",
     "aboutsite": "دربارهٔ {{SITENAME}}",
     "aboutpage": "Project:درباره",
     "copyright": "محتوایات تحت اجازه‌نامهٔ $1 هستند مگر اینکه خلافش ذکر شده باشد.",
     "accountcreatedtext": "حساب کاربری برای [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|بحث]]) ایجاد شده است.",
     "createaccount-title": "ایجاد حساب کاربری در {{SITENAME}}",
     "createaccount-text": "یک نفر برای رایانامه شما یک حساب کاربری در {{SITENAME}} با نام «$2» ایجاد کرده‌است ($4)، که گذرواژهٔ آن چنین است: $3\nشما باید به سامانه وارد شوید تا گذرواژهٔ خود را تغییر بدهید.\n\nاگر این حساب اشتباهی ساخته شده است، این پیغام را نادیده بگیرید.",
-    "usernamehasherror": "نام کاربری نمی‌تواند شامل نویسه‌های درهم باشد",
     "login-throttled": "شما به تازگی چندین‌بار برای ثبت ورود تلاش کرده‌اید.\nلطفاً پیش از آنکه دوباره تلاش کنید $1 صبر کنید.",
     "login-abort-generic": "ورود شما ناموفق بود - خاتمهٔ ناگهانی داده شد",
     "loginlanguagelabel": "زبان: $1",
     "prefs-skin": "پوسته",
     "skin-preview": "پیش‌نمایش",
     "datedefault": "بدون ترجیح",
-    "prefs-beta": "ویژگی‌های آزمایشی",
     "prefs-datetime": "تاریخ و زمان",
     "prefs-labs": "گزینه‌های آزمایشی",
     "prefs-user-pages": "صفحه‌های کاربری",
     "upload-permitted": "انواع مجاز پرونده‌ها: $1.",
     "upload-preferred": "انواع ترجیح‌داده شده پرونده‌ها: $1.",
     "upload-prohibited": "انواع نامجاز پرونده‌ها: $1.",
-    "uploadlog": "سیاههٔ بارگذاری‌ها",
     "uploadlogpage": "سیاههٔ بارگذاری‌ها",
     "uploadlogpagetext": "فهرست زیر فهرستی از آخرین بارگذاری پرونده‌ها است.\nبرای مرور دیداری [[Special:NewFiles|نگارخانهٔ پرونده‌های جدید]] را ببینید.",
     "filename": "نام پرونده",
     "filereuploadsummary": "تغییرات پرونده:",
     "filestatus": "وضعیت حق تکثیر:",
     "filesource": "منبع:",
-    "uploadedfiles": "پرونده‌های بارشده",
     "ignorewarning": "چشم‌پوشی از هشدار و ذخیرهٔ پرونده.",
     "ignorewarnings": "چشم‌پوشی از همهٔ هشدارها",
     "minlength1": "نام پرونده دست کم باید یک حرف باشد.",
     "overwroteimage": "نسخه جدیدی از  «[[$1]]» را بارگذاری کرد",
     "uploaddisabled": "بارگذاری غیرفعال است.",
     "copyuploaddisabled": "بارگذاری از طریق نشانی اینترنتی غیرفعال است.",
-    "uploadfromurl-queued": "بارگذاری شما به صف اضافه شد.",
     "uploaddisabledtext": "امکان بارگذاری پرونده غیرفعال است.",
     "php-uploaddisabledtext": "بارگذاری پرونده‌های پی‌اچ‌پی غیرفعال است.\nلطفاً تنظیمات file_uploads را بررسی کنید.",
     "uploadscripted": "این صفحه حاوی کد اچ‌تی‌ام‌ال یا اسکریپتی است که ممکن است به‌نادرست توسط مرورگر وب تفسیر شود.",
     "upload-misc-error": "خطای نامعلوم در بارگذاری",
     "upload-misc-error-text": "هنگام بارگذاری، خطایی نامعلوم رخ داد.\nلطفاً اطمینان حاصل کنید که نشانی اینترنتی معتبر و قابل دسترسی است و بعد دوباره تلاش کنید.\nاگر مشکل همچنان برقرار بود با یکی از [[Special:ListUsers/sysop|مدیران]] تماس بگیرید.",
     "upload-too-many-redirects": "نشانی اینترتی حاوی تعداد بیش از اندازه‌ای تغییرمسیر است",
-    "upload-unknown-size": "اندازهٔ نامشخص",
     "upload-http-error": "یک خطای اچ‌تی‌تی‌پی رخ داد: $1",
     "upload-copy-upload-invalid-domain": "بارگذاری کپی پرونده‌ها از این دامنه امکان‌پذیر نیست.",
     "backend-fail-stream": "نمی‌توان پروندهٔ $1 را ارسال کرد.",
     "img-auth-streaming": "در حال جاری ساختن «$1».",
     "img-auth-public": "عملکرد img_auth.php برونداد پرونده‌ها از یک ویکی خصوصی است.\nاین ویکی به عنوان یک ویکی عمومی تنظیم شده‌است.\nبرای امنیت بهینه، img_auth.php غیرفعال است.",
     "img-auth-noread": "کاربر دسترسی خواندن «$1» را ندارد.",
-    "img-auth-bad-query-string": "آدرس اینترنتی شامل یک رشتهٔ نامعتبر درخواست است.",
     "http-invalid-url": "نشانی نامعتبر: $1",
     "http-invalid-scheme": "نشانی‌های اینترنتی با طرح «$1» پشتیبانی نمی‌شوند.",
     "http-request-error": "درخواست اچ‌تی‌تی‌پی به علت خطایی ناشناخته، ناموفق بود.",
     "filehist-dimensions": "ابعاد",
     "filehist-filesize": "اندازهٔ پرونده",
     "filehist-comment": "توضیح",
-    "filehist-missing": "پروندهٔ ناموجود",
     "imagelinks": "به‌کاررفتن پرونده",
     "linkstoimage": "{{PLURAL:$1|صفحهٔ|صفحه‌های}} زیر به این تصویر پیوند {{PLURAL:$1|دارد|دارند}}:",
     "linkstoimage-more": "بیش از $1 صفحه به این پرونده پیوند {{PLURAL:$1|دارد|دارند}}.\nفهرست زیر تنها {{PLURAL:$1|اولین پیوند|اولین $1 پیوند}} به این صفحه را نشان می‌دهد.\n[[Special:WhatLinksHere/$2|فهرست کامل]] نیز موجود است.",
     "emailuser-title-notarget": "رایانامه به کاربر",
     "emailpage": "رایانامه به کاربر",
     "emailpagetext": "شما می‌توانید از فرم زیر برای ارسال یک رایانامه به این {{GENDER:$1|کاربر}} استفاده کنید.\nنشانی رایانامه‌ای که در [[Special:Preferences|ترجیحات کاربریتان]] وارد کرده‌اید در نشانی فرستنده (From) نامه خواهد آمد، تا گیرنده بتواند پاسخ دهد.",
-    "usermailererror": "رایانامه دچار خطا شد:",
     "defemailsubject": "رایانامه {{SITENAME}} از طرف کاربر «$1»",
     "usermaildisabled": "رایانامهٔ کاربر غیرقعال است",
     "usermaildisabledtext": "شما در این ویکی نمی‌توانید به دیگر کاربران رایانامه بفرستید",
     "noemailtitle": "نشانی رایانامه موجود نیست",
     "noemailtext": "این کاربر نشانی رایانامهٔ معتبری مشخص نکرده است،",
-    "nowikiemailtitle": "اجازهٔ ارسال رایانامه داده نشده‌است",
     "nowikiemailtext": "این کاربر انتخاب کرده که از دیگر کاربران رایانامه دریافت نکند.",
     "emailnotarget": "نام کاربری ناموجود یا نامعتبر برای گیرنده.",
     "emailtarget": "نام کاربری دریافت‌کننده را وارد کنید",
     "nowatchlist": "در فهرست پی‌گیری‌های شما هیچ موردی نیست.",
     "watchlistanontext": "برای مشاهده و ویرایش فهرست پی‌گیری‌های خود از $1 استفاده کنید.",
     "watchnologin": "به سامانه وارد نشده‌اید",
-    "watchnologintext": "برای تغییر فهرست پی‌گیری‌هایتان باید [[Special:UserLogin|به سامانه وارد شوید]].",
     "addwatch": "افزودن به فهرست پی‌گیری",
     "addedwatchtext": "صفحهٔ «[[:$1]]» به [[Special:Watchlist|فهرست پی‌گیری‌های]] شما اضافه شد.\nتغییرات این صفحه و صفحهٔ بحث متناظرش در آینده در اینجا فهرست خواهد شد.",
     "removewatch": "حذف از فهرست پی‌گیری",
     "watching": "پی‌گیری...",
     "unwatching": "توقف پی‌گیری...",
     "watcherrortext": "ایرادی در هنگام عوض کردن تنظیمات فهرست پیگیرتان برای «$1» رخ داد.",
-    "enotif_mailer": "رایانامهٔ اطلاع‌رسانی {{SITENAME}}",
     "enotif_reset": "نشان‌گذاری همهٔ صفحه‌ها به‌عنوان بازدیدشده",
     "enotif_impersonal_salutation": "کاربر {{SITENAME}}",
     "enotif_subject_deleted": "{{SITENAME}} صفحهٔ $1 توسط {{gender:$2|$2}} حذف شد.",
     "excontent": "محتوای صفحه این بود: «$1»",
     "excontentauthor": "محتوای صفحه این بود: «$1» (و تنها مشارکت‌کننده «[[Special:Contributions/$2|$2]]» بود)",
     "exbeforeblank": "محتوای صفحه قبل از خالی‌کردن این بود: «$1»",
-    "exblank": "صفحه خالی بود",
     "delete-confirm": "حذف «$1»",
     "delete-legend": "حذف",
     "historywarning": "'''هشدار!''' صفحه‌ای که قصد دارید حذف کنید تاریخچه‌ای با حدود $1 {{PLURAL:$1|نسخه|نسخه}} دارد:",
     "importunknownsource": "نوع مأخذ درون‌ریزی معلوم نیست",
     "importcantopen": "پروندهٔ درون‌ریزی صفحه‌ها باز نشد",
     "importbadinterwiki": "پیوند میان‌ویکی نادرست",
-    "importnotext": "صفحه خالی یا بدون متن",
     "importsuccess": "درون‌ریزی با موفقیت انجام شد!",
-    "importhistoryconflict": "نسخه‌های ناسازگار از تاریخچهٔ این صفحه وجود دارد (احتمالاً این صفحه پیش از این درون‌ریزی شده است)",
     "importnosources": "هیچ منبعی برای درون‌ریزی اطلاعات از ویکی دیگر تعریف نشده‌است.",
     "importnofile": "هیچ پرونده‌ای برای درون‌ریزی بارگذاری نشده‌است.",
     "importuploaderrorsize": "در بارگذاری پروندهٔ درون‌ریزی، اشکال رخ داد.\nاندازهٔ پرونده بیشتر از حداکثر اندازهٔ مجاز است.",
index fbecb98..d8458d4 100644 (file)
     "disclaimers": "Deentine",
     "disclaimerpage": "Project:Deentine kuuɓtidinɗe",
     "edithelp": "Ballal Taƴtagol",
-    "helppage": "Help:Loowdi",
     "mainpage": "Hello jaɓɓorgo",
     "mainpage-description": "Hello jaɓɓorgo",
     "policy-url": "Eɓɓoore:Dawirgol",
index b66508a..0c5c0c4 100644 (file)
     "permalink": "Ikilinkki",
     "print": "Tulosta",
     "view": "Näytä",
+    "view-foreign": "Katso kohdetta $1",
     "edit": "Muokkaa",
+    "edit-local": "Muokkaa paikallista kuvausta",
     "create": "Luo sivu",
+    "create-local": "Lisää paikallinen kuvaus",
     "editthispage": "Muokkaa tätä sivua",
     "create-this-page": "Luo tämä sivu",
     "delete": "Poista",
     "pool-timeout": "Lukon aikakatkaisu.",
     "pool-queuefull": "Lukkojono on täysi.",
     "pool-errorunknown": "Tuntematon virhe.",
+    "pool-servererror": "Pool counter -palvelu ei ole käytettävissä ($1).",
     "aboutsite": "Tietoja {{GRAMMAR:elative|{{SITENAME}}}}",
     "aboutpage": "Project:Tietoja",
     "copyright": "Sisältö on käytettävissä lisenssillä $1, ellei toisin ole mainittu.",
     "accountcreatedtext": "Käyttäjätunnus [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|keskustelu]]) luotiin.",
     "createaccount-title": "Tunnuksen luominen {{GRAMMAR:illative|{{SITENAME}}}}",
     "createaccount-text": "Joku on luonut tunnuksen $2 {{GRAMMAR:illative|{{SITENAME}}}} ($4).\nTunnus on \"$2\" ja sen salasana on \"$3\". Sinun on syytä kirjautua sisään ja vaihtaa salasanasi heti.\n\nSinun ei tarvitse välittää tästä viestistä, jos tämä tunnus on luotu virheellisesti.",
-    "usernamehasherror": "Käyttäjätunnus ei voi sisältää ristikkomerkkejä (#).",
     "login-throttled": "Olet tehnyt liian monta kirjautumisyritystä.\nOdota $1 ennen kuin yrität uudelleen.",
     "login-abort-generic": "Kirjautuminen epäonnistui – keskeytetty",
     "loginlanguagelabel": "Kieli: $1",
     "searcheverything-enable": "Hae kaikista nimiavaruuksista",
     "searchrelated": "samankaltainen",
     "searchall": "kaikki",
-    "showingresults": "{{PLURAL:$1|<strong>Yksi</strong> tulos|<strong>$1</strong> tulosta}} tuloksesta <strong>$2</strong> alkaen.",
+    "showingresults": "Alla on vain {{PLURAL:$1|<strong>1</strong> hakutulos|<strong>$1</strong> hakutulosta}} alkaen tuloksesta nro <strong>$2</strong>.",
     "showingresultsinrange": "Alla näytetään {{PLURAL:$1|<strong>1</strong> tulos|<strong>$1</strong> tulosta}} väliltä <strong>$2</strong> – <strong>$3</strong>.",
-    "showingresultsnum": "Alla on {{PLURAL:$3|'''Yksi''' hakutulos|'''$3''' hakutulosta}} alkaen '''$2.''' tuloksesta.",
+    "showingresultsnum": "Alla on {{PLURAL:$3|<strong>1</strong> hakutulos|<strong>$3</strong> hakutulosta}} alkaen tuloksesta nro <strong>$2</strong>.",
     "showingresultsheader": "{{PLURAL:$5|Tulokset '''$1'''–'''$3'''|Tulokset '''$1'''–'''$2''' kaikkiaan '''$3''' osuman joukosta}} haulle '''$4'''",
     "search-nonefound": "Hakusi ei tuottanut tulosta.",
     "powersearch-legend": "Laajennettu haku",
     "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",
     "upload-permitted": "Sallitut tiedostomuodot: $1.",
     "upload-preferred": "Suositellut tiedostomuodot: $1.",
     "upload-prohibited": "Kielletyt tiedostomuodot: $1.",
-    "uploadlog": "Tiedostoloki",
     "uploadlogpage": "Tiedostoloki",
     "uploadlogpagetext": "Alla on luettelo uusimmista tiedostonlisäyksistä. Kaikki ajat näytetään palvelimen aikavyöhykkeessä.",
     "filename": "Tiedoston nimi:",
     "filereuploadsummary": "Muutokset",
     "filestatus": "Tiedoston tekijänoikeudet",
     "filesource": "Lähde",
-    "uploadedfiles": "Lisätyt tiedostot",
     "ignorewarning": "Tallenna tiedosto varoituksesta huolimatta.",
     "ignorewarnings": "Ohita kaikki varoitukset",
     "minlength1": "Tiedoston nimessä pitää olla vähintään yksi merkki.",
     "overwroteimage": "tallensi uuden version [[$1]]",
     "uploaddisabled": "Tiedostojen tallennus ei ole käytössä.",
     "copyuploaddisabled": "Tallennus URL:n kautta on poistettu käytöstä.",
-    "uploadfromurl-queued": "Tallennuksesi on siirretty jonoon.",
     "uploaddisabledtext": "Tiedostojen tallennus on poistettu käytöstä.",
     "php-uploaddisabledtext": "PHP:n tiedostojen lähetys ei ole käytössä. Tarkista asetukset kohdasta file_uploads.",
     "uploadscripted": "Tämä tiedosto sisältää HTML-koodia tai skriptejä, jotka selain saattaa virheellisesti suorittaa.",
     "upload-misc-error": "Virhe",
     "upload-misc-error-text": "Tiedoston etälähetys ei onnistunut. Varmista, että antamasi osoite on oikein ja toimiva. Jos virhe ei katoa, ota yhteyttä sivuston [[Special:ListUsers/sysop|ylläpitäjään]].",
     "upload-too-many-redirects": "URL sisälsi liian monta ohjausta",
-    "upload-unknown-size": "Tuntematon koko",
     "upload-http-error": "HTTP-virhe: $1",
     "upload-copy-upload-invalid-domain": "Tiedostojen tallentamista tästä verkko-osoitteesta ei ole sallittu.",
     "backend-fail-stream": "Tiedoston $1 virtauttaminen epäonnistui.",
     "img-auth-streaming": "Toistetaan tiedostoa ”$1”.",
     "img-auth-public": "Img_auth.php:n tarkoitus on näyttää tiedostoja yksityisessä wikissä.\nTämä wiki on asennettu julkiseksi wikiksi.\nParhaan turvallisuuden vuoksi img_auth.php on poissa käytöstä.",
     "img-auth-noread": "Käyttäjillä ei ole oikeutta lukea tiedostoa ”$1”.",
-    "img-auth-bad-query-string": "Osoitteessa on epäkelpo query string -määritys.",
     "http-invalid-url": "Kelpaamaton URL: $1",
     "http-invalid-scheme": "Verkko-osoitteita kaavalla \"$1\" ei tueta",
     "http-request-error": "HTTP-pyyntö epäonnistui tuntemattoman virheen takia.",
     "filehist-dimensions": "Koko",
     "filehist-filesize": "Tiedostokoko",
     "filehist-comment": "Kommentti",
-    "filehist-missing": "Tiedosto puuttuu",
     "imagelinks": "Tiedoston käyttö",
     "linkstoimage": "{{PLURAL:$1|Seuraavalta sivulta|$1 sivulla}} on linkki tähän tiedostoon:",
     "linkstoimage-more": "Enemmän kuin $1 {{PLURAL:$1|sivu|sivua}} linkittää tähän tiedostoon.\nSeuraava lista näyttää {{PLURAL:$1|ensimmäisen linkittävän sivun|$1 ensimmäistä linkittävää sivua}} tähän tiedostoon.\n[[Special:WhatLinksHere/$2|Koko lista]] on saatavilla.",
     "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ä",
+    "listgrouprights-namespaceprotection-header": "Nimiavaruuksien rajoitukset",
+    "listgrouprights-namespaceprotection-namespace": "Nimiavaruus",
+    "listgrouprights-namespaceprotection-restrictedto": "Käyttäjän muokkausoikeudet",
     "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-summary": "Tällä sivulla on luettelo sellaisista ongelmia havaitsevista luokista (tarkkailuluokat), joiden sisällön koostaa 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.",
+    "noindex-category-desc": "Tätä sivua eivät hakurobotit indeksoi, koska sivulla on taikasana <code><nowiki>__NOINDEX__</nowiki></code> ja koska sivu on sellaisessa nimiavaruudessa, jossa taikasanan käyttö on sallittua.",
+    "index-category-desc": "Tällä sivulla on koodi <code><nowiki>__INDEX__</nowiki></code> ja sivu on sellaisessa nimiavaruudessa, jossa koodin käyttö on sallittua. Tämän vuoksi hakurobotit indeksoivat tämän sivun, vaikka ilman koodia sivua ei indeksoitaisi normaalisti.",
+    "post-expand-template-inclusion-category-desc": "Jos kaikki mallineet laajennetaan, sivun koko on suurempi kuin <code>$wgMaxArticleSize</code>. Tämän vuoksi kaikkia mallineita ei laajennettu.",
+    "post-expand-template-argument-category-desc": "Kun mallineen argumentti on laajennettu (argumentti on merkkijono kolmen kaarisulun sisällä kuten <code>{{{Foo}}})</code>, sivu on suurempi kuin <code>$wgMaxArticleSize</code>.",
+    "broken-file-category-desc": "Tämä luokka sisältää ne sivut, joissa on rikkinäinen tiedostolinkki. Tällä tarkoitetaan linkkiä sellaiseen tiedostoon, jota ei olemassa.",
+    "hidden-category-category-desc": "Tämä on luokka, joka sisältää koodin <code><nowiki>__HIDDENCAT__</nowiki></code>. Koodi estää luokan näkymisen sivujen alareunassa olevassa luokkien laatikossa oletusarvoisesti.",
     "trackingcategories-nodesc": "Ei kuvausta olemassa.",
     "trackingcategories-disabled": "Luokka on poistettu käytöstä",
     "mailnologin": "Lähettäjän osoite puuttuu",
     "emailuser-title-notarget": "Lähetä sähköpostia käyttäjälle",
     "emailpage": "Lähetä sähköpostia käyttäjälle",
     "emailpagetext": "Jos tämä {{GENDER:$1|käyttäjä}} on antanut asetuksissaan kelvollisen sähköpostiosoitteen, alla olevalla lomakkeella voit lähettää hänelle viestin. [[Special:Preferences|Omissa asetuksissasi]] annettu sähköpostiosoite näkyy sähköpostin lähettäjän osoitteena, jotta vastaanottaja voi suoraan vastata viestiin.",
-    "usermailererror": "Postitus palautti virheen:",
     "defemailsubject": "Sähköpostia käyttäjältä $1 sivustolta {{SITENAME}}",
     "usermaildisabled": "Käyttäjien sähköposti poistettu käytöstä",
     "usermaildisabledtext": "Et voi lähettää sähköpostia muille käyttäjille tässä wikissä",
     "noemailtitle": "Ei sähköpostiosoitetta",
     "noemailtext": "Tämä käyttäjä ei ole määritellyt kelvollista sähköpostiosoitetta.",
-    "nowikiemailtitle": "Sähköpostin lähettäminen ei sallittu",
     "nowikiemailtext": "Tämä käyttäjä ei halua sähköpostia muilta käyttäjiltä.",
     "emailnotarget": "Vastaanottajan käyttäjänimeä ei ole tai se on väärä.",
     "emailtarget": "Vastaanottajan käyttäjätunnus",
     "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",
     "watching": "Lisätään tarkkailulistalle...",
     "unwatching": "Poistetaan tarkkailulistalta...",
     "watcherrortext": "Sivun ”$1” tarkkailulista-asetusten muutoksissa tapahtui virhe.",
-    "enotif_mailer": "{{GRAMMAR:genitive|{{SITENAME}}}} sivu on muuttunut -ilmoitus",
     "enotif_reset": "Merkitse kaikki sivut nähdyiksi",
     "enotif_impersonal_salutation": "{{GRAMMAR:genitive|{{SITENAME}}}} käyttäjä",
     "enotif_subject_deleted": "{{GENDER:$2|$2}} poisti {{GRAMMAR:elative|{{SITENAME}}}} sivun $1",
     "excontent": "sisälsi: ”$1”",
     "excontentauthor": "sisälsi: ”$1” (ainoa muokkaaja oli $2)",
     "exbeforeblank": "ennen tyhjentämistä sisälsi: ”$1”",
-    "exblank": "oli tyhjä",
     "delete-confirm": "Poista ”$1”",
     "delete-legend": "Sivun poisto",
     "historywarning": "'''Varoitus:''' Sivua, jota olet poistamassa, on muokattu noin $1 {{PLURAL:$1|kerta|kertaa}}:",
     "importunknownsource": "Tuntematon lähdetyyppi",
     "importcantopen": "Tuontitiedoston avaus epäonnistui",
     "importbadinterwiki": "Kelpaamaton wikienvälinen linkki",
-    "importnotext": "Tyhjä tai ei tekstiä",
     "importsuccess": "Tuonti onnistui!",
-    "importhistoryconflict": "Sivusta on olemassa tuonnin kanssa ristiriitainen muokkausversio. Tämä sivu on saatettu tuoda jo aikaisemmin.",
     "importnosources": "Wikienvälisiä tuontilähteitä ei ole määritelty ja suorat historiatallennukset on poistettu käytöstä.",
     "importnofile": "Mitään tuotavaa tiedostoa ei lähetetty.",
     "importuploaderrorsize": "Tuontitiedoston tallennus epäonnistui. Tiedosto on suurempi kuin sallittu yläraja.",
index e1ed5b8..06493a4 100644 (file)
     "disclaimers": "Vastuuvaphaus",
     "disclaimerpage": "Project: Ylheinen varoitus",
     "edithelp": "Mookkausapua",
-    "helppage": "Help: Sisältö",
     "mainpage": "Alkusivu",
     "mainpage-description": "Alkusivu",
     "portal": "Kaikitten purthaali",
index 257a637..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",
index 76a1464..4ad6826 100644 (file)
     "accountcreatedtext": "Le compte utilisateur pour [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|discussion]]) a été créé.",
     "createaccount-title": "Création d’un compte pour {{SITENAME}}",
     "createaccount-text": "Quelqu’un a créé un compte pour votre adresse de courriel sur {{SITENAME}} ($4) intitulé « $2 », avec le mot de passe « $3 ».\nVous devriez ouvrir une session et modifier dès à présent votre mot de passe.\n\nIgnorez ce message si ce compte a été créé par erreur.",
-    "usernamehasherror": "Le nom d'utilisateur ne peut pas contenir des caractères de hachage",
     "login-throttled": "Vous avez tenté un trop grand nombre de connexions dernièrement.\nVeuillez attendre $1 avant d'essayer à nouveau.",
     "login-abort-generic": "Votre tentative de connexion a échoué",
     "loginlanguagelabel": "Langue : $1",
     "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",
     "upload-permitted": "Formats de fichiers autorisés : $1.",
     "upload-preferred": "Formats de fichiers préférés : $1.",
     "upload-prohibited": "Formats de fichiers interdits : $1.",
-    "uploadlog": "Journal d’import de fichiers",
     "uploadlogpage": "Journal d’import de fichiers",
     "uploadlogpagetext": "Voici la liste des derniers fichiers importés sur le serveur.\nVoyez la [[Special:NewFiles|galerie des nouvelles images]] pour une présentation plus visuelle.",
     "filename": "Nom du fichier",
     "filereuploadsummary": "Modifications du fichier :",
     "filestatus": "Statut du droit d'auteur :",
     "filesource": "Source :",
-    "uploadedfiles": "Fichiers importés",
     "ignorewarning": "Ignorer l'avertissement et sauvegarder le fichier quand même",
     "ignorewarnings": "Ignorer les avertissements",
     "minlength1": "Le noms de fichiers doivent comprendre au moins une lettre.",
     "overwroteimage": "a importé une nouvelle version de « [[$1]] »",
     "uploaddisabled": "Désolé, l’import de fichiers est désactivé.",
     "copyuploaddisabled": "Import de fichier par URL désactivé.",
-    "uploadfromurl-queued": "Votre fichier a été mis dans la file d’attente.",
     "uploaddisabledtext": "L’import de fichiers est désactivé sur ce wiki.",
     "php-uploaddisabledtext": "L'import de fichiers a été désactivé dans PHP. Vérifiez l'option de configuration file_uploads.",
     "uploadscripted": "Ce fichier contient du code HTML ou un script qui pourrait être interprété de façon incorrecte par un navigateur web.",
     "upload-misc-error": "Erreur d’import inconnue",
     "upload-misc-error-text": "Une erreur inconnue est survenue pendant l’import.\nVeuillez vérifier que l’URL est valide et accessible, puis essayer à nouveau.\nSi le problème persiste, contactez un [[Special:ListUsers/sysop|administrateur]].",
     "upload-too-many-redirects": "L’URL contient trop de redirections.",
-    "upload-unknown-size": "Taille inconnue",
     "upload-http-error": "Une erreur HTTP est survenue : $1",
     "upload-copy-upload-invalid-domain": "La copie des téléversements n’est pas disponible depuis ce domaine.",
     "backend-fail-stream": "Impossible de lire le fichier $1.",
     "img-auth-streaming": "Lecture en continu de « $1 ».",
     "img-auth-public": "La fonction de img_auth.php est d'afficher des fichiers d'un wiki privé.\nCe wiki est configuré comme un wiki public.\nPour une sécurité optimale, img_auth.php est désactivé.",
     "img-auth-noread": "L'utilisateur n'a pas le droit en lecture sur « $1 ».",
-    "img-auth-bad-query-string": "L'URL a une chaîne de requête invalide.",
     "http-invalid-url": "URL incorrecte : $1",
     "http-invalid-scheme": "Les URL avec le schéma « $1 » ne sont pas prises en charge.",
     "http-request-error": "Erreur inconnue lors de l'envoi de la requête.",
     "filehist-dimensions": "Dimensions",
     "filehist-filesize": "Taille du fichier",
     "filehist-comment": "Commentaire",
-    "filehist-missing": "Fichier manquant",
     "imagelinks": "Utilisation du fichier",
     "linkstoimage": "{{PLURAL:$1|La page suivante utilise|Les $1 pages suivantes utilisent}} ce fichier :",
     "linkstoimage-more": "Plus {{PLURAL:$1|d'une page utilise|de $1 pages utilisent}} ce fichier.\nLa liste suivante affiche seulement {{PLURAL:$1|la première page qui utilise|les $1 premières pages qui utilisent}} ce fichier.\nUne [[Special:WhatLinksHere/$2|liste complète]] est disponible.",
     "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.",
+    "noindex-category-desc": "La page contient un mot magique <code><nowiki>__NOINDEX__</nowiki></code> (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 <code><nowiki>__INDEX__</nowiki></code> (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 <code>$wgMaxArticleSize</code> ; 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 <code>{{{Foo}}}</code>), la page dépasse <code>$wgMaxArticleSize</code>.",
     "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.",
+    "hidden-category-category-desc": "C’est une catégorie contenant <code><nowiki>__HIDDENCAT__</nowiki></code>, 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",
     "emailuser-title-notarget": "Envoyer un courriel à l'utilisateur",
     "emailpage": "Envoyer un courriel à l'utilisateur",
     "emailpagetext": "Vous pouvez utiliser le formulaire ci-dessous pour envoyer un courriel à {{GENDER:$1|cet utilisateur|cette utilisatrice}}.\nL'adresse électronique que vous avez indiquée dans [[Special:Preferences|vos préférences]] apparaîtra dans le champ « Expéditeur » de votre message ; ainsi, le destinataire pourra vous répondre directement.",
-    "usermailererror": "Erreur dans l'objet du courriel :",
     "defemailsubject": "{{SITENAME}} Courriel de l'utilisateur « $1 »",
     "usermaildisabled": "L'envoi de courriels entre utilisateurs est désactivé",
     "usermaildisabledtext": "Vous ne pouvez pas envoyer de courriels à d'autres utilisateurs sur ce wiki",
     "noemailtitle": "Aucune adresse de courriel",
     "noemailtext": "Cet utilisateur n'a pas spécifié une adresse de courriel valide.",
-    "nowikiemailtitle": "Pas de courriel autorisé",
     "nowikiemailtext": "Cet utilisateur a choisi de ne pas recevoir de courriel de la part d'autres utilisateurs.",
     "emailnotarget": "Nom d'utilisateur du destinataire inexistant ou invalide.",
     "emailtarget": "Entrez le nom d'utilisateur du destinataire",
     "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",
     "watching": "Suivi…",
     "unwatching": "Fin du suivi…",
     "watcherrortext": "Une erreur s'est produite lors de la modification des paramètres de votre liste de suivi pour « $1 ».",
-    "enotif_mailer": "Système de notification par courriel de {{SITENAME}}",
     "enotif_reset": "Marquer toutes les pages comme visitées",
     "enotif_impersonal_salutation": "Utilisateur de {{SITENAME}}",
     "enotif_subject_deleted": "La page $1 sur {{SITENAME}} a été supprimée par {{GENDER:$2|$2}}",
     "excontent": "contenait « $1 »",
     "excontentauthor": "contenait « $1 » (et son seul contributeur était [[Special:Contributions/$2|$2]])",
     "exbeforeblank": "contenait avant blanchiment « $1 »",
-    "exblank": "la page était vide",
     "delete-confirm": "Supprimer « $1 »",
     "delete-legend": "Supprimer",
     "historywarning": "'''Attention :''' la page que vous êtes sur le point de supprimer a un historique avec environ $1 {{PLURAL:$1|version|versions}} :",
     "importunknownsource": "Type inconnu de la source à importer",
     "importcantopen": "Impossible d'ouvrir le fichier à importer",
     "importbadinterwiki": "Mauvais lien inter-wiki",
-    "importnotext": "Vide ou sans texte",
     "importsuccess": "L'importation a réussi !",
-    "importhistoryconflict": "Un conflit a été détecté dans l'historique des versions (cette page a pu être importée auparavant).",
     "importnosources": "Aucune source d'importation inter-wiki n'a été définie et l'import direct d'historiques est désactivé.",
     "importnofile": "Aucun fichier d'importation n'a été envoyé.",
     "importuploaderrorsize": "L'import du fichier a échoué.\nSa taille est supérieure au maximum autorisé pour l'import de fichier.",
index 463b5f2..03f016a 100644 (file)
     "disclaimers": "Avertissements",
     "disclaimerpage": "Project:Avertissements ordinaires",
     "edithelp": "Aide",
-    "helppage": "Help:Aide",
     "mainpage": "Page Principale",
     "mainpage-description": "Page Principale",
     "policy-url": "Project:Régulations",
index 7d3e7cd..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",
index d421a55..ce9aa63 100644 (file)
     "accountcreatedtext": "Det brükerkonto för [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|talk]]) as iinracht wurden.",
     "createaccount-title": "En brükerkonto üüb {{SITENAME}} iinracht",
     "createaccount-text": "Diar as mä din e-mail adres för di en brükerkonto \"$2\" üüb {{SITENAME}} ($4) maaget wurden. För \"$2\" as automaatisk det paaswurd \"$3\" iinracht wurden.\nDü skulst di nü uunmelde an det paaswurd anre.\n\nWan det brükerkonto ütj fersen uunlaanj wurden as, säärst dü niks widjer onernem.",
-    "usernamehasherror": "Uun brükernöömer mut nian rütjen föörkem.",
     "login-throttled": "Dü heest tufölsis fersoocht, di uuntumeldin.\nWees so gud an teew $1, iar dü det noch ans ferschükst.",
     "login-abort-generic": "Det uunmeldin hää ei loket - Ufbreegen",
     "loginlanguagelabel": "Spriak: $1",
     "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",
     "upload-permitted": "Tuläät slacher faan datein: $1.",
     "upload-preferred": "Slacher faan datein, diar dü brük skulst: $1.",
     "upload-prohibited": "Ei tuläät slacher faan datein: $1.",
-    "uploadlog": "datei logbuk",
     "uploadlogpage": "Datei-logbuk",
     "uploadlogpagetext": "Detheer as det logbuk för huuchschüürd datein. Dü könst uk det [[Special:NewFiles|galerii faan nei datein]] uunluke.",
     "filename": "Dateinööm",
     "filereuploadsummary": "Feranrangen faan det datei:",
     "filestatus": "Copyright-Status:",
     "filesource": "Kwel",
-    "uploadedfiles": "Huuchschüürd datein",
     "ignorewarning": "Ei üüb wäärnangen aachte an det datei seekre",
     "ignorewarnings": "Ei am wäärnangen komre",
     "minlength1": "Dateinöömer skel tumanst ään buksteew lung wees.",
     "overwroteimage": "hää en nei werjuun faan „[[$1]]“ huuchschüürd",
     "uploaddisabled": "Huuchschüüren as ei aktiwiaret",
     "copyuploaddisabled": "Huuchschüüren faan URLs as ei aktiwiaret.",
-    "uploadfromurl-queued": "Din huuchschüürd datei teewt.",
     "uploaddisabledtext": "Det huuchschüüren faan datein as ei aktiwiaret.",
     "php-uploaddisabledtext": "Det huuchschüüren faan datein as uun PHP ei aktiwiaret.\nLuke di det iinstelang faan <code>file_uploads</code> uun.",
     "uploadscripted": "Uun detdiar datei stäänt HTML- of Scriptcode, an küd ütj fersen faan en browser ütjfeerd wurd.",
     "upload-misc-error": "Bi't huuchschüüren as wat skiaf gingen.",
     "upload-misc-error-text": "Bi't huuchschüüren as wat skiaf gingen. Luke di det URL noch ans uun, an of det sidj uk würelk diar as.\nWan det goorei wal, do skriiw tu en [[Special:ListUsers/sysop|administraator]].",
     "upload-too-many-redirects": "Det URL hää tuföl widjerfeerangen.",
-    "upload-unknown-size": "Ünbekäänd grate",
     "upload-http-error": "Diar as en HTTP-feeler mä: $1",
     "upload-copy-upload-invalid-domain": "Kopiin faan datein kön faan detdiar domeen ei huuchschüürd wurd.",
     "backend-fail-stream": "Det datei $1 küd ei auerdraanj wurd.",
     "img-auth-streaming": "„$1“ woort iinleesen.",
     "img-auth-public": "Mä img_auth.php wurd datein faan en priwoot Wiki ütjden.\nDetheer as oober en öfentelk Wiki.\nFör a seekerhaid as img_auth.php ei aktiwiaret.",
     "img-auth-noread": "Di brüker hää nian rocht, „$1“ tu leesen.",
-    "img-auth-bad-query-string": "Uun det URL san ei tuläät uffraagtiakens.",
     "http-invalid-url": "Ei tuläät URL: $1",
     "http-invalid-scheme": "URLs mä det münster „$1“ kön ei brükt wurd.",
     "http-request-error": "HTTP-feeler bi't uffraagin.",
     "filehist-dimensions": "Miaten",
     "filehist-filesize": "Dateigrate",
     "filehist-comment": "Komentaar",
-    "filehist-missing": "Datei ei diar",
     "imagelinks": "Hü det datei brükt woort",
     "linkstoimage": "{{PLURAL:$1|Detdiar sidj brükt|Jodiar $1 sidjen brük}} detdiar datei:",
     "linkstoimage-more": "Muar üs $1 {{PLURAL:$1|sidj ferwiset|sidjen ferwise}} üüb detdiar datei.\nDet list wiset {{PLURAL:$1|at iarst ferwisang|a iarst $1 ferwisangen}} üüb detdiar datei.\nDü könst uk det [[Special:WhatLinksHere/$2|hial list]] uunluke.",
     "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.",
+    "noindex-category-desc": "Üüb detdiar sidj stäänt det maagisk wurd <code><nowiki>__NOINDEX__</nowiki></code> 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 <code><nowiki>__INDEX__</nowiki></code> 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 <code>$wgMaxArticleSize</code>, 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 <code>{{{Foo}}})</code> as det sidj grater üs <code>$wgMaxArticleSize</code>.",
     "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.",
+    "hidden-category-category-desc": "Det as en kategorii, huar <code><nowiki>__HIDDENCAT__</nowiki></code> üü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",
     "emailuser-title-notarget": "E-mail tu brüker",
     "emailpage": "E-mail tu brüker",
     "emailpagetext": "Dü könst {{GENDER:$1|di brüker|det brükerin}} mä det formulaar en e-mail schüür.\nDin aanj e-mail adres faan din [[Special:Preferences|iinstelangen]] woort uunwiset, so dat {{GENDER:$1|di brüker|det brükerin}} di saner amwai swaare koon.",
-    "usermailererror": "Det e-mail objekt wiset en feeler uun.",
     "defemailsubject": "{{SITENAME}} e-mail faan brüker „$1“",
     "usermaildisabled": "E-mail fun as ei aktiif",
     "usermaildisabledtext": "Dü könst nian e-mail tu ööder brükern schüür.",
     "noemailtitle": "Nian e-mail adres",
     "noemailtext": "Didiar brüker hää nian gudkäänd e-mail adres uunden.",
-    "nowikiemailtitle": "E-mail koon ei wechschüürd wurd",
     "nowikiemailtext": "Didiar brüker maad nian e-mails faan ööder brükern fu.",
     "emailnotarget": "Didiar brükernööm as ei bekäänd of ei gudkäänd, am ham en e-mail tu schüüren",
     "emailtarget": "Brükernööm faan di ööder brüker iindu",
     "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",
     "watching": "Uun't uug behual ...",
     "unwatching": "Ei uun't uug behual ...",
     "watcherrortext": "Bi't anrin faan iinstelangen för „$1“ as wat skiaf gingen.",
-    "enotif_mailer": "{{SITENAME}}-e-mail-noorachten siinst",
     "enotif_reset": "Aal a sidjen üs besoocht kääntiakne",
     "enotif_impersonal_salutation": "{{SITENAME}}-brüker",
     "enotif_subject_deleted": "{{SITENAME}}-sidj $1 as faan {{GENDER:$2|$2}} stregen wurden.",
     "excontent": "diar sted: „$1“",
     "excontentauthor": "diar sted: „$1“ (iansagst bewerker: [[Special:Contributions/$2|$2]])",
     "exbeforeblank": "diar sted föör't leesag maagin: „$1“",
-    "exblank": "sidj wiar leesag",
     "delete-confirm": "Strik \"$1\"",
     "delete-legend": "Strike",
     "historywarning": "'''Paase üüb:''' Det sidj, wat dü strik wel, hää amanbi $1 {{PLURAL:$1|werjuun|werjuunen}}:",
     "importunknownsource": "Ünbekäänd importkwel",
     "importcantopen": "Det import-datei küd ei eeben maaget wurd.",
     "importbadinterwiki": "Ferkiard interwiki-link",
-    "importnotext": "Leesag of nään tekst",
     "importsuccess": "Import klaar!",
-    "importhistoryconflict": "Diar san al ääler werjuunen diar. Ferlicht as det sidj al ans importiaret wurden.",
     "importnosources": "För di transwiki-import san nian kwelen uunden. Dü könst werjuunen ei direkt huuchschüür.",
     "importnofile": "Diar as nian importdatei bestemet wurden.",
     "importuploaderrorsize": "Bi't huuchschüüren faan det importdatei as wat skiaf gingen. Det datei as tu grat.",
index 4233f4e..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",
index d448cc9..12b457c 100644 (file)
     "permalink": "Fêste keppeling",
     "print": "Ofdrukke",
     "view": "Lêze",
-    "edit": "Wizigje",
+    "edit": "Feroarje",
     "create": "Oanmeitsje",
     "editthispage": "Side bewurkje",
     "create-this-page": "Dizze side oanmeitsje",
     "revdelete-hide-comment": "De bewurkingsgearfetting ferskûlje",
     "revdelete-hide-user": "Meidoggernamme/IP fan de meidogger ferskûlje",
     "revdelete-hide-restricted": "Dizze beheinings tapasse op behearders en dizze ynterface ôfslute",
+    "revdelete-radio-set": "Ferburgen",
+    "revdelete-radio-unset": "Sichtber",
     "revdelete-suppress": "Gegevens foar behearders likegoed as oaren ûnderdrukke",
     "revdelete-unsuppress": "Beheinings op tebeksette feroarings fuorthelje",
     "revdelete-log": "Reden:",
     "revdelete-submit": "Tapasse op selektearre bewurking",
-    "revdelete-success": "'''Sichtberens fan'e feroaring mei sukses ynsteld.'''",
+    "revdelete-success": "'''Sichtberens fan 'e feroaring mei sukses ynsteld.'''",
     "logdelete-success": "'''Sichtberens fan it barren mei sukses ynsteld.'''",
     "revdel-restore": "Sichtberens feroarje",
     "pagehist": "Sideskiednis",
     "upload-permitted": "Talitten triemtypen: $1.",
     "upload-preferred": "Oanwiisde triemtypen: $1.",
     "upload-prohibited": "Ferbeane triemtypen: $1.",
-    "uploadlog": "oanbiedloch",
     "uploadlogpage": "Oanbiedloch",
     "uploadlogpagetext": "List fan de lêst oanbeane triemmen. (Tiid oanjûn as UTC).",
     "filename": "Triemnamme",
     "filereuploadsummary": "Triemferoarings:",
     "filestatus": "Auteursrjochtensituaasje:",
     "filesource": "Boarne:",
-    "uploadedfiles": "Oanbeane triemmen",
     "ignorewarning": "Negearje de warskôging en lis triem dochs fêst.",
     "ignorewarnings": "Negearje warskôgings",
     "minlength1": "Triemnammen moatte minstens út ien teken bestean.",
     "upload-file-error-text": "Der wie in ynterne fout doe't in tydlike triem op'e server oanmakke waard.\nNim kontakt op mei in [[Special:ListUsers/sysop|behearder]].",
     "upload-misc-error": "Unbekende oanbiedfout",
     "upload-misc-error-text": "Der is by it oanbieden in ûnbekende fout optreden.\nKontrolearje of de URL krekt en beskikber is en besykje it nochris.\nAs it probleem oanhâldt, nim dan kontakt op mei in\n[[Special:ListUsers/sysop|behearder]].",
-    "upload-unknown-size": "Unbekinde grutte",
     "upload-curl-error6": "Koe de URL net berikke",
     "upload-curl-error6-text": "De opjûne URL is net berikber.\nKontrolearje oft de URL krekt is en oft de webside beskikber is.",
     "upload-curl-error28": "Oanbiedtiid foarby",
     "filehist-dimensions": "Ofmjittings",
     "filehist-filesize": "Triem grutte",
     "filehist-comment": "Opmerkings",
-    "filehist-missing": "Triem net fûn",
     "imagelinks": "Ofbyldkeppelings",
     "linkstoimage": "Dizze {{PLURAL:$1|side is|$1 siden binne}} keppele oan it ôfbyld:",
     "linkstoimage-more": "Der {{PLURAL:$2|is|binne}} mear as $1 {{PLURAL:$1|ferwizing|ferwizings}} nei dizze triem.\nDe folgjende list jout allinne de earste {{PLURAL:$1|ferwizing|$1 ferwizings}} nei dizze triem wer.\nDer is ek in [[Special:WhatLinksHere/$2|folsleine list]].",
     "emailuser": "Skriuw meidogger",
     "emailpage": "E-post nei meidogger",
     "emailpagetext": "Fia dit berjocht kinne jo in e-mail oan dizze brûker ferstjoere.\nIt e-mailadres dat jo opjûn hawwe by [[Special:Preferences|jo foarkarren]] wurdt as ôfstjoerder  brûkt.\nDe ûntfanger kin dus daliks nei jo reagearje.",
-    "usermailererror": "Flatermelding by ferstjoeren:",
     "defemailsubject": "E-post fan {{SITENAME}}",
     "noemailtitle": "Gjin e-postadres",
     "noemailtext": "Dizze meidogger hat gjin jildich e-postadres ynsteld, of hat oanjûn gjin post fan oare meidoggers krije te wollen.",
-    "nowikiemailtitle": "E-mail is net tastien",
     "nowikiemailtext": "Dizze brûker wol gjin e-mail ûntfange fan oare brûkers.",
     "email-legend": "In e-mail ferstjoere nei in oare brûker fan {{SITENAME}}",
     "emailfrom": "Fan:",
     "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",
     "excontent": "ynhâld wie: '$1'",
     "excontentauthor": "ynhâld wie: '$1' (en de ienige bewurker wie: '[[Special:Contributions/$2|$2]]')",
     "exbeforeblank": "foar de tekst wiske wie, wie dat: '$1'",
-    "exblank": "side wie leech",
     "delete-confirm": "\"$1\" wiskje",
     "delete-legend": "Wiskje",
     "historywarning": "Warskôging: De side dy't jo wiskje wolle hat skiednis:",
     "importunknownsource": "Unbekende ymportboarnetype",
     "importcantopen": "De ymporttriem koe net iepenen wurde.",
     "importbadinterwiki": "Ferkearde ynterwikiferwizing",
-    "importnotext": "Leech of gjin tekst",
     "importsuccess": "Ymport slagge!",
     "importnofile": "Gjin ymporttriem is oanbeane.",
     "import-noarticle": "Gjin side te ymportearjen!",
     "exif-gpstimestamp": "GPS-tiid (atoomklok)",
     "exif-gpsspeedref": "Snelheidsienheid",
     "exif-gpsdatestamp": "GPS-datum",
+    "exif-source": "Boarne",
+    "exif-contact": "Kontakt ynformaasje",
+    "exif-writer": "Skriuwer",
+    "exif-languagecode": "Taal",
+    "exif-iimcategory": "Kategory",
+    "exif-datetimereleased": "Utbrocht op",
+    "exif-serialnumber": "Searjenûmer fan de kamera",
+    "exif-cameraownername": "Eigner fan de kamera",
+    "exif-copyrightowner": "Copyright eigner",
+    "exif-disclaimer": "Foarbehâld",
     "exif-unknowndate": "Datum ûnbekend",
     "exif-orientation-1": "Normaal",
     "exif-componentsconfiguration-0": "bestiet net",
     "exif-sharpness-0": "Normaal",
     "exif-subjectdistancerange-0": "Unbekend",
     "exif-subjectdistancerange-2": "Tichtby",
+    "exif-gpsdestdistance-m": "Milen",
+    "exif-gpsdestdistance-n": "Seemilen",
     "watchlistall2": "alles",
     "namespacesall": "alles",
     "monthsall": "alle",
     "confirmemail_body": "Immen, nei gedachten jo, hat him by {{SITENAME}} oanmelde as \"$2\", mei dit netpostadres ($1).\n\nHjirtroch komme ek de netpostfunksjes fan {{SITENAME}} foar jo beskikber. Iepenje de neikommende keppeling om te befêstigjen dat jo wier josels by {{SITENAME}} mei dit netpostadres oanmelde hawwe:\n\n$3\n\nAt jo dat *net* wienen, brûk dy keppeling dan net, en klik hjir:\n\n$5\n\nDizze befêstigingskoade ferrint dan op $4.",
     "scarytranscludetoolong": "[URL-adres is te lang]",
     "confirmrecreate": "Sûnt jo begûn binne dizze side te bewurkjen, hat meidogger [[User:$1|$1]] ([[User talk:$1|oerlis]]) de side wiske. De reden dy't derfoar jûn waard wie:\n: ''$2''\nWolle jo de side wier op 'e nij skriuwe?",
+    "confirm_purge_button": "Okee",
+    "confirm-watch-button": "Okee",
+    "confirm-unwatch-button": "Okee",
+    "confirm-unwatch-top": "Dizze side fan myn folchlist ôfhelje",
+    "imgmultipageprev": "side werom",
     "imgmultipagenext": "folgjende side →",
     "imgmultigo": "Los!",
     "imgmultigoto": "Gean nei side $1",
+    "img-lang-default": "(standert taal)",
     "table_pager_next": "Folgjende side",
+    "table_pager_prev": "Side werom",
     "table_pager_first": "Earste side",
+    "table_pager_last": "Lêste side",
     "table_pager_limit_submit": "Los!",
     "table_pager_empty": "Gjin resultaat",
     "autosumm-blank": "Alle ynhâld fan de side weismiten",
     "autoredircomment": "Ferwiist troch nei [[$1]]",
     "autosumm-new": "Nije Side: $1",
     "livepreview-loading": "Ynlade...",
+    "livepreview-ready": "Lade... Klear!",
     "watchlistedit-normal-title": "Folchlist bewurkje",
     "watchlistedit-normal-submit": "Siden wiskje",
     "watchlistedit-raw-titles": "Siden:",
     "specialpages-group-spam": "Spamhelpmiddels",
     "blankpage": "Side is leech",
     "intentionallyblankpage": "Dizze side is bewust leech lizzen en wurdt brûkt foar benchmarks, ensfh.",
+    "tags-active-yes": "Ja",
+    "tags-active-no": "Nee",
+    "tags-edit": "bewurkje",
+    "tags-hitcount": "$1 {{PLURAL:$1|bewurking|bewurkings}}",
+    "comparepages": "Siden ferlykje",
+    "compare-page1": "Side 1",
+    "compare-page2": "Side 2",
+    "compare-rev1": "Revyzje 1",
+    "compare-rev2": "Revyzje 2",
+    "compare-submit": "Ferlykje",
+    "compare-invalid-title": "Unjildige titel.",
     "revdelete-restricted": "hat beheinings oplein oan behearders",
     "revdelete-unrestricted": "hat beheinings foar behearders goedmakke",
     "rightsnone": "(gjin)",
     "feedback-cancel": "Ofbrekke",
     "feedback-submit": "Feedback ferstjoere",
     "feedback-close": "Dien",
-    "searchsuggest-search": "Sykje"
+    "searchsuggest-search": "Sykje",
+    "expand_templates_ok": "Okee",
+    "expand_templates_remove_comments": "Berjochten fuorthelje"
 }
index 20cbebe..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",
index e304e0a..c315751 100644 (file)
     "nowatchlist": "倷𠮶监视列表什哩都冇有。",
     "watchlistanontext": "请$1眵吖或改吖倷𠮶监视列表。",
     "watchnologin": "冇登入",
-    "watchnologintext": "倷要[[Special:UserLogin|登入]]起才改得正倷𠮶监视列表。",
     "addedwatchtext": "页面\"[[:$1]]\" 加到嘞倷𠮶[[Special:Watchlist|监视列表]]。个页同佢𠮶讨论页𠮶全部改动以后都会列到许首,佢会用'''粗体''' 列到[[Special:RecentChanges|最近更改]]让倷更加容易识别。 倷以后要系拿佢到监视列表删卟佢𠮶话,就到导航条点吖“莫眏到”。",
     "removedwatchtext": "页面[[:$1]]到[[Special:Watchlist|倷𠮶监视列表]]删卟哩。",
     "watch": "眏到",
index dedb541..aeb3d49 100644 (file)
     "nowatchlist": "倷嗰監視列表什哩都冇有。",
     "watchlistanontext": "請$1眵吖或改吖倷嗰監視列表。",
     "watchnologin": "冇登入",
-    "watchnologintext": "倷要[[Special:UserLogin|登入]]起才改得正倷嗰監視列表。",
     "addedwatchtext": "頁面「[[:$1]]」加到嘞倷嗰[[Special:Watchlist|監視列表]]。箇頁同佢嗰討論頁嗰全部改動以後都會列到許首,佢會用'''粗體''' 列到[[Special:RecentChanges|最近更改]]讓倷更加容易識別。 倷以後要係拿佢到監視列表刪卟佢嗰話,就到導航條點吖「莫眏到」。",
     "removedwatchtext": "頁面[[:$1]]到[[Special:Watchlist|倷嗰監視列表]]刪卟哩。",
     "watch": "眏到",
index 477114f..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",
index 438ac56..37f5124 100644 (file)
@@ -13,7 +13,8 @@
             "Toliño",
             "Vivaelcelta",
             "Xosé",
-            "לערי ריינהארט"
+            "לערי ריינהארט",
+            "Fitoschido"
         ]
     },
     "tog-underline": "Subliñar as ligazóns:",
     "permalink": "Ligazón permanente",
     "print": "Imprimir",
     "view": "Ver",
+    "view-foreign": "Ver en $1",
     "edit": "Editar",
+    "edit-local": "Editar a descrición local",
     "create": "Crear",
+    "create-local": "Engadir a descrición local",
     "editthispage": "Editar esta páxina",
     "create-this-page": "Crear esta páxina",
     "delete": "Borrar",
     "accountcreatedtext": "Creouse a conta de usuario para [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|conversa]]).",
     "createaccount-title": "Creación dunha conta para {{SITENAME}}",
     "createaccount-text": "Alguén creou unha conta chamada \"$2\" para o seu enderezo de correo electrónico en {{SITENAME}} ($4), e con contrasinal \"$3\".\nDebe acceder ao sistema e mudar o contrasinal agora.\n\nPode facer caso omiso desta mensaxe se se creou esta conta por erro.",
-    "usernamehasherror": "O nome de usuario non pode conter cancelos (\"#\")",
     "login-throttled": "Fixo demasiados intentos de acceder ao sistema.\nPor favor, agarde $1 antes de probar outra vez.",
     "login-abort-generic": "Acceso ao sistema incorrecto; abortado",
     "loginlanguagelabel": "Lingua: $1",
     "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",
     "upload-permitted": "Tipos de ficheiro permitidos: $1.",
     "upload-preferred": "Tipos de ficheiro preferidos: $1.",
     "upload-prohibited": "Tipos de ficheiro prohibidos: $1.",
-    "uploadlog": "rexistro de cargas",
     "uploadlogpage": "Rexistro de cargas",
     "uploadlogpagetext": "A continuación está a lista cos últimos ficheiros cargados no servidor.\nVexa a [[Special:NewFiles|galería de imaxes novas]] para ollar unha visión máis xeral.",
     "filename": "Nome do ficheiro",
     "filereuploadsummary": "Cambios no ficheiro:",
     "filestatus": "Estado dos dereitos de autor:",
     "filesource": "Fonte:",
-    "uploadedfiles": "Ficheiros cargados",
     "ignorewarning": "Ignorar a advertencia e gardar o ficheiro de calquera xeito",
     "ignorewarnings": "Ignorar as advertencias",
     "minlength1": "Os nomes dos ficheiros deben ter cando menos unha letra.",
     "overwroteimage": "enviou unha nova versión de \"[[$1]]\"",
     "uploaddisabled": "Sentímolo, a subida de ficheiros está desactivada.",
     "copyuploaddisabled": "A carga mediante URL está desactivada.",
-    "uploadfromurl-queued": "A súa carga púxose á cola.",
     "uploaddisabledtext": "A carga de ficheiros está desactivada.",
     "php-uploaddisabledtext": "As cargas de ficheiros PHP están desactivadas. Por favor, comprobe a característica file_uploads.",
     "uploadscripted": "Este ficheiro contén código HTML ou script que pode producir erros ao ser interpretado polo navegador.",
     "upload-misc-error": "Erro de carga descoñecido",
     "upload-misc-error-text": "Ocorreu un erro descoñecido durante a carga.\nComprobe que o enderezo URL é válido e accesible e, despois, inténteo de novo.\nSe o problema persiste, póñase en contacto cun [[Special:ListUsers/sysop|administrador]].",
     "upload-too-many-redirects": "O enderezo URL contiña moitas redireccións",
-    "upload-unknown-size": "Tamaño descoñecido",
     "upload-http-error": "Produciuse un erro HTTP: $1",
     "upload-copy-upload-invalid-domain": "A copia de cargas non está dispoñible neste dominio.",
     "backend-fail-stream": "Non se puido transmitir o ficheiro \"$1\".",
     "img-auth-streaming": "Secuenciando \"$1\".",
     "img-auth-public": "A función de img_auth.php é para ficheiros de saída desde un wiki privado.\nEste wiki está configurado como público.\nPara unha seguridade óptima, img_auth.php está desactivado.",
     "img-auth-noread": "O usuario non ten acceso á lectura de \"$1\".",
-    "img-auth-bad-query-string": "O enderezo URL ten unha secuencia de consulta incorrecta.",
     "http-invalid-url": "URL non válido: $1",
     "http-invalid-scheme": "Os enderezos URL co esquema \"$1\" non están soportados",
     "http-request-error": "Erro descoñecido ao enviar a solicitude.",
     "filehist-dimensions": "Dimensións",
     "filehist-filesize": "Tamaño do ficheiro",
     "filehist-comment": "Comentario",
-    "filehist-missing": "Falta o ficheiro",
     "imagelinks": "Uso do ficheiro",
     "linkstoimage": "{{PLURAL:$1|A seguinte páxina liga|As seguintes $1 páxinas ligan}} con esta imaxe:",
     "linkstoimage-more": "Máis {{PLURAL:$1|dunha páxina liga|de $1 páxinas ligan}} con este ficheiro.\nA seguinte lista só mostra {{PLURAL:$1|a primeira páxina que liga|as primeiras $1 páxina que ligan}} con el.\nHai dispoñible [[Special:WhatLinksHere/$2|unha lista completa]].",
     "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.",
+    "noindex-category-desc": "A páxina non está indexada polos robots porque ten a palabra máxica <code><nowiki>__NOINDEX__</nowiki></code> e está nun espazo de nomes no que esa marca está permitida.",
+    "index-category-desc": "A páxina contén a palabra máxica <code><nowiki>__INDEX__</nowiki></code> (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 <code>$wgMaxArticleSize</code>; algúns modelos non se expandiron.",
+    "post-expand-template-argument-category-desc": "Despois de expandir o argumento dun modelo (algo entre chaves triples, como <code>{{{Proba}}}</code>), a páxina é maior que <code>$wgMaxArticleSize</code>.",
     "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.",
+    "hidden-category-category-desc": "Esta é unha categoría coa palabra máxica <code><nowiki>__HIDDENCAT__</nowiki></code>, 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",
     "emailuser-title-notarget": "Enviar un correo electrónico a un usuario",
     "emailpage": "Enviar un correo electrónico a un usuario",
     "emailpagetext": "Pode usar o seguinte formulario para enviar unha mensaxe de correo electrónico a {{GENDER:$1|este usuario|esta usuaria}}.\nO enderezo de correo electrónico que inseriu [[Special:Preferences|nas súas preferencias]] aparecerá no campo \"De:\" do correo, polo que {{GENDER:$1|o receptor|a receptora}} da mensaxe poderá responderlle directamente.",
-    "usermailererror": "O obxecto enviado deu unha mensaxe de erro:",
     "defemailsubject": "Correo electrónico do usuario $1 de {{SITENAME}}",
     "usermaildisabled": "O correo electrónico do usuario está desactivado",
     "usermaildisabledtext": "Non pode enviar correos electrónicos a outros usuarios deste wiki",
     "noemailtitle": "Sen enderezo de correo electrónico",
     "noemailtext": "Este usuario non especificou un enderezo de correo electrónico válido.",
-    "nowikiemailtitle": "Sen correo electrónico habilitado",
     "nowikiemailtext": "Este usuario elixiu non recibir correos electrónicos doutros usuarios.",
     "emailnotarget": "O nome de usuario do destinatario non existe ou é incorrecto.",
     "emailtarget": "Introduza o nome de usuario do destinatario",
     "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",
     "watching": "Vixiando...",
     "unwatching": "Deixando de vixiar...",
     "watcherrortext": "Houbo un erro ao cambiar as súas opcións de vixilancia para a páxina \"$1\".",
-    "enotif_mailer": "Sistema de notificacións por correo de {{SITENAME}}",
     "enotif_reset": "Marcar todas as páxinas como visitadas",
     "enotif_impersonal_salutation": "Usuario de {{SITENAME}}",
     "enotif_subject_deleted": "{{GENDER:$2|$2}} borrou a páxina chamada \"$1\" en {{SITENAME}}",
     "excontent": "o contido era: \"$1\"",
     "excontentauthor": "o contido era: \"$1\" (e o único editor foi [[Special:Contributions/$2|$2]])",
     "exbeforeblank": "o contido antes do baleirado era: \"$1\"",
-    "exblank": "a páxina estaba baleira",
     "delete-confirm": "Borrar \"$1\"",
     "delete-legend": "Borrar",
     "historywarning": "'''Atención:''' A páxina que está a piques de borrar ten un historial con aproximadamente $1 {{PLURAL:$1|revisión|revisións}}:",
     "importunknownsource": "Fonte de importación descoñecida",
     "importcantopen": "Non se pode abrir o ficheiro importado",
     "importbadinterwiki": "Ligazón interwiki incorrecta",
-    "importnotext": "Baleiro ou sen texto",
     "importsuccess": "A importación rematou!",
-    "importhistoryconflict": "Existe un conflito no historial de revisións (se cadra, xa se importou esta páxina anteriormente)",
     "importnosources": "Non se defininiu ningunha fonte de importación transwiki e os envíos directos dos historiais están desactivados.",
     "importnofile": "Non se enviou ningún ficheiro de importación.",
     "importuploaderrorsize": "Fallou o envío do ficheiro de importación. O ficheiro é máis grande que o tamaño de envío permitido.",
     "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",
index 376f895..339c540 100644 (file)
     "disclaimers": "Chotraio",
     "disclaimerpage": "Project:Sadeo chotraio",
     "edithelp": "Sudarunk palov",
-    "helppage": "Help:Mozkur",
     "mainpage": "Mukhel Pan",
     "mainpage-description": "Mukhel Pan",
     "portal": "Somudaik proves-dar",
index 53ba295..f0c6be3 100644 (file)
     "disclaimers": "𐍅𐌰𐌳𐌾𐍉𐌱𐌹𐌻𐌰𐌲𐌴𐌹𐌽𐍃",
     "disclaimerpage": "Project:𐍅𐌰𐌳𐌾𐌹𐍃 𐌱𐌹𐌻𐌰𐌲𐌴𐌹𐌽𐍃",
     "edithelp": "𐌼𐌰𐌹𐌳𐌴𐌹𐌽𐌹𐌷𐌹𐌻𐍀𐌰",
-    "helppage": "Help:𐌷𐌰𐌿𐌱𐌹𐌳𐌰𐍃𐌴𐌹𐌳𐍉",
     "mainpage": "𐌷𐌰𐌿𐌱𐌹𐌳𐌰𐍃𐌴𐌹𐌳𐍉",
     "mainpage-description": "𐌷𐌰𐌿𐌱𐌹𐌳𐌰𐍃𐌴𐌹𐌳𐍉",
     "portal": "𐌱𐌰𐌿𐍂𐌲𐌹𐍃 𐌲𐌰𐍅𐌹",
index 69a242a..88225fe 100644 (file)
     "accountcreatedtext": "S Benutzerkonto fir [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|Diskussion]]) isch aagleit wore.",
     "createaccount-title": "Aalege vum e Benutzerkonto fir {{SITENAME}}",
     "createaccount-text": "Fir Dii isch e Benutzerkonto \"$2\" uf {{SITENAME}} ($4) aaglait wore. S Passwort fir \"$2\" , wu automatisch generiert woren isch, isch \"$3\". Du sottsch Di jetz aamälde un s Passwort ändere.\n\nWänn s Benutzerkonto us Versäh aaglait woren isch, chasch die Nochricht ignoriere.",
-    "usernamehasherror": "In Benutzernäme derf s kei Rautezeiche din haa",
     "login-throttled": "Du hesch z vilmol umesuscht versuecht, Di aazmälde. Bitte wart $1, voreb Du s non emol versuechsch.",
     "login-abort-generic": "Dyy Aamäldig isch nit erfolgryych gsii – Abbroche",
     "loginlanguagelabel": "Sproch: $1",
     "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-createaccount": "Nöis Benutzerkonto aalege",
     "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.",
     "prefs-skin": "Benutzeroberflechi",
     "skin-preview": "Vorschou",
     "datedefault": "kei Aagab",
-    "prefs-beta": "Betafunktione",
     "prefs-datetime": "Datum un Zyt",
     "prefs-labs": "Alphafunktione",
     "prefs-user-pages": "Benutzersyte",
     "upload-permitted": "Dateitype, wu erlaubt sin: $1.",
     "upload-preferred": "Dateitype, wu bevorzugt sin: $1.",
     "upload-prohibited": "Dateitype, wu nit erlaubt sin: $1.",
-    "uploadlog": "Datei-Logbuech",
     "uploadlogpage": "Dateie-Logbuech",
     "uploadlogpagetext": "Des isch s Logbuech vu dr uffegladene Dateie.\nLueg au d [[Special:NewFiles|Galerii vu neije Dateie]] fir e visuälle Iberblick.",
     "filename": "Dateiname",
     "filereuploadsummary": "Dateiänderige:",
     "filestatus": "Urheberrächts-Status:",
     "filesource": "Quälle:",
-    "uploadedfiles": "Uffegladeni Dateie",
     "ignorewarning": "Warnig ignoriere un d Datei spychere",
     "ignorewarnings": "Warnige ignoriere",
     "minlength1": "Dateinäme mien zmindescht e Buechstab lang syy.",
     "overwroteimage": "het e neiji Version vu „[[$1]]“ uffeglade",
     "uploaddisabled": "Uffelade deaktiviert",
     "copyuploaddisabled": "S Uffelade iber URL isch abschalte wore.",
-    "uploadfromurl-queued": "Dyy Uffeladig isch jetz in dr Warteschlang.",
     "uploaddisabledtext": "S Uffelade vu Dateie isch deaktiviert.",
     "php-uploaddisabledtext": "S Uffelade vu PHP-Dateie isch deaktiviert wore. Bitte iberprief d file_uploads-Yystellig.",
     "uploadscripted": "In däre Datei git s HTML- oder Scriptcode, wu fälschligerwyys vun eme Webbrowser usgfiert chennt were.",
     "upload-misc-error": "Nit bekannte Fähler bim Uffelade",
     "upload-misc-error-text": "Bim Uffelade isch e nit bekannte Fähler uftrette.\nPrief d URL uf Fähler un dr Online-Status vu dr Syte un versuech s no mol.\nWänn s Problem alno uftritt, informier e [[Special:ListUsers/sysop|Ammann]].",
     "upload-too-many-redirects": "In dr URL het s zvyl Wyterleitige",
-    "upload-unknown-size": "Nit bekannti Greßi",
     "upload-http-error": "E HTTP-Fähler isch ufträtte: $1",
     "upload-copy-upload-invalid-domain": "As Kopi uffeladbari Dateie sin iber die Domain nit verfiegbar.",
     "backend-fail-stream": "D Datei $1 het nit chenne ibertrait wäre.",
     "img-auth-streaming": "Am Lade vu „$1“.",
     "img-auth-public": "img_auth.php git Dateie vun eme privaten Wiki uus.\nDes Wiki isch as effentlig Wiki konfiguriert.\nUs Sicherheitsgrinde isch img_auth.php deaktiviert.",
     "img-auth-noread": "Benutzer derf „$1“ nit läse.",
-    "img-auth-bad-query-string": "D URL wyst e nit giltigi Abfrogzeichnefolg uf.",
     "http-invalid-url": "Nit giltigi URL: $1",
     "http-invalid-scheme": "URL mit em Schema „$1“ wäre nit unterstitzt",
     "http-request-error": "Fähler bim Verschicke vu dr Aafrog.",
     "filehist-dimensions": "Mäß",
     "filehist-filesize": "Dateigrößi",
     "filehist-comment": "Kommentar",
-    "filehist-missing": "Datei fählt",
     "imagelinks": "Verwändig vu dr Datei",
     "linkstoimage": "Di {{PLURAL:$1|Syte|$1 Sytene}} händ en Link zu dem Bild:",
     "linkstoimage-more": "Meh as {{PLURAL:$1|ei Syte verwyyst|$1 Syte verwyyse}} uf die Datei.\nDie Lischt zeigt nume {{PLURAL:$1|dr erscht Link|di erschte $1 Link}} uf die Datei.\nE [[Special:WhatLinksHere/$2|vollständigi Lischt]] isch verfiegbar.",
     "emailuser-title-notarget": "E-Mail an Benutzer",
     "emailpage": "E-Mail an Benutzer",
     "emailpagetext": "Du chasch {{GENDER:$1|em Benutzer|dr Benutzeri}} mit däm Formular e E-Mail schicke.\nAs Absender wird d E-Mail-Adräss us Dyyne [[Special:Preferences|Yystellige]] yytrait, ass {{GENDER:$1|dr Benutzer|d Benutzeri}} Dir cha Antwort gee.",
-    "usermailererror": "S Mail-Objekt het e Fähler zruckgee:",
     "defemailsubject": "{{SITENAME}}-E-Mail vum Benutzer „$1“",
     "usermaildisabled": "Benutzer-E-Mail abgstellt",
     "usermaildisabledtext": "Du chasch in däm Wiki kei E-Mail an anderi Benutzer schicke",
     "noemailtitle": "Kei e-Mail-Adrässe",
     "noemailtext": "Dää Benutzer het kei bstätigti E-Mail-Adräss aagee oder wet kei E-Mail vo andere Benutzer.",
-    "nowikiemailtitle": "Kei E-Mail Versand mögli",
     "nowikiemailtext": "De Benutzer möcht kei E-Mails vo andri Benutzer erhalte",
     "emailnotarget": "Benutzername fir dr Empfang vun ere E-Mail git s nit oder isch nit giltig.",
     "emailtarget": "Dr Benutzername vum Empfänger yygee",
     "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",
     "watching": "Am beobachte …",
     "unwatching": "Nümm am beobachten …",
     "watcherrortext": "Bim Ändere vu dr Beobachtigslischtenyystellige fir „$1“ het s e Fähler gee.",
-    "enotif_mailer": "{{SITENAME}} E-Mail-Benochrichtigungsdienscht",
     "enotif_reset": "Alli Syte as aagluegt markiere",
     "enotif_impersonal_salutation": "{{SITENAME}}-Benutzer",
     "enotif_subject_deleted": "{{SITENAME}}-Syte $1 isch vu {{GENDER:$2|$2}} glescht wore",
     "excontent": "Alter Inhalt: '$1'",
     "excontentauthor": "einzige Inhalt: '$1' (bearbeitet worde nume dür '$2')",
     "exbeforeblank": "Inhalt voreb d Syte gläärt woren isch: '$1'",
-    "exblank": "Syte isch läär gsi",
     "delete-confirm": "„$1“ lesche",
     "delete-legend": "Lesche",
     "historywarning": "'''Warnig:'''  Die Syte, wu Du wit lesche, het e Versionsgschicht mit schetzigswyys $1 {{PLURAL:$1|Version|Versione}}:",
     "importunknownsource": "Importquell isch unbekannt",
     "importcantopen": "D Importdatei het nit chenne ufgmacht wäre.",
     "importbadinterwiki": "Falscher Interwiki-Link",
-    "importnotext": "Leer oder kei Teggscht",
     "importsuccess": "Dr Import isch abgschlosse.",
-    "importhistoryconflict": "Es het scho ältri Versione wo mit dere kollidiere. Es isch mögli dass die Syte scho emool importiert worde isch.",
     "importnosources": "Für de Transwiki-Import sin kei Quelle definiert worde. Wege dem isch s direkte Ufelade vo Gschichtsversione gsperrt.",
     "importnofile": "Es isch kei Importdatei ufeglade worde.",
     "importuploaderrorsize": "S Ufelade vo dr Importdatei isch misslunge. D Datei isch grösser als erlaubt isch.",
     "hours": "{{PLURAL:$1|1 Stund|$1 Stunde}}",
     "days": "{{PLURAL:$1|1 Tag|$1 Täg}}",
     "ago": "vor $1",
+    "sunday-at": "Sunntig am $1",
+    "yesterday-at": "Geschtert am $1",
     "bad_image_list": "Format:\n\nNume Zylene, wo mit emne * afö, wärde berücksichtigt.\nNach em * mues zersch e Link zuren Unerwünschte Datei cho.\nWyteri Links uf der glyche Zyle wärden als Usnahme behandlet, wo die Datei trotzdäm darff vorcho.",
     "metadata": "Metadate",
     "metadata-help": "Die Datei het wyteri Informatione, allwäg vor Digitalkamera oder vom Scanner wo se het gschaffe.\nWe die Datei isch veränderet worde, de cha's sy, das die zuesätzlechi Information für di verändereti Datei nümm richtig zuetrifft.",
     "imgmultipagenext": "nächschti Syte →",
     "imgmultigo": "Gang!",
     "imgmultigoto": "Gang uf Syte $1",
+    "img-lang-default": "(Standardsproch)",
+    "img-lang-info": "Des Bild in $1 rendere. $2",
+    "img-lang-go": "Gang",
     "ascending_abbrev": "uf",
     "descending_abbrev": "ab",
     "table_pager_next": "Näggschti Syte",
     "version-hook-subscribedby": "Ufruef vu",
     "version-version": "(Version $1)",
     "version-license": "Lizänz",
+    "version-ext-license": "Lizänz",
+    "version-ext-colheader-name": "Erwyterig",
+    "version-ext-colheader-license": "Lizänz",
+    "version-ext-colheader-description": "Bschryybig",
+    "version-ext-colheader-credits": "Autore",
+    "version-license-title": "Lizänz fir $1",
+    "version-license-not-found": "S sin keini detaillierte Lizänzinformatione fir die Erwyterig gfunde wore.",
+    "version-credits-title": "Danksagige fir $1",
+    "version-credits-not-found": "S sin keini detaillierte Danksagigsinformatione fir die Erwyterig gfunde wore.",
     "version-poweredby-credits": "Die Websyte nutzt '''[https://www.mediawiki.org/wiki/MediaWiki/de MediaWiki]''', Copyright © 2001–$1 $2.",
     "version-poweredby-others": "anderi",
+    "version-poweredby-translators": "Ibersetzer vu translatewiki.net",
     "version-credits-summary": "Mir danke däne Lyt fir ihri Bytreg zue [[Special:Version|MediaWiki]].",
     "version-license-info": "MediaWiki isch e freji Software, d. h. s cha, no dr Bedingige vu dr GNU General Public-Lizänz, wu vu dr Free Software Foundation vereffentligt woren isch, wyterverteilt un/oder modifiziert wäre. Doderbyy cha d Version 2, oder no eigenem Ermässe, jedi nejeri Version vu dr Lizänz brucht wäre.\n\nDes Programm wird in dr Hoffnig verteilt, ass es nitzli isch, aber OHNI JEDI GARANTI un sogar ohni di impliziert Garanti vun ere MÄRTGÄNGIGKEIT oder EIGNIG FIR E BSTIMMTE ZWÄCK. Doderzue git meh Hiiwys in dr GNU General Public-Lizänz.\n\nE [{{SERVER}}{{SCRIPTPATH}}/COPYING Kopi vu dr GNU General Public-Lizänz] sott zämme mit däm Programm verteilt wore syy. Wänn des nit eso isch, cha ne Kopi bi dr Free Software Foundation Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA, schriftli aagforderet oder [//www.gnu.org/licenses/old-licenses/gpl-2.0.html online gläse] wäre.",
     "version-software": "Installierti Software",
     "version-entrypoints": "Yygangspunkt-URL",
     "version-entrypoints-header-entrypoint": "Yygangspunkt",
     "version-entrypoints-header-url": "URL",
+    "redirect": "Wyterleitig uf Benutzersyte, Syte, Syteversion oder Datei",
+    "redirect-legend": "Wyterleitig uf e Datei oder e Syte",
+    "redirect-summary": "Die Spezialsyte leitet wyter uf e Benutzersyte (numerischi Benutzerkännig aagee), Syte (Sytekännig aagee), Syteversion (Versionskännig aagee) oder Datei (Dateiname aagee). Benutzig: [[{{#Special:Redirect}}/user/101]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]] oder [[{{#Special:Redirect}}/file/Example.jpg]].",
+    "redirect-submit": "Gang",
+    "redirect-lookup": "Sueche:",
+    "redirect-value": "Wärt:",
+    "redirect-user": "Benutzer-ID",
+    "redirect-page": "Syten-ID",
+    "redirect-revision": "Syteversion",
+    "redirect-file": "Dateiname",
+    "redirect-not-exists": "Wärt nit gfunde",
     "fileduplicatesearch": "Datei-Duplikat sueche",
     "fileduplicatesearch-summary": "Suech no Datei-Duplikat uf dr Grundlag vu ihrem Hash-Wärt.",
     "fileduplicatesearch-legend": "No Duplikat sueche",
     "fileduplicatesearch-result-n": "D Datei „$1“ het {{PLURAL:$2|1 identisch Duplikat|$2 identischi Duplikat}}.",
     "fileduplicatesearch-noresults": "S isch kei Datei mit em Name „$1“ gfunde wore.",
     "specialpages": "Spezialsytene",
-    "specialpages-note": "* Reguläri Spezialsyte\n* <span class=\"mw-specialpagerestricted\">Zuegriffsbschränkti Spezialsyte</span>\n* <span class=\"mw-specialpagecached\">Gecachti Spezialsyte (dr Inhalt ist villicht veraltet.)</span>",
+    "specialpages-note-top": "Zeichenerklärig:",
+    "specialpages-note": "* Normali Spezialsyte.\n* <span class=\"mw-specialpagerestricted\">Spezialsyte mit bschränktem Zuegang.</span>",
     "specialpages-group-maintenance": "Wartigslischte",
     "specialpages-group-other": "Andri Spezialsyte",
     "specialpages-group-login": "Aamälde/Konto aalege",
     "tags": "Änderigs-Tag priefe",
     "tag-filter": "[[Special:Tags|Markierigs]]filter:",
     "tag-filter-submit": "Filter",
+    "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|Markierig|Markierige}}]]: $2)",
     "tags-title": "Tag",
     "tags-intro": "Die Syte zeigt alli Tag, wu Bearbeitige mit markiert wäre un derzue d Bedytig vun ene.",
     "tags-tag": "Markierigsname",
     "tags-display-header": "Benännig uf dr Änderigslischte",
     "tags-description-header": "Vollständigi Bschryybig",
     "tags-hitcount-header": "Markierti Änderige",
+    "tags-active-yes": "Jo",
+    "tags-active-no": "Nei",
     "tags-edit": "bearbeite",
     "tags-hitcount": "$1 {{PLURAL:$1|Änderig|Änderige}}",
     "comparepages": "Syte verglyyche",
     "dberr-problems": "Excusez! Die Seite het im Momänt tächnischi Schwirigkeite.",
     "dberr-again": "Wart e paar Minute un lad derno nej.",
     "dberr-info": "(Cha kei Verbindig zum Datebank-Server härstelle: $1)",
+    "dberr-info-hidden": "(Cha kei Verbindig zum Datebank-Server härstelle)",
     "dberr-usegoogle": "Du chenntsch in dr Zwischezyt mit Google sueche.",
     "dberr-outofdate": "Obacht: Dr Suechindex vu unsere Syte chennt veraltet syy.",
     "dberr-cachederror": "Des isch e Kopii vum Cache vu dr Syte, wu Du aagforderet hesch, un chennt veraltet syy.",
     "htmlform-submit": "Ibertrage",
     "htmlform-reset": "Änderige ruckgängig mache",
     "htmlform-selectorother-other": "Anderi",
+    "htmlform-no": "Nei",
+    "htmlform-yes": "Jo",
+    "htmlform-chosen-placeholder": "Wehl en Option",
     "sqlite-has-fts": "$1 mit Unterstitzig vu dr Volltextsuechi",
     "sqlite-no-fts": "$1 ohni Unterstitzig vu dr Volltextsuechi",
     "logentry-delete-delete": "$1 het d Syte $3 glöscht",
index 011b1a7..aee8136 100644 (file)
     "accountcreatedtext": "[[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|talk]]) માટે સભ્ય ખાતું બનાવવામાં આવ્યું છે.",
     "createaccount-title": "{{SITENAME}} માટે ખાતુ બનાવ્યું",
     "createaccount-text": "કોઇકે {{SITENAME}} ($4) પર, નામ \"$2\", ગુપ્તસંજ્ઞા \"$3\", શાથે તમારા ઇ-મેઇલ એડ્રેસ માટે ખાતુ બનાવેલ છે.\n\nતમે હવે પ્રવેશ કરી અને ગુપ્તસંજ્ઞા બદલી શકો છો.\n\nજો આ ખાતુ ભુલથી બનેલું હોય તો,આ સંદેશને અવગણી શકો છો.",
-    "usernamehasherror": "સભ્યનામમાં ગડબડિયા ચિહ્નો ન હોઈ શકે",
     "login-throttled": "તમે હાલમાં ઘણાં જ પ્રવેશ પ્રયત્નો કર્યા છે.\nકૃપા કરી ફરી પ્રયત્ન કરતાં પહેલાં $1 રાહ જુઓ.",
     "login-abort-generic": "તમારું પ્રવેશ નિષ્ફળ થયું - છોડી દેવાયું",
     "loginlanguagelabel": "ભાષા: $1",
     "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",
     "upload-permitted": "રજામંદ ફાઈલ પ્રકારો: $1.",
     "upload-preferred": "ઈચ્છીત ફાઈલ પ્રકારો: $1.",
     "upload-prohibited": "પ્રતિબંધીત ફાઈલ પ્રકારો: $1.",
-    "uploadlog": "ચઢાવેલી ફાઇલોનું માહિતિ પત્રક",
     "uploadlogpage": "ચઢાવેલી ફાઇલોનું માહિતિ પત્રક",
     "uploadlogpagetext": "નીચે હાલમાં ચડાવેલી ફાઇલોની યાદી છે.\nવધુ ફાઇલો દ્રશમાન કરવા [[Special:NewFiles|gallery of new files]] જુઓ",
     "filename": "ફાઇલ નામ",
     "filereuploadsummary": "ફાઈલ ફેરફારો",
     "filestatus": "પ્રકાશનાધિકાર સ્થિતિ",
     "filesource": "સ્રોત:",
-    "uploadedfiles": "ફાઇલ ચડાવો",
     "ignorewarning": "ચેતવણીને અવગણી ને પણ ફાઇલ સાચવો",
     "ignorewarnings": "કોઇ પણ ચેતવણી અવગણો",
     "minlength1": "ફાઇલ નામની લંબાઇ કમ સે કમ એક અક્ષર જેટલી તો હોવી જ જોઇએ.",
     "overwroteimage": " \"[[$1]]\" ની નવી આવૃત્તિ ચઢાવો.",
     "uploaddisabled": "ફાઇલ ચઢાવ પ્રતિબંધિત",
     "copyuploaddisabled": "URL દ્વાર ફાઇલ ચઢાવ પ્રતિબંધિત",
-    "uploadfromurl-queued": "તમારી ચઢાવેલી ફાઇલ કતારમાં ઉમેરાઇ છે.",
     "uploaddisabledtext": "ફાઇલ ચઢાવવું નિષ્ક્રીય બનાવ્યું છે",
     "php-uploaddisabledtext": "PHPમાં ફાઇલ અપલોડ નિષ્ક્રીય કરી દેવાયો છે.\nફાઇલ ચડાવવાના વિકલ્પ ફરી તપાસો.",
     "uploadscripted": "આ ફાઇલ HTML કે અન્ય સ્ક્રીપ્ટ કોડ ધરાવે છે જે વેબ બ્રાઉઝર દ્વારા ભૂલથી ઉપયોગમાં લઇ શકાય છે.",
     "upload-misc-error": "અજ્ઞાત ફાઇલ ચડાવ ચૂક",
     "upload-misc-error-text": "ફાઈલ ચડાવતી વખતે કાંઇક ત્રુટિ રહી ગઇ.\nખાત્રી કરો કે URL વૈધ છે અને સક્રીય છે અને ફરી પ્રયત્ન કરો.\nતેમ છતાં પણ  પ્રોબ્લેમ રહે તો અહીં સંપર્ક કરશો [[Special:ListUsers/sysop|administrator]].",
     "upload-too-many-redirects": "URLમાં ઘણાં ઉપ નિર્દેશનો છે.",
-    "upload-unknown-size": "અજ્ઞાત કદ",
     "upload-http-error": " HTTP ત્રુટિ : $1",
     "upload-copy-upload-invalid-domain": "આ વેબસાઇટ પરથી ફાઈલ નહીં ચડાવાય.",
     "backend-fail-stream": "ફાઈલ $1 ને લાવી ન શકાઈ.",
     "img-auth-streaming": "ચિત્ર માહીતી  \"$1\" ઉતરી રહી છે.",
     "img-auth-public": "img_auth.php દ્વારા કાર્યાન્વીત થતી ક્રિયા નીજી વિકિ માંથી ફાઇલ કાઢવા વપરાય છે. \nઆ વિકિ ની ગોઠવણ જન વિકી તરીકે થયેલી છે.\nમહત્તમ સુરક્ષા માટે, img_auth.php ને નિષ્ક્રિય કરાઇ છે.",
     "img-auth-noread": "\"$1\" વાંચવાને સભ્યને પરવાનગી નથી.",
-    "img-auth-bad-query-string": "આ URL માં અમાન્ય ક્વેરી શબ્દમાળા છે",
     "http-invalid-url": "અવૈધ URL: $1",
     "http-invalid-scheme": "$1 પદ્ધતિના URLs અહીં ચાલતી નથી",
     "http-request-error": "અજ્ઞાત ત્રુટીને કારણે HTTP અરજી નિષ્ફળ",
     "filehist-dimensions": "પરિમાણો",
     "filehist-filesize": "ફાઇલનું કદ",
     "filehist-comment": "ટિપ્પણી",
-    "filehist-missing": "ફાઇલ ગાયબ",
     "imagelinks": "ફાઇલનો વપરાશ",
     "linkstoimage": "આ ફાઇલ સાથે {{PLURAL:$1|નીચેનું પાનું જોડાયેલું|$1 નીચેનાં પાનાઓ જોડાયેલાં}} છે",
     "linkstoimage-more": "$1 કરતાં વધુ {{PLURAL:$1|પાનું|પાનાં}} આ ફાઇલ સાથે જોડાય છે.\nનીચે જણાવેલ યાદી ફક્ત આ ફાઇલ સાથે જોડાયેલ {{PLURAL:$1|પ્રથમ પાનાની કડી|પ્રથમ $1 પાનાંની કડીઓ}} બતાવે છે.\nઅહીં [[Special:WhatLinksHere/$2|પુરી યાદી]]  મળશે.",
     "emailuser-title-notarget": "ઇ-મેલ વપરાશકર્તા",
     "emailpage": "ઈ-મેલ સભ્ય",
     "emailpagetext": "તમે નીચે દર્શાવેલ ફોર્મ વાપરી આ {{GENDER:$1|સભ્ય}}ને ઇ-મેલ મોકલી શકો છો.\nતમે [[Special:Preferences|તમારી પસંદમાં]] જે ઇ-મેલ લખ્યો હશે તે \"દ્વારા\"ના નામ હેઠળ દેખાશે, જેથી ઇ-મેલ મેળવનાર તમને સંદેશાનો જવાબ આપી શકશે.",
-    "usermailererror": "મેલ વસ્તુ પાઠવવામાં ત્રુટિ",
     "defemailsubject": "{{SITENAME}} સભ્ય $1 તરફથી ઈ-મેલ",
     "usermaildisabled": "સભ્યનો ઈ-મેલ નિષ્ક્રિય કરાયો",
     "usermaildisabledtext": "તમે આ વિકિ પર અન્ય સભ્યોને ઇ-મેલ મોકલી ન શકો",
     "noemailtitle": "ઈ-મેલ એડ્રેસ નથી",
     "noemailtext": "આ સભ્યએ  વૈધ ઇ-મેલ સરનામું નથી આપ્યું.",
-    "nowikiemailtitle": "કોઇ પણ ઇ મેલની રજા નથી",
     "nowikiemailtext": "અન્ય સભ્યો ઇ-મેલ ન મોકલે તેવી આ સભ્યની પસંદગી છે.",
     "emailnotarget": "પ્રાપ્તકર્તા માટે બિન-હયાત અથવા અમાન્ય વપરાશકર્તા નામ.",
     "emailtarget": "પ્રાપ્તકર્તા નું સભ્યનામ દાખલ કરો",
     "nowatchlist": "તમારી ધ્યાન સૂચિ ખાલી છે",
     "watchlistanontext": "તમારી ધ્યાનસૂચિની વસ્તુઓ જોવા અને ફેરફાર કરવા $1 કરો",
     "watchnologin": "પ્રવેશ કરેલ નથી",
-    "watchnologintext": "ધ્યાનસૂચિમાં ફેરફારાકરવા તમે પ્રવેશ [[Special:UserLogin|logged in]] કરેલો હોવો જરૂરી છે.",
     "addwatch": "ધ્યાનસૂચિ માં ઉમેરો",
     "addedwatchtext": "પાનું \"[[:$1]]\" તમારી [[Special:Watchlist|ધ્યાનસૂચિ]]માં ઉમેરાઈ ગયું છે.\nભવિષ્યમાં આ પાના અને તેનાં સંલગ્ન ચર્ચાનાં પાનામાં થનારા ફેરફારોની યાદી ત્યાં આપવામાં આવશે.",
     "removewatch": "ધ્યાનસૂચિમાંથી કાઢી નાખો",
     "watching": "નજર રાખી રહ્યાં છો...",
     "unwatching": "નજર રાખવાની બંધ કરી છે...",
     "watcherrortext": "તમારી ધ્યાનસૂચિ નાં સેટિંગ્સ માં \"$1\" માં ફેરફાર કરતી વખતે ભૂલ આવી.",
-    "enotif_mailer": "{{SITENAME}} સૂચના ઈ-મેલ પ્રેષક",
     "enotif_reset": "બધા પાનાને મુલાકાત લેવાયેલા અંકિત કરો",
     "enotif_impersonal_salutation": "{{SITENAME}} સભ્ય",
     "enotif_subject_deleted": "{{SITENAME}} પૃષ્ઠ $1 {{gender:$2|$2}}એ દૂર કર્યું છે",
     "excontent": "આટલી જ માહિતી હતી: \"$1\"",
     "excontentauthor": "માત્ર આજ માહિતી હતી : \"$1\" (અને યોગદાન કરનાર માત્ર \"[[Special:Contributions/$2|$2]]\" જ હતા)",
     "exbeforeblank": "આ પાનું ભૂંસતા પહેલા તેમાં આ શબ્દો હતાં: $1",
-    "exblank": "પાનું ખાલી હતું",
     "delete-confirm": "$1ને ભૂસી નાંખો.",
     "delete-legend": "રદ કરો",
     "historywarning": "'''ચેતવણી:''' જે પાનું તમે હટાવવા જઇ રહ્યાં છો તેને આશરે $1 {{PLURAL:$1|પુનરાવર્તન|પુનરાવર્તનો}}નો ઇતિહાસ છે:",
     "importunknownsource": "અજ્ઞાત આયાતી સ્રોત પ્રકાર",
     "importcantopen": "આયાતી ફાઈલ નાખોલી શકાઈ",
     "importbadinterwiki": "ખરાબ આંતરીકા વિકિ કડી",
-    "importnotext": "ખાલી કે શબ્દ વિહીન",
     "importsuccess": "આયાત સંપૂર્ણ",
-    "importhistoryconflict": "એક બીજાથી વિસંગત ફેરફારો અસ્તિત્વ ધરાવે છે ( કદાક આ પાનું પહેલાં આયાત કરાયું હોય)",
     "importnosources": "કોઇ પણ આંતર વિકિ સ્રોત જણાવાયા નથી અને સીધા ઇતિહાસ ફાઇલ ચડાવવા પર રોક લાગેલી છે.",
     "importnofile": "કોઇ પણ આયાતી ફાઇલ ન ચડાવી શકાઇ",
     "importuploaderrorsize": "આયાતી ફાઇલ ચડાવવાનું અસફળ\nમંજૂર કદ કરતા આ ફાઈલાનું કદ મોટું છે.",
index 8ae4767..dafdb28 100644 (file)
     "disclaimers": "Hattara",
     "disclaimerpage": "Project:Babban gargaɗi",
     "edithelp": "Taimako kan gyara",
-    "helppage": "Help:Tsaraba",
     "mainpage": "Marhabin",
     "privacy": "Manufar kare sirri",
     "privacypage": "Project:Manufar kare sirri",
index ae5a06e..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": "監視",
index a5a4e6c..a378633 100644 (file)
     "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",
     "filedesc": "Hōʻuluʻulu manaʻo",
     "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]]\"",
     "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",
     "filehist-dimensions": "Nā Nui",
     "filehist-filesize": "Nui o ka waihona",
     "filehist-comment": "Kaumanaʻo",
-    "filehist-missing": "Nele ka waihona",
     "imagelinks": "Nā Hana waihona",
     "linkstoimage": "Loulou {{PLURAL:$1|kekahi ‘ao‘ao|kēia mau ‘ao‘ao $1}} i kēia waihona:",
     "nolinkstoimage": "ʻAʻohe ʻaoʻao e loulou i kēia waihona.",
index 0804816..c2b0d37 100644 (file)
     "permalink": "קישור קבוע",
     "print": "גרסה להדפסה",
     "view": "צפייה",
+    "view-foreign": "הצגה ב{{GRAMMAR:תחילית|$1}}",
     "edit": "עריכה",
+    "edit-local": "עריכת התיאור המקומי",
     "create": "יצירה",
+    "create-local": "הוספת תיאור מקומי",
     "editthispage": "עריכת דף זה",
     "create-this-page": "יצירת דף זה",
     "delete": "מחיקה",
     "accountcreatedtext": "חשבון המשתמש [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|שיחה]]) נוצר.",
     "createaccount-title": "יצירת חשבון ב{{grammar:תחילית|{{SITENAME}}}}",
     "createaccount-text": "מישהו יצר חשבון בשם $2 ב{{grammar:תחילית|{{SITENAME}}}} ($4), והסיסמה הזמנית של החשבון היא \"$3\". עליכם להיכנס ולשנות עכשיו את הסיסמה.\n\nבאפשרותכם להתעלם מהודעה זו, אם החשבון נוצר בטעות.",
-    "usernamehasherror": "שם משתמש אינו יכול לכלול תווי סולמית",
     "login-throttled": "ביצעתם לאחרונה ניסיונות רבים מדי להיכנס לחשבון זה.\nאנא המתינו $1 לפני שתנסו שוב.",
     "login-abort-generic": "הכניסה לחשבון לא הצליחה - היא הופסקה",
     "loginlanguagelabel": "שפה: $1",
     "prefs-skin": "עיצוב",
     "skin-preview": "תצוגה מקדימה",
     "datedefault": "ברירת המחדל",
-    "prefs-beta": "אפשרויות בטא",
     "prefs-datetime": "תאריך ושעה",
     "prefs-labs": "אפשרויות מעבדה",
     "prefs-user-pages": "דפי משתמש",
     "upload-permitted": "סוגי קבצים מותרים: $1.",
     "upload-preferred": "סוגי קבצים מומלצים: $1.",
     "upload-prohibited": "סוגי קבצים אסורים: $1.",
-    "uploadlog": "יומן העלאות קבצים",
     "uploadlogpage": "יומן העלאות",
     "uploadlogpagetext": "להלן רשימה של העלאות הקבצים האחרונות שבוצעו.\nראו את [[Special:NewFiles|גלריית הקבצים החדשים]] להצגה ויזואלית שלהם.",
     "filename": "שם הקובץ",
     "filereuploadsummary": "השינויים בקובץ:",
     "filestatus": "מעמד זכויות יוצרים:",
     "filesource": "מקור:",
-    "uploadedfiles": "קבצים שהועלו",
     "ignorewarning": "התעלמות מהאזהרה ושמירת הקובץ בכל זאת",
     "ignorewarnings": "התעלמות מכל האזהרות",
     "minlength1": "שמות קבצים צריכים להיות בני תו אחד לפחות.",
     "overwroteimage": "העלה גרסה חדשה של הקובץ [[$1]]",
     "uploaddisabled": "העלאת קבצים מבוטלת.",
     "copyuploaddisabled": "העלאת קבצים מכתובת URL מבוטלת.",
-    "uploadfromurl-queued": "העלאתכם הועברה לתור המשימות.",
     "uploaddisabledtext": "אפשרות העלאת הקבצים מבוטלת.",
     "php-uploaddisabledtext": "אפשרות העלאת הקבצים מבוטלת ברמת PHP. אנא בדקו את ההגדרה file_uploads.",
     "uploadscripted": "הקובץ כולל קוד סקריפט או HTML שעשוי להתפרש או להתבצע בטעות על ידי הדפדפן.",
     "upload-misc-error": "שגיאת העלאה בלתי ידועה",
     "upload-misc-error-text": "שגיאת העלאה בלתי ידועה התרחשה במהלך ההעלאה.\nאנא ודאו שכתובת ה־URL תקינה וזמינה ונסו שוב.\nאם הבעיה חוזרת על עצמה, אנא צרו קשר עם [[Special:ListUsers/sysop|מפעיל מערכת]].",
     "upload-too-many-redirects": "הכתובת מכילה הפניות רבות מדי",
-    "upload-unknown-size": "גודל בלתי ידוע",
     "upload-http-error": "התרחשה שגיאת HTTP‏: $1",
     "upload-copy-upload-invalid-domain": "העלאת קבצים משרת זה אינה אפשרית.",
     "backend-fail-stream": "לא הייתה אפשרות להזרים את הקובץ \"$1\".",
     "img-auth-streaming": "מבצע הזרמה של \"$1\".",
     "img-auth-public": "img_auth.php משמש להצגת קבצים מתוך אתר ויקי פרטי.\nאתר ויקי זה מוגדר כציבורי.\nכדי להשיג אבטחה מרבית, img_auth.php מבוטל.",
     "img-auth-noread": "למשתמש אין הרשאה לקרוא את \"$1\".",
-    "img-auth-bad-query-string": "לכתובת ה־URL יש מחרוזת פרמטרים בלתי תקינה.",
     "http-invalid-url": "כתובת URL בלתי תקינה: $1",
     "http-invalid-scheme": "כתובות URL מהסוג \"$1\" אינן נתמכות.",
     "http-request-error": "בקשת ה־HTTP נכשלה עקב שגיאה בלתי ידועה.",
     "filehist-dimensions": "ממדים",
     "filehist-filesize": "גודל הקובץ",
     "filehist-comment": "הערה",
-    "filehist-missing": "הקובץ חסר",
     "imagelinks": "שימוש בקובץ",
     "linkstoimage": "{{PLURAL:$1|הדף הבא משתמש|הדפים הבאים משתמשים}} בקובץ זה:",
     "linkstoimage-more": "יותר {{PLURAL:$1|מדף אחד מקשר|מ־$1 דפים מקשרים}} לקובץ זה.\nהרשימה הבאה מראה רק את {{PLURAL:$1|הדף הראשון שמקשר|$1 הדפים הראשונים שמקשרים}} לקובץ זה.\nניתן לצפות ב[[Special:WhatLinksHere/$2|רשימה המלאה]].",
     "listgrouprights-removegroup-self": "הסרת {{PLURAL:$2|הקבוצה|הקבוצות}} מהחשבון האישי: $1",
     "listgrouprights-addgroup-self-all": "הוספת כל הקבוצות לחשבון האישי",
     "listgrouprights-removegroup-self-all": "הסרת כל הקבוצות מהחשבון האישי",
+    "listgrouprights-namespaceprotection-header": "הגבלות על מרחבי שם",
+    "listgrouprights-namespaceprotection-namespace": "מרחב השם",
+    "listgrouprights-namespaceprotection-restrictedto": "ההרשאה או ההרשאות המאפשרות למשתמשים לערוך",
     "trackingcategories": "קטגוריות מעקב",
     "trackingcategories-summary": "דף זה כולל רשימה של קטגוריות מעקב, שנוצרות אוטומטית על־ידי תוכנת מדיה‏‏֫־ויקי. ניתן לשנות את שמותיהן על‏‏֫־ידי שינוי הודעות המערכת הרלוונטיות במרחב השם \"{{ns:8}}\".",
     "trackingcategories-msg": "קטגוריית מעקב",
     "trackingcategories-name": "שם ההודעה",
     "trackingcategories-desc": "הקריטריון להכללה בקטגוריה",
-    "noindex-category-desc": "×\94×\93×£ ×\9b×\95×\9c×\9c ×\90ת ×\9e×\99×\9cת ×\94קס×\9d <nowiki>__×\9c×\90\9c×\97×\99פ×\95ש__</nowiki> (×\95×\94×\95×\90 ×\91×\9eר×\97×\91 ×©×\9d ×©×\91×\95 ×\93×\92×\9c ×\9b×\96×\94 ×\9e×\95תר ×\9cש×\99×\9e×\95ש), ×\95×\9c×\9b×\9f ×\90×\99× ×\95 ×\9e×\90×\95× ×\93קס ×¢×\9câ\80\8fâ\80\8fÖ«Ö¾×\99×\93×\99 ×¨×\95×\91×\95×\98×\99×\9d.",
-    "index-category-desc": "הדף כולל את מילת הקסם <nowiki>__לחיפוש__</nowiki> (והוא במרחב שם שבו דגל כזה מותר לשימוש), ולכן הוא מאונדקס על‏‏֫־ידי רובוטים אף שכברירת מחדל הוא לא היה מאונדקס על ידם.",
-    "post-expand-template-inclusion-category-desc": "לאחר הרחבת כל התבניות, גודל הדף גדול מ‏‏֫־$wgMaxArticleSize, ולכן מספר תבניות אינן מורחבות.",
-    "post-expand-template-argument-category-desc": "לאחר הרחבת ארגומנט של תבנית (משהו בסוגריים משולשים, כגון {{{Foo}}}), הדף גדול מ‏‏֫‏‏֫־$wgMaxArticleSize.",
+    "noindex-category-desc": "×\94×\93×£ ×\90×\99× ×\95 ×\9e×\90×\95× ×\93קס ×¢×\9câ\80\8fâ\80\8fÖ¾×\99×\93×\99 ×¨×\95×\91×\95×\98×\99×\9d ×\9b×\99×\95×\95×\9f ×©×\94×\95×\90 ×\9b×\95×\9c×\9c ×\90ת ×\9e×\99×\9cת ×\94קס×\9d <code><nowiki>__NOINDEX__</nowiki></code> ×\95×\94×\95×\90 ×\91×\9eר×\97×\91 ×©×\9d ×©×\91×\95 ×\93×\92×\9c ×\9b×\96×\94 ×\9e×\95תר ×\9cש×\99×\9e×\95ש.",
+    "index-category-desc": "הדף כולל את מילת הקסם <code><nowiki>__INDEX__</nowiki></code> (והוא במרחב שם שבו דגל כזה מותר לשימוש), ולכן הוא מאונדקס על‏‏֫־ידי רובוטים אף שכברירת מחדל הוא לא היה מאונדקס על ידם.",
+    "post-expand-template-inclusion-category-desc": "לאחר הרחבת כל התבניות, גודל הדף גדול מ‏‏֫־<code>$wgMaxArticleSize</code>, ולכן מספר תבניות אינן מורחבות.",
+    "post-expand-template-argument-category-desc": "לאחר הרחבת ארגומנט של תבנית (משהו בסוגריים משולשים, כגון <code>{{{Foo}}})</code>, הדף גדול מ‏‏֫‏‏֫־<code>$wgMaxArticleSize</code>.",
     "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>, שגורמת לה לא להופיע בתיבת קישורי הקטגוריות בדפים כברירת מחדל.",
     "emailuser-title-notarget": "שליחת דוא\"ל למשתמש",
     "emailpage": "שליחת דואר למשתמש",
     "emailpagetext": "ניתן להשתמש בטופס כדי לשלוח הודעת דואר אלקטרוני {{GENDER:$1|למשתמש זה|למשתמשת זו}}.\nכתובת הדואר האלקטרוני שכתבתם ב[[Special:Preferences|העדפות המשתמש שלכם]] תופיע ככתובת שההודעה נשלחה ממנה, כדי לאפשר תגובה ישירה.",
-    "usermailererror": "אובייקט הדואר החזיר שגיאה:",
     "defemailsubject": "דוא\"ל מ{{grammar:תחילית|{{SITENAME}}}} מהמשתמש \"$1\"",
     "usermaildisabled": "שליחת דוא\"ל למשתמשים מבוטלת",
     "usermaildisabledtext": "אינכם רשאים לשלוח דואר אלקטרוני למשתמשים אחרים באתר זה",
     "noemailtitle": "אין כתובת דואר אלקטרוני",
     "noemailtext": "משתמש זה לא הזין כתובת דואר אלקטרוני תקינה.",
-    "nowikiemailtitle": "שליחת דוא\"ל אינה אפשרית",
     "nowikiemailtext": "משתמש זה בחר שלא לקבל דואר אלקטרוני ממשתמשים אחרים.",
     "emailnotarget": "שם המשתמש של הנמען לא קיים או בלתי תקין.",
     "emailtarget": "הקלידו את שם המשתמש של הנמען",
     "nowatchlist": "אין דפים ברשימת המעקב.",
     "watchlistanontext": "עליכם $1 כדי לצפות או לערוך פריטים ברשימת המעקב.",
     "watchnologin": "לא נכנסת לחשבון",
-    "watchnologintext": "עליכם [[Special:UserLogin|להיכנס לחשבון]] כדי לערוך את רשימת המעקב.",
     "addwatch": "הוספה לרשימת המעקב",
     "addedwatchtext": "הדף [[:$1]] נוסף ל[[Special:Watchlist|רשימת המעקב]].\nשינויים שייערכו בעתיד בדף זה ובדף השיחה שלו, יוצגו ברשימת המעקב.",
     "removewatch": "הסרה מרשימת המעקב",
     "watching": "בהוספה לרשימת המעקב…",
     "unwatching": "בהסרה מרשימת המעקב…",
     "watcherrortext": "אירעה שגיאה בעת שינוי הגדרות רשימת המעקב של \"$1\".",
-    "enotif_mailer": "הודעות {{SITENAME}}",
     "enotif_reset": "סימון כל הדפים כאילו נצפו",
     "enotif_impersonal_salutation": "משתמש של {{SITENAME}}",
     "enotif_subject_deleted": "הדף $1 ב{{grammar:תחילית|{{SITENAME}}}} נמחק על ידי $2",
     "excontent": "התוכן היה: \"$1\"",
     "excontentauthor": "התוכן היה: \"$1\" ({{GENDER:$2|והתורם היחיד היה|והתורמת היחידה הייתה}} \"[[Special:Contributions/$2|$2]]\")",
     "exbeforeblank": "התוכן לפני שרוקן היה: \"$1\"",
-    "exblank": "הדף היה ריק",
     "delete-confirm": "מחיקת $1",
     "delete-legend": "מחיקה",
     "historywarning": "'''אזהרה:''' לדף שאתם עומדים למחוק יש היסטוריית שינויים של {{PLURAL:$1|גרסה אחת|$1 גרסאות}}:",
     "importunknownsource": "סוג ייבוא בלתי ידוע",
     "importcantopen": "פתיחת קובץ הייבוא נכשלה",
     "importbadinterwiki": "קישור בינוויקי שגוי",
-    "importnotext": "ריק או חסר טקסט",
     "importsuccess": "הייבוא הושלם בהצלחה!",
-    "importhistoryconflict": "ישנה התנגשות עם ההיסטוריה הקיימת של הדף (ייתכן שהדף יובא בעבר)",
     "importnosources": "אין מקורות לייבוא בין־אתרי, וייבוא ישיר של דף עם היסטוריה אינו מאופשר כעת.",
     "importnofile": "לא הועלה קובץ ייבוא.",
     "importuploaderrorsize": "העלאת קובץ הייבוא נכשלה. הקובץ היה גדול יותר מגודל ההעלאה המותר.",
index 38d3b53..a357506 100644 (file)
     "accountcreatedtext": "[[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|वार्ता]]) के लिये खाता निर्मित कर दिया गया है।",
     "createaccount-title": "{{SITENAME}} के लिये खाता बनाएँ",
     "createaccount-text": "आपके ई-मेल पते के लिये किसी ने {{SITENAME}} ($4) पर \"$2\" सदस्य नाम से \"$3\" कूटशब्द (पासवर्ड) सहित खाता खोला है।\nआपको लॉग इन कर के अपना कूटशब्द (पासवर्ड) तुरंत बदल लेना चाहिये।\n\nयदि यह खाता गलती से खोला गया है, तो आप इस मेसेज को नज़रंदाज़ कर सकते हैं।",
-    "usernamehasherror": "सदस्यनाम में हैश कैरैक्टर वर्जित हैं।",
     "login-throttled": "आपने हाल ही में कई बार लॉग इन करने के प्रयास किये हैं।\nपुनः प्रयास करने से पहले कृपया $1 प्रतीक्षा करें।",
     "login-abort-generic": "आपका सत्रारम्भ असफल रहा - निष्फलित",
     "loginlanguagelabel": "भाषा: $1",
     "prefs-skin": "त्वचा",
     "skin-preview": "झलक",
     "datedefault": "खा़स पसंद नहीं",
-    "prefs-beta": "बीटा सुविधाएँ",
     "prefs-datetime": "दिनांक तथा समय",
     "prefs-labs": "लैब विशेषताएँ",
     "prefs-user-pages": "सदस्य पृष्ठ",
     "upload-permitted": "अनुमतित फ़ाइल प्रकार: $1।",
     "upload-preferred": "पसंदीदा फ़ाइल प्रकार: $1।",
     "upload-prohibited": "प्रतिबंधिक फ़ाइल प्रकार: $1।",
-    "uploadlog": "अपलोड लॉग",
     "uploadlogpage": "अपलोड लॉग",
     "uploadlogpagetext": "नीचे हाल ही में अपलोड की गई फ़ाइलों की सूची है।\nकृपया और द्रैश्यिक विवरण के लिए [[Special:NewFiles|नई फ़ाइलों की गैलरी]] देखें।",
     "filename": "फ़ाइल का नाम",
     "filereuploadsummary": "फ़ाइल में बदलाव:",
     "filestatus": "कॉपीराइट स्थिति:",
     "filesource": "स्रोत:",
-    "uploadedfiles": "अपलोड की हुई फ़ाइलें",
     "ignorewarning": "चेतावनियाँ नज़र‍ंदाज़ करें और फ़ाइल अपलोड करें",
     "ignorewarnings": "सभी चेतावनियों को नज़रंदाज़ करें",
     "minlength1": "फ़ाइल का नाम कम-से-कम एक अक्षर का होना चाहिये।",
     "overwroteimage": "\"[[$1]]\" का नया अवतरण अपलोड किया",
     "uploaddisabled": "अपलोड प्रतिबंधित हैं।",
     "copyuploaddisabled": "यू॰आर॰एल द्वारा अपलोड अक्षम हैं।",
-    "uploadfromurl-queued": "आपका अपलोड पंक्तिबद्ध किया गया।",
     "uploaddisabledtext": "फ़ाइल अपलोड अक्षम हैं।",
     "php-uploaddisabledtext": "पी॰एच॰पी में फ़ाइल अपलोड बंद हैं।\nकृपया file_uploads जमाव की जाँच करें।",
     "uploadscripted": "इस फ़ाइल में एच॰टी॰एम॰एल या स्क्रिप्ट कोड है, जो वेब ब्राउज़र द्वारा गलत पढ़ा जा सकता है।",
     "upload-misc-error": "अज्ञात अपलोड त्रुटि",
     "upload-misc-error-text": "अपलोड के दौरान कोई अज्ञात त्रुटि आई।\nकृपया यह पुष्टि कर लें कि यू॰आर॰एल वैध है और उस तक पहुँचा जा सकता है, उसके बाद फिर कोशिश करें।\nअगर फिर भी समस्या आती है तो किसी [[Special:ListUsers/sysop|प्रबंधक]] से संपर्क करें।",
     "upload-too-many-redirects": "इस यू॰आर॰एल में अत्यधिक पुनर्निर्देशन हैं",
-    "upload-unknown-size": "अज्ञात आकार",
     "upload-http-error": "एक एच॰टी॰टी॰पी त्रुटि आई: $1",
     "upload-copy-upload-invalid-domain": "कॉपी अपलोड इस डोमेन से उपलब्ध नहीं हैं।",
     "backend-fail-stream": "फ़ाइल $1 स्ट्रीम नहीं हो पाई।",
     "img-auth-streaming": "\"$1\" को स्ट्रीम किया जा रहा है।",
     "img-auth-public": "img_auth.php निजी विकि से फ़ाइलें प्रदान करने का काम करता है।\nयह विकि सार्वजनिक विकि है।\nउचित सुरक्षा के लिए img_auth.php को अक्षम है।",
     "img-auth-noread": "प्रयोक्ता को \"$1\" पढ़ने का अधिकार नहीं है।",
-    "img-auth-bad-query-string": "यू॰आर॰एल में अवैध क्वेरी स्ट्रिंग है।",
     "http-invalid-url": "अमान्य यू॰आर॰एल: $1",
     "http-invalid-scheme": "\"$1\" से शुरू होने वाले यू॰आर॰एल स्वीकार्य नहीं हैं।",
     "http-request-error": "एच॰टी॰टी॰पी अनुरोध अज्ञात त्रुटि के कारण असफल रहा।",
     "filehist-dimensions": "आकार",
     "filehist-filesize": "फ़ाईल का आकार (बाइट)",
     "filehist-comment": "टिप्पणी",
-    "filehist-missing": "फ़ाइल मौजूद नहीं है",
     "imagelinks": "फ़ाइल का उपयोग",
     "linkstoimage": "निम्नोक्त {{PLURAL:$1|पृष्ठ|$1 पन्नों}} में इस फ़ाइल की कड़ियाँ हैं:",
     "linkstoimage-more": "{{PLURAL:$1|$1}} से अधिक पृष्ठ इस फ़ाइल से जुड़ते हैं।\nनिम्नोक्त सूची फ़ाइल से जुड़ने वाले {{PLURAL:$1|$1 पृष्ठ|$1 पृष्ठ}} दिखाती है।\n[[Special:WhatLinksHere/$2|पूरी सूची]] भी उपलब्ध है।",
     "emailuser-title-notarget": "सदस्य को ई-मेल करें",
     "emailpage": "सदस्य को ई-मेल करें",
     "emailpagetext": "नीचे दिए पर्चे को जरिए आप इस {{GENDER:$1|सदस्य}} को ई-मेल भेज सकते हैं।\nआपने जो पता [[Special:Preferences|अपनी पसंद]] में दिया था वह इस ई-मेल के \"भेजने वाले\" के तौर पर आएगा, अतः प्राप्तकर्ता आपको सीधे जवाब दे सकेंगे।",
-    "usermailererror": "मेल ऑब्जेक्ट ने त्रुटि दी:",
     "defemailsubject": "{{SITENAME}} ई-मेल \"$1\" सदस्य से",
     "usermaildisabled": "सदस्य ई-मेल अक्षम किया गया",
     "usermaildisabledtext": "आप इस विकि पर ई-मेल अन्य सदस्यों को ई-मेल नहीं भेज सकते हैं",
     "noemailtitle": "कोई ई-मेल एड्रेस नहीं",
     "noemailtext": "इस सदस्य ने वैध ई-मेल पता नहीं दिया है।",
-    "nowikiemailtitle": "ई-मेल की अनुमति नहीं है",
     "nowikiemailtext": "इस सदस्य ने अन्य सदस्यों से ई-मेल न प्राप्त करने का फ़ैसला लिया हुआ है।",
     "emailnotarget": "प्राप्तकर्ता के लिए अस्तित्वहीन या अमान्य सदस्यनाम।",
     "emailtarget": "प्राप्तकर्ता का सदस्यनाम भरें",
     "nowatchlist": "आपकी ध्यानसूची में कोई भी पृष्ठ नहीं हैं।",
     "watchlistanontext": "अपनी ध्यानसूची में मौजूद पृष्ठ देखने या फिर संपादित करने के लिये कॄपया $1 करें।",
     "watchnologin": "लॉग इन नहीं किया है",
-    "watchnologintext": "ध्यानसूची में बदलाव के लिये [[Special:UserLogin|लॉग इन]] करना आवश्यक है।",
     "addwatch": "ध्यानसूची में जोड़ें",
     "addedwatchtext": "आपकी [[Special:Watchlist|ध्यानसूची]] में \"[[:$1]]\" पृष्ठ जोड़ दिया गया है।\nभविष्य में इस पृष्ठ तथा इसके वार्ता पृष्ठ में होने वाले बदलाव आपकी ध्यानसूची में दिखेंगे।",
     "removewatch": "ध्यानसूची से हटाएँ",
     "watching": "ध्यान दे रहे हैं...",
     "unwatching": "ध्यान हटा रहे हैं...",
     "watcherrortext": "\"$1\" के लिये आपकी ध्यानसूची सेटिंग बदलते समय त्रुटि हुई।",
-    "enotif_mailer": "{{SITENAME}} सूचना इ-मेल कर्ता",
     "enotif_reset": "सभी पृष्ठ देखे हुए दर्शाएँ",
     "enotif_impersonal_salutation": "{{SITENAME}} सदस्य",
     "enotif_subject_deleted": "{{SITENAME}} पृष्ठ $1 को {{gender:$2|$2}} ने हटा दिया है",
     "excontent": "पाठ था: '$1'",
     "excontentauthor": "पाठ था: '$1' (और सिर्फ '[[Special:Contributions/$2|$2]]' का योगदान था।)",
     "exbeforeblank": "खाली करने से पहले पाठ था: '$1'",
-    "exblank": "पृष्ठ खाली था",
     "delete-confirm": "\"$1\" को हटाएँ",
     "delete-legend": "हटाएँ",
     "historywarning": "''' चेतावनी: ''' आप जो पृष्ठ हटाने जा रहे हैं उसके इतिहास में लगभग $1 {{PLURAL:$1|अवतरण}} हैं:",
     "importunknownsource": "अज्ञात आयात स्रोत प्रकार",
     "importcantopen": "आयात फ़ाईल खोल नहीं पायें",
     "importbadinterwiki": "अवैध अन्तरविकि कड़ी",
-    "importnotext": "खाली अथवा पाठ नहीं",
     "importsuccess": "आयात सफल हुआ!",
-    "importhistoryconflict": "उपलब्ध इतिहास अवतरण आपसमें विरोधी हैं (यह पृष्ठ पहलेसे आयात कर दिया गया होनेकी आशंका हैं)",
     "importnosources": "कोई भी ट्रान्सविकी आयात स्रोत मिले नहीं और प्रत्यक्ष इतिहास अपलोड बन्द कर दिए गए हैं।",
     "importnofile": "कोईभी आयात फ़ाईल अपलोड नहीं हुई हैं।",
     "importuploaderrorsize": "आयात फ़ाईल अपलोड हुई नहीं। इसका आकार अनुमतिसे ज्यादा हैं।",
index 662c62c..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",
index 51af343..92564f9 100644 (file)
     "accountcreatedtext": "Suradnički je račun [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|talk]]) stvoren.",
     "createaccount-title": "Otvaranje suradničkog računa za {{SITENAME}}",
     "createaccount-text": "Netko je stvorio suradnički račun s Vašom adresom elektronske pošte na {{SITENAME}} ($4) nazvan \"$2\", s lozinkom \"$3\". Trebali biste se prijaviti i odmah promijeniti lozinku.\n\nMožete zanemariti ovu poruku ako je suradnički račun stvoren nenamjerno.",
-    "usernamehasherror": "Suradničko ime ne može sadržavati znakove #",
     "login-throttled": "Nedavno ste se previše puta pokušali prijaviti.\nMolimo Vas pričekajte $1 prije nego što pokušate ponovno.",
     "login-abort-generic": "Vaša prijava bila je neuspješna - Prekinuto",
     "loginlanguagelabel": "Jezik: $1",
     "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",
     "upload-permitted": "Dopušteni tipovi datoteka: $1.",
     "upload-preferred": "Poželjni tipovi datoteka: $1.",
     "upload-prohibited": "Zabranjeni tipovi datoteka: $1.",
-    "uploadlog": "evidencija postavljanja",
     "uploadlogpage": "Evidencija_postavljanja",
     "uploadlogpagetext": "Dolje je popis nedavno postavljenih slika.",
     "filename": "Ime datoteke",
     "filereuploadsummary": "Izmjene datoteke:",
     "filestatus": "Status autorskih prava:",
     "filesource": "Izvor:",
-    "uploadedfiles": "Postavljene datoteke",
     "ignorewarning": "Zanemari upozorenja i snimi datoteku.",
     "ignorewarnings": "Zanemari sva upozorenja",
     "minlength1": "Ime datoteke mora imati barem jedno slovo.",
     "overwroteimage": "postavljena nova inačica od \"[[$1]]\"",
     "uploaddisabled": "Postavljanje je onemogućeno",
     "copyuploaddisabled": "Postavljanje URL-om onemogućeno.",
-    "uploadfromurl-queued": "Vaše postavljanje je na čekanju.",
     "uploaddisabledtext": "Postavljanje datoteka je onemogućeno.",
     "php-uploaddisabledtext": "Postavljanja datoteka su onemogućena u PHP-u. Molimo provjerite postavke za postavljanje datoteka.",
     "uploadscripted": "Ova datoteka sadrži HTML ili skriptu, što može dovesti do grešaka u web pregledniku.",
     "upload-misc-error": "Nepoznata pogrješka pri snimanju",
     "upload-misc-error-text": "Dogodila se nepoznata pogrješka pri snimanju.\nProvjerite valjanost i dostupnost URL-a i pokušajte opet.\nAko se problem ponovi, javite to [[Special:ListUsers/sysop|administratoru]].",
     "upload-too-many-redirects": "URL je sadržavao previše preusmjeravanja",
-    "upload-unknown-size": "Nepoznata veličina",
     "upload-http-error": "HTTP-pogrješka: $1",
     "upload-copy-upload-invalid-domain": "Kopije postavljenih datoteka nisu dostupne s ove domene.",
     "backend-fail-stream": "Ne mogu prikazati datoteku $1.",
     "img-auth-streaming": "Tok \"$1\".",
     "img-auth-public": "Funkcija img_auth.php služi za izlaz datoteka s privatnih wikija.\nOvaj wiki je postavljena kao javni wiki.\nZa optimalnu sigurnost, img_auth.php je onemogućena.",
     "img-auth-noread": "Suradnik nema pristup za čitanje \"$1\".",
-    "img-auth-bad-query-string": "URL ima nevažeći izraz upita.",
     "http-invalid-url": "Nevaljan URL: $1",
     "http-invalid-scheme": "URL-ovi s prefiksom \"$1\" nisu podržani.",
     "http-request-error": "HTTP zahtjev nije uspio zbog nepoznate pogreške.",
     "filehist-dimensions": "Dimenzije",
     "filehist-filesize": "Veličina datoteke",
     "filehist-comment": "Komentar",
-    "filehist-missing": "Nedostaje datoteka",
     "imagelinks": "Upotreba datoteke",
     "linkstoimage": "{{PLURAL:$1|Sljedeća stranica povezuje|$1 sljedećih stranice povezuju}} na ovu datoteku:",
     "linkstoimage-more": "Više od $1 {{PLURAL:$1|stranice povezuje|stranica povezuje}} na ovu datoteku.\nSljedeći popis prikazuje {{PLURAL:$1|stranice koje|prvih $1 stranica koje}} vode na ovu datoteku.\n[[Special:WhatLinksHere/$2|Ovdje se nalazi]] potpuni popis.",
     "emailuser-title-notarget": "Pošalji e-poštu suradniku",
     "emailpage": "Pošalji e-poštu suradniku",
     "emailpagetext": "Možete koristiti ovaj obrazac za slanje elektroničke pošte {{GENDER:$1|suradniku|suradnici}}.\nE-mail adresa iz Vaših [[Special:Preferences|postavki]] nalazit će se u \"From\" polju poruke i primatelj će Vam moći izravno odgovoriti.",
-    "usermailererror": "Sustav pošte javio je pogrešku:",
     "defemailsubject": "{{SITENAME}} e-mail od suradnika \"$1\"",
     "usermaildisabled": "Suradnička e-pošta je onemogućena",
     "usermaildisabledtext": "Ne možete slati e-poštu drugim suradnicima na ovom wikiju",
     "noemailtitle": "Nema adrese primaoca",
     "noemailtext": "Ovaj suradnik nije odredio valjanu e-mail adresu.",
-    "nowikiemailtitle": "E-mail nije dozvoljen",
     "nowikiemailtext": "Ovaj suradnik je odlučio ne primati e-mail od drugih suradnika.",
     "emailnotarget": "Nepostojeće ili nevažeće suradničko ime za primatelja.",
     "emailtarget": "Unesite suradničko ime primatelja",
     "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",
     "watching": "Pratim...",
     "unwatching": "Prestajem pratiti...",
     "watcherrortext": "Došlo je do pogreške kod izmjene Vašeg popisa praćenja za \"$1\".",
-    "enotif_mailer": "{{SITENAME}} - izvješća o promjenama",
     "enotif_reset": "Označi sve stranice kao već posjećene",
     "enotif_impersonal_salutation": "{{SITENAME}} suradnik",
     "enotif_subject_deleted": "{{gender:$2|Suradnik|Suradnica}} $2 {{gender:$2|je obrisao|je obrisala}} stranicu $1 projekta {{SITENAME}}",
     "excontent": "sadržaj je bio: '$1'",
     "excontentauthor": "sadržaj je bio: '$1' (a jedini urednik '$2')",
     "exbeforeblank": "sadržaj prije brisanja je bio: '$1'",
-    "exblank": "stranica je bila prazna",
     "delete-confirm": "Obriši \"$1\"",
     "delete-legend": "Izbriši",
     "historywarning": "'''Upozorenje''':  Stranica koju želite obrisati ima starije izmjene s približno $1 {{PLURAL:$1|inačicom|inačice|inačica}}:",
     "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",
     "importunknownsource": "Nepoznat tip stranica za uvoz",
     "importcantopen": "Ne mogu otvoriti datoteku za uvoz",
     "importbadinterwiki": "Neispravna međuwiki poveznica",
-    "importnotext": "Prazno ili bez teksta",
     "importsuccess": "Uvoz je uspio!",
-    "importhistoryconflict": "Došlo je do konflikta među prijašnjim inačicama (ova je stranica možda već uvezena)",
     "importnosources": "Nije unesen nijedan izvor za transwiki uvoz i neposredno postavljanje povijesti je onemogućeno.",
     "importnofile": "Nije postavljena uvozna datoteka.",
     "importuploaderrorsize": "Uvoz datoteke nije uspio. Datoteka je veća od dopuštene veličine.",
index 1798dc1..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ć",
index 3bed54f..ed2c375 100644 (file)
     "accountcreatedtext": "[[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|vita]]) felhasználói fiókja sikeresen létrejött.",
     "createaccount-title": "Új {{SITENAME}}-azonosító létrehozása",
     "createaccount-text": "Valaki létrehozott számodra egy \"$2\" nevű {{SITENAME}}-azonosítót ($4).\nA hozzá tartozó jelszó \"$3\", melyet a bejelentkezés után minél előbb változtass meg.\n\nHa nem kértél új azonosítót, és tévedésből kaptad ezt a levelet, hagyd figyelmen kívül.",
-    "usernamehasherror": "A felhasználónév nem tartalmazhat hash karaktereket",
     "login-throttled": "Túl sok hibás bejelentkezés.\nVárj $1, mielőtt újra próbálkozol.",
     "login-abort-generic": "A bejelentkezés sikertelen – megszakítva",
     "loginlanguagelabel": "Nyelv: $1",
     "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",
     "upload-permitted": "Engedélyezett fájltípusok: $1.",
     "upload-preferred": "Támogatott fájltípusok: $1.",
     "upload-prohibited": "Tiltott fájltípusok: $1.",
-    "uploadlog": "feltöltési napló",
     "uploadlogpage": "Feltöltési napló",
     "uploadlogpagetext": "Lentebb látható a legutóbbi felküldések listája.\nLásd még az [[Special:NewFiles|új fáljlok galériáját]]",
     "filename": "Fájlnév",
     "filereuploadsummary": "Változtatások:",
     "filestatus": "Szerzői jogi állapot:",
     "filesource": "Forrás:",
-    "uploadedfiles": "Feltöltött fájlok",
     "ignorewarning": "Biztosan így akarom feltölteni",
     "ignorewarnings": "Hagyd figyelmen kívül a figyelmeztetéseket",
     "minlength1": "A fájlnévnek legalább egy betűből kell állnia.",
     "overwroteimage": "feltöltötte a(z) „[[$1]]” fájl új változatát",
     "uploaddisabled": "Feltöltések kikapcsolva",
     "copyuploaddisabled": "A feltöltés URL alapján le van tiltva.",
-    "uploadfromurl-queued": "A feltöltésed a várakozási sorba került.",
     "uploaddisabledtext": "A fájlfeltöltés nem engedélyezett.",
     "php-uploaddisabledtext": "A PHP-s fájlfeltöltés le van tiltva. Ellenőrizd a file_uploads beállítást.",
     "uploadscripted": "Ez a fájl olyan HTML- vagy parancsfájlkódot tartalmaz, melyet tévedésből egy webböngésző esetleg értelmezni próbálhatna.",
     "upload-misc-error": "Ismeretlen feltöltési hiba",
     "upload-misc-error-text": "A feltöltés során ismeretlen hiba történt.  Kérjük, ellenőrizd, hogy az URL érvényes-e és hozzáférhető-e, majd próbáld újra.  Ha a probléma továbbra is fennáll, akkor lépj kapcsolatba az [[Special:ListUsers/sysop|adminisztrátorral]].",
     "upload-too-many-redirects": "Az URL túl sokszor volt átirányítva",
-    "upload-unknown-size": "Ismeretlen méretű",
     "upload-http-error": "HTTP-hiba történt: $1",
     "upload-copy-upload-invalid-domain": "Másolás nem engedélyezett ebből a tartományból.",
     "backend-fail-stream": "Nem sikerült sugározni ezt a fájlt: $1.",
     "img-auth-streaming": "„$1” továbbítása.",
     "img-auth-public": "Az img_auth.php funkciója az, hogy fájlokat közvetítsen egy privát wikiből.\nEz a wiki publikus, így a biztonság miatt az img_auth.php ki van kapcsolva.",
     "img-auth-noread": "A szerkesztő nem jogosult a(z) „$1” olvasására.",
-    "img-auth-bad-query-string": "Az URL-cím érvénytelen lekérdezést tartalmaz.",
     "http-invalid-url": "Érvénytelen URL-cím: $1",
     "http-invalid-scheme": "A(z) „$1” sémájú URL-ek nem támogatottak.",
     "http-request-error": "A HTTP-kérés nem sikerült egy ismeretlen hiba miatt.",
     "filehist-dimensions": "Felbontás",
     "filehist-filesize": "Fájlméret",
     "filehist-comment": "Megjegyzés",
-    "filehist-missing": "A fájl hiányzik",
     "imagelinks": "Fájlhasználat",
     "linkstoimage": "Az alábbi {{PLURAL:$1|lap hivatkozik|lapok hivatkoznak}} erre a fájlra:",
     "linkstoimage-more": "Több, mint {{PLURAL:$1|egy|$1}} oldal hivatkozik erre a fájlra.\nA következő lista csak az {{PLURAL:$1|első linket|első $1 linket}} tartalmazza.\nA teljes lista [[Special:WhatLinksHere/$2|ezen a lapon]] található meg.",
     "emailuser-title-notarget": "E-mail küldése a felhasználónak",
     "emailpage": "E-mail küldése",
     "emailpagetext": "{{GENDER:$1|felhasználó}}nevű szerkesztő e-mail-címére ezen űrlap kitöltésével üzenetet tudsz küldeni.\nFeladóként a [[Special:Preferences|beállításaid]]nál megadott e-mail-címed fog szerepelni, így a címzett közvetlenül tud majd válaszolni neked.",
-    "usermailererror": "A levélküldő objektum hibával tért vissza:",
     "defemailsubject": "{{SITENAME}} e-mail a következő felhasználótól: „$1”",
     "usermaildisabled": "Email fogadás letiltva",
     "usermaildisabledtext": "Nem küldhetsz emailt más felhasználóknak ezen a wikin",
     "noemailtitle": "Nincs e-mail cím",
     "noemailtext": "Ez a szerkesztő nem adott meg érvényes e-mail címet.",
-    "nowikiemailtitle": "Nem küldhető e-mail üzenet",
     "nowikiemailtext": "Ez a szerkesztő nem kíván másoktól e-mail üzeneteket fogadni.",
     "emailnotarget": "A címzett nem létezik vagy a felhasználónév érvénytelen.",
     "emailtarget": "Írd be címzett felhasználónevét",
     "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",
     "watching": "Figyelés...",
     "unwatching": "Figyelés befejezése...",
     "watcherrortext": "Hiba történt a(z) „$1” lapra vonatkozó figyelőlista-beállítások módosítása közben.",
-    "enotif_mailer": "{{SITENAME}} Értesítéspostázó",
     "enotif_reset": "Az összes lap megjelölése felkeresettként",
     "enotif_impersonal_salutation": "{{SITENAME}} felhasználó",
     "enotif_subject_deleted": "$2 törölte a $1 {{SITENAME}} oldalt.",
     "excontent": "a lap tartalma: „$1”",
     "excontentauthor": "a lap tartalma: „$1” (és csak „[[Special:Contributions/$2|$2]]” szerkesztette)",
     "exbeforeblank": "az eltávolítás előtti tartalom: „$1”",
-    "exblank": "a lap üres volt",
     "delete-confirm": "$1 törlése",
     "delete-legend": "Törlés",
     "historywarning": "'''Figyelem:''' a lapnak, amit törölni készülsz, körülbelül $1 változattal rendelkező laptörténete van:",
     "importunknownsource": "Ismeretlen import forrástípus",
     "importcantopen": "Nem nyitható meg az importfájl",
     "importbadinterwiki": "Rossz wikiközi hivatkozás",
-    "importnotext": "Üres, vagy nincs szöveg",
     "importsuccess": "Az importálás befejeződött!",
-    "importhistoryconflict": "Ütköző előzményváltozat létezik (lehet, hogy már importálták ezt a lapot)",
     "importnosources": "Nincsenek transzwikiimport-források definiálva, a közvetlen laptörténet-felküldés pedig nem megengedett.",
     "importnofile": "Nem került importfájl feltöltésre.",
     "importuploaderrorsize": "Az importálandó fájl feltöltése nem sikerült, mert nagyobb, mint a megengedett feltöltési méret.",
index 4f566b9..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": "Հեռացնել հսկացանկից",
index c71ffa2..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",
index 4bb742d..535c491 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.",
     "accountcreatedtext": "Akun pengguna untuk [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|bicara]]) telah dibuat.",
     "createaccount-title": "Pembuatan akun untuk {{SITENAME}}",
     "createaccount-text": "Seseorang telah membuat sebuah akun untuk alamat surel Anda di {{SITENAME}} ($4) dengan nama \"$2\" dan kata sandi \"$3\". Anda dianjurkan untuk masuk log dan mengganti kata sandi Anda sekarang.\n\nAnda dapat mengabaikan pesan ini jika akun ini dibuat karena suatu kesalahan.",
-    "usernamehasherror": "Nama pengguna tidak bisa mengandung tanda pagar",
     "login-throttled": "Anda sudah terlalu sering mencoba masuk log.\nSilakan menunggu $1 sebelum mencoba lagi.",
     "login-abort-generic": "Proses masuk Anda tidak berhasil - Dibatalkan",
     "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",
     "upload-permitted": "Jenis berkas yang diperbolehkan: $1.",
     "upload-preferred": "Jenis berkas yang disarankan: $1.",
     "upload-prohibited": "Jenis berkas yang dilarang: $1.",
-    "uploadlog": "log pengunggahan",
     "uploadlogpage": "Log pengunggahan",
     "uploadlogpagetext": "Berikut adalah daftar unggahan berkas terbaru. \nLihat [[Special:NewFiles|galeri berkas baru]] untuk tampilan visual.",
     "filename": "Nama berkas",
     "filereuploadsummary": "Perubahan berkas:",
     "filestatus": "Status hak cipta:",
     "filesource": "Sumber:",
-    "uploadedfiles": "Berkas yang telah dimuat",
     "ignorewarning": "Abaikan peringatan dan langsung simpan berkas.",
     "ignorewarnings": "Abaikan peringatan apa pun",
     "minlength1": "Nama berkas paling tidak harus terdiri dari satu huruf.",
     "overwroteimage": "memuat versi baru dari \"[[$1]]\"",
     "uploaddisabled": "Maaf, fasilitas pemuatan dimatikan.",
     "copyuploaddisabled": "Pengunggahan dengan URL dimatikan.",
-    "uploadfromurl-queued": "Pengunggahan Anda telah terantri.",
     "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.",
     "upload-misc-error": "Kesalahan pemuatan yang tak dikenal",
     "upload-misc-error-text": "Suatu kesalahan yang tak dikenal terjadi sewaktu pemuatan. Harap pastikan bahwa URL tersebut valid dan dapat diakses dan silakan coba lagi. Jika masalah ini tetap terjadi, kontak administrator sistem.",
     "upload-too-many-redirects": "URL mengandung terlalu banyak pengalihan",
-    "upload-unknown-size": "Ukuran tidak diketahui",
     "upload-http-error": "Kesalahan HTTP terjadi: $1",
     "upload-copy-upload-invalid-domain": "Unggahan salinan tidak tersedia dari domain ini.",
     "backend-fail-stream": "Tidak bisa mengalikan berkas $1.",
     "img-auth-streaming": "Streaming \"$1\".",
     "img-auth-public": "Fungsi dari img_auth.php adalah mengeluarkan berkas dari wiki pribadi.\nWiki ini di atur sebagai wiki umum.\nUntuk pilihan keamanan, img_auth.php dinonaktifkan.",
     "img-auth-noread": "Pengguna tidak memiliki akses untuk membaca \"$1\".",
-    "img-auth-bad-query-string": "URL memiliki string kueri yang tidak sah.",
     "http-invalid-url": "URL tidak sah: $1",
     "http-invalid-scheme": "URL dengan skema \"$1\" tidak didukung.",
     "http-request-error": "Permintaan HTTP gagal karena kesalahan yang tidak diketahui.",
     "filehist-dimensions": "Dimensi",
     "filehist-filesize": "Besar berkas",
     "filehist-comment": "Komentar",
-    "filehist-missing": "Berkas tidak ditemukan",
     "imagelinks": "Pranala berkas",
     "linkstoimage": "{{PLURAL:$1||}}$1 halaman berikut memiliki pranala ke berkas ini:",
     "linkstoimage-more": "Lebih dari $1 {{PLURAL:$1|halaman|halaman}} memiliki pranala ke berkas ini.\nDaftar berikut menampilkan {{PLURAL:$1|halaman dengan pranala langsung|$1 halaman dengan pranala langsung}} ke berkas ini.\nJuga tersedia [[Special:WhatLinksHere/$2|daftar selengkapnya]].",
     "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",
     "emailuser-title-notarget": "Kirim surel",
     "emailpage": "Kirim surel ke pengguna ini",
     "emailpagetext": "Anda dapat menggunakan formulir di bawah ini untuk mengirimkan surel ke {{GENDER:$1|pengguna}} ini.\nAlamat surel yang Anda masukkan di [[Special:Preferences|preferensi akun Anda]] akan muncul sebagai alamat \"Dari\" dalam surel tersebut, sehingga penerima dapat langsung membalas kepada Anda.",
-    "usermailererror": "Kesalahan objek surat:",
     "defemailsubject": "Surel {{SITENAME}} dari pengguna \"$1\"",
     "usermaildisabled": "Surel pengguna dinonaktifkan",
     "usermaildisabledtext": "Anda tidak dapat mengirim surel pada pengguna lain di wiki ini",
     "noemailtitle": "Tidak ada alamat surel",
     "noemailtext": "Pengguna ini tidak memberikan suatu alamat surel yang valid.",
-    "nowikiemailtitle": "Surel tak diizinkan",
     "nowikiemailtext": "Pengguna ini telah memilih untuk tidak menerima surel dari pengguna lain.",
     "emailnotarget": "Nama pengguna penerima tidak ada atau tidak sah.",
     "emailtarget": "Masukkan nama pengguna penerima",
     "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",
     "watching": "Memantau...",
     "unwatching": "Menghilangkan pemantauan...",
     "watcherrortext": "Terjadi kesalahan saat mengubah preferensi daftar pantauan Anda untuk \" $1 \".",
-    "enotif_mailer": "Pengirim Notifikasi {{SITENAME}}",
     "enotif_reset": "Tandai semua halaman sebagai telah dikunjungi",
     "enotif_impersonal_salutation": "Pengguna {{SITENAME}}",
     "enotif_subject_deleted": "Halaman $1 di {{SITENAME}} telah dihapus oleh {{gender:$2|$2}}",
     "excontent": "isi sebelumnya: '$1'",
     "excontentauthor": "isinya hanya berupa: '$1' (dan satu-satunya penyumbang adalah '[[Special:Contributions/$2|$2]]')",
     "exbeforeblank": "isi sebelum dikosongkan: '$1'",
-    "exblank": "halaman kosong",
     "delete-confirm": "Hapus \"$1\"",
     "delete-legend": "Hapus",
     "historywarning": "'''Peringatan:''' Halaman yang akan Anda hapus mempunyai sejarah dengan $1 {{PLURAL:$1|revisi|revisi}}:",
     "importunknownsource": "Sumber impor tidak dikenali",
     "importcantopen": "Berkas impor tidak dapat dibuka",
     "importbadinterwiki": "Pranala interwiki rusak",
-    "importnotext": "Kosong atau tidak ada teks",
     "importsuccess": "Impor sukses!",
-    "importhistoryconflict": "Terjadi konflik revisi sejarah (mungkin pernah mengimpor halaman ini sebelumnya)",
     "importnosources": "Tidak ada sumber impor transwiki yang telah dibuat dan pemuatan riwayat secara langsung telah di non-aktifkan.",
     "importnofile": "Tidak ada berkas sumber impor yang telah dimuat.",
     "importuploaderrorsize": "Pemuatan berkas impor gagal. Ukuran berkas melebihi ukuran yang diperbolehkan.",
index f35f165..2613139 100644 (file)
@@ -18,7 +18,6 @@
     "october": "Nuliaġvik",
     "november": "Quyyavik",
     "december": "Uvluiḷaq",
-    "helppage": "Help:anniqsuiruq",
     "mainpage": "Makpiġaaq Kanna",
     "mainpage-description": "Makpibaaq Kanna",
     "portal-url": "Project:qargi"
index 2fc4fe8..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",
index 92181a0..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",
index b53c41c..aa8c0cd 100644 (file)
     "accountcreatedtext": "Notandaaðgangurinn fyrir [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|spjall]]) hefur verið búinn til.",
     "createaccount-title": "Innskráningagerð á {{SITENAME}}",
     "createaccount-text": "Einhver bjó til aðgang fyrir netfangið þitt á {{SITENAME}} ($4) undir nafninu „$2“, með lykilorðið „$3“.\nÞú ættir að skrá þig inn og breyta lykilorðinu núna.\n\nÞú getur hunsað þessi skilaboð, ef villa hefur átt sér stað.",
-    "usernamehasherror": "Notendanöfn mega ekki innihalda kassa (#)",
     "login-throttled": "Þér hefur mistekist að skrá þig inn undir þessu notendanafni of oft.\nVinsamlegast bíðið $1 áður en þú reynir aftur.",
     "login-abort-generic": "Innskráningin misheppnaðist - hætt var við hana.",
     "loginlanguagelabel": "Tungumál: $1",
     "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",
     "upload-permitted": "Heimilaðar skráargerðir: $1.",
     "upload-preferred": "Ákjósanlegustu skrárgerðirnar: $1.",
     "upload-prohibited": "Óheimiluð skrárgerð: $1.",
-    "uploadlog": "innhlaðningarskrá",
     "uploadlogpage": "Innhlaðningarskrá",
     "uploadlogpagetext": "Fyrir neðan er listi yfir nýlegustu innhlöðnu skrárnar.\nSjá [[Special:NewFiles|myndasafn nýrra mynda]] fyrir myndrænna yfirlit.",
     "filename": "Skráarnafn",
     "filereuploadsummary": "Skráarbreytingar:",
     "filestatus": "Staða höfundaréttar:",
     "filesource": "Heimild:",
-    "uploadedfiles": "Hlóð inn skráunum",
     "ignorewarning": "Hunsa viðvaranir og vista þessa skrá",
     "ignorewarnings": "Hunsa allar viðvaranir",
     "minlength1": "Skráarnöfn þurfa að vera að minnsta kosti einn stafur að lengd",
     "overwroteimage": "hlóð inn nýrri útgáfu af \"[[$1]]\"",
     "uploaddisabled": "Lokað er fyrir að hlaða inn myndum.",
     "copyuploaddisabled": "Lokað er fyrir að hlaða inn myndum frá vefslóð.",
-    "uploadfromurl-queued": "Upphlaðið þitt hefur verið sett í biðröð.",
     "uploaddisabledtext": "Lokað er fyrir að hlaða inn skrám.",
     "php-uploaddisabledtext": "Skráar upphlöð eru óvirk í PHP.\nVinsamlegast athugaðu stillinguna í file_uploads.",
     "uploadscripted": "Þetta skjal inniheldur (X)HTML eða forskriftu sem gæti valdið villum í vöfrum.",
     "upload-misc-error": "Óþekkt innhleðsluvilla",
     "upload-misc-error-text": "Upphal þitt mistókst vegna óþekktrar villu.\nAthugaðu hvort vefslóðin sé rétt og aðgengileg og að því loknu reyndu aftur.\nEf vandamálið lagast ekki, hafðu samband við [[Special:ListUsers/sysop|stjórnanda]].",
     "upload-too-many-redirects": "Vefslóðin inniheldur of margar tilvísanir.",
-    "upload-unknown-size": "Óþekkt stærð",
     "upload-http-error": "HTTP villa kom upp við upphal skráarinnar: $1",
     "upload-copy-upload-invalid-domain": "Lokað er fyrir afritun skráa frá öðrum vefþjón á þessu vefsvæði.",
     "backend-fail-stream": "Gat ekki streymt skránni „$1“.",
     "img-auth-streaming": "Streymi \"$1\".",
     "img-auth-public": "Virkni img_auth.php er að flytja út skrár frá einkawiki.\nÞessi wiki er stilltur sem opinber wiki.\nVegna öryggissjónarmiða er img_auth.php óvirkt.",
     "img-auth-noread": "Notandinn hefur ekki rétt til að lesa \"$1\"",
-    "img-auth-bad-query-string": "Vefslóðin hefur ógildan fyrirspurnar streng.",
     "http-invalid-url": "Vitlaust veffang: $1",
     "http-invalid-scheme": "Vefslóðir með \"$1\" forskeyti eru óstuddar.",
     "http-request-error": "HTTP beiðni mistókst vegna óþekktrar villu.",
     "filehist-dimensions": "Víddir",
     "filehist-filesize": "Stærð skráar",
     "filehist-comment": "Athugasemd",
-    "filehist-missing": "Skrá vantar",
     "imagelinks": "Skráartenglar",
     "linkstoimage": "Eftirfarandi {{PLURAL:$1|síða tengist|$1 síður tengjast}} í þessa skrá:",
     "linkstoimage-more": "Fleiri en $1 {{PLURAL:$1|síða tengist|síður tengjast}} þessari skrá.\nEftirfarandi listi sýnir {{PLURAL:$1|fyrsta myndatengilinn|fyrstu $1 myndatenglana}}.\n[[Special:WhatLinksHere/$2|Tæmandi listi]] er til staðar.",
     "emailuser-title-notarget": "Senda tölvupóst",
     "emailpage": "Senda tölvupóst",
     "emailpagetext": "Hafi notandinn tilgreint netfang í stillingunum sínum er hægt að senda póst til {{GENDER:$1|hans|hennar|hans}} hér.\nPóstfangið sem þú tilgreindir í [[Special:Preferences|stillingunum þínum]] birtist í \"Frá:\" hluta tölvupóstsins, svo að viðtakandi hans geti svarað beint til þín.",
-    "usermailererror": "Póst hlutur skilaði villu:",
     "defemailsubject": "{{SITENAME}} skilaboð frá notandanum \"$1\"",
     "usermaildisabled": "Netfang notenda er óvirkt",
     "usermaildisabledtext": "Þú getur ekki sent tölvupóst til annara notenda á þessum wiki",
     "noemailtitle": "Ekkert póstfang",
     "noemailtext": "Þessi notandi hefur ekki tilgreint gilt netfang.",
-    "nowikiemailtitle": "Tölvupóstur óheimill",
     "nowikiemailtext": "Þessi notandi hefur valið að fá engan tölvupóst frá öðrum notendum.",
     "emailnotarget": "Notendanafn er ekki til eða ógilt fyrir þennan viðtakanda.",
     "emailtarget": "Tilgreindu notendanafn viðtakanda",
     "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",
     "watching": "Vakta...",
     "unwatching": "Afvakta...",
     "watcherrortext": "Villa kom upp við breytingu á stillingum vaktlistans fyrir \"$1\".",
-    "enotif_mailer": "{{SITENAME}} tilkynningasendill",
     "enotif_reset": "Merkja allar síður sem skoðaðar",
     "enotif_impersonal_salutation": "{{SITENAME}}notandi",
     "enotif_subject_deleted": "$1 á {{SITENAME}} hefur verið eytt af {{gender:$2|$2}}",
     "excontent": "innihaldið var: „$1“",
     "excontentauthor": "innihaldið var: '$1' (og öll framlög voru frá '[[Special:Contributions/$2|$2]]')",
     "exbeforeblank": "innihald fyrir tæmingu var: '$1'",
-    "exblank": "síðan var tóm",
     "delete-confirm": "Eyða „$1“",
     "delete-legend": "Eyða",
     "historywarning": "'''Viðvörun:''' Síðan sem þú ert um það bil að eyða hefur breytingarskrá með $1 {{PLURAL:$1|breytingu|breytingum}}:",
     "importunknownsource": "Óþekkt innflutningstilfangsgerð",
     "importcantopen": "Get ekki opnað innflutt skjal",
     "importbadinterwiki": "Villa í tungumálatengli",
-    "importnotext": "Tómt eða enginn texti",
     "importsuccess": "Innflutningi lokið!",
-    "importhistoryconflict": "Breytingarskrá þessarar síðu er þegar til (gæti hafa verið flutt inn áður)",
     "importnosources": "Engin uppspretta hefur verið valin og bein upphlöð breytingarskráa eru óvirk.",
     "importnofile": "Engri skrá var hlaðið inn.",
     "importuploaderrorsize": "Upphlöðun skráarinnar mistókst.\nSkráin er stærri en hámarsstærð síðna segir til um.",
index 9298564..426ccc8 100644 (file)
     "permalink": "Link permanente",
     "print": "Stampa",
     "view": "Visualizza",
+    "view-foreign": "Vedi su $1",
     "edit": "Modifica",
+    "edit-local": "Modifica descrizione locale",
     "create": "Crea",
+    "create-local": "Aggiungi descrizione locale",
     "editthispage": "Modifica questa pagina",
     "create-this-page": "Crea questa pagina",
     "delete": "Cancella",
     "accountcreatedtext": "È stata creata un'utenza per [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|msg]]).",
     "createaccount-title": "Creazione di un accesso a {{SITENAME}}",
     "createaccount-text": "Qualcuno ha creato un accesso a {{SITENAME}} ($4) a nome di $2, associato a questo indirizzo di posta elettronica. La password per l'utente \"$2\" è impostata a \"$3\".\nÈ opportuno eseguire un accesso quanto prima e cambiare la password immediatamente.\n\nSe l'accesso è stato creato per errore, si può ignorare questo messaggio.",
-    "usernamehasherror": "Il nome utente non può contenere caratteri hash",
     "login-throttled": "Sono stati effettuati troppi tentativi di accesso in breve tempo.\nAttendi $1 e riprova in seguito.",
     "login-abort-generic": "Il tuo login non ha avuto successo - Annullato",
     "loginlanguagelabel": "Lingua: $1",
     "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",
     "upload-permitted": "Tipi di file consentiti: $1.",
     "upload-preferred": "Tipi di file consigliati: $1.",
     "upload-prohibited": "Tipi di file non consentiti: $1.",
-    "uploadlog": "File caricati",
     "uploadlogpage": "File caricati",
     "uploadlogpagetext": "Di seguito sono elencati gli ultimi file caricati.\nConsultare la [[Special:NewFiles|galleria dei nuovi file]] per una visione d'insieme.",
     "filename": "Nome del file",
     "filereuploadsummary": "Cambiamenti al file:",
     "filestatus": "Informazioni sul copyright:",
     "filesource": "Fonte:",
-    "uploadedfiles": "Elenco dei file caricati",
     "ignorewarning": "Ignora l'avviso e salva comunque il file",
     "ignorewarnings": "Ignora i messaggi di avvertimento del sistema",
     "minlength1": "Il nome del file dev'essere composto da almeno un carattere.",
     "overwroteimage": "ha caricato una nuova versione di \"[[$1]]\"",
     "uploaddisabled": "Il caricamento dei file è disabilitato.",
     "copyuploaddisabled": "Il caricamento tramite URL è disabilitato.",
-    "uploadfromurl-queued": "Il caricamento è stato accodato.",
     "uploaddisabledtext": "Il caricamento dei file non è attivo.",
     "php-uploaddisabledtext": "Il caricamento di file tramite PHP è disabilitato. Controlla la configurazione di file_uploads.",
     "uploadscripted": "Questo file contiene codice HTML o di script, che potrebbe essere interpretato erroneamente da un browser web.",
     "upload-misc-error": "Errore di caricamento sconosciuto",
     "upload-misc-error-text": "Si è verificato un errore non identificato durante il caricamento del file. Verificare che la URL sia corretta e accessibile e provare di nuovo. Se il problema persiste, contattare un [[Special:ListUsers/sysop|amministratore]].",
     "upload-too-many-redirects": "L'URL conteneva troppi redirect",
-    "upload-unknown-size": "Dimensione sconosciuta",
     "upload-http-error": "Si è verificato un errore HTTP: $1",
     "upload-copy-upload-invalid-domain": "Non è consentito il caricamento di copie da questo dominio.",
     "backend-fail-stream": "Impossibile trasmettere il file $1.",
     "img-auth-streaming": "\"$1\" in streaming.",
     "img-auth-public": "La funzione di img_auth.php è di dare in output file da un sito wiki privato.\nQuesto sito è configurato come un wiki pubblico.\nPer una sicurezza ottimale, img_auth.php è disattivato.",
     "img-auth-noread": "L'utente non ha accesso alla lettura di \"$1\".",
-    "img-auth-bad-query-string": "L'URL contiene una stringa di query non valida.",
     "http-invalid-url": "URL non valido: $1",
     "http-invalid-scheme": "URL con il prefisso \"$1\" non sono supportati.",
     "http-request-error": "Richiesta HTTP fallita a causa di un errore sconosciuto.",
     "filehist-dimensions": "Dimensioni",
     "filehist-filesize": "Dimensione del file",
     "filehist-comment": "Commento",
-    "filehist-missing": "File mancante",
     "imagelinks": "Uso del file",
     "linkstoimage": "{{PLURAL:$1|La seguente pagina contiene|Le seguenti $1 pagine contengono}} collegamenti al file:",
     "linkstoimage-more": "Più di $1 {{PLURAL:$1|pagina punta|pagine puntano}} a questo file.\nDi seguito sono elencate solo {{PLURAL:$1|la prima pagina che punta|le prime $1 pagine che puntano}} a questo file.\nÈ disponibile un [[Special:WhatLinksHere/$2|elenco completo]].",
     "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",
+    "listgrouprights-namespaceprotection-header": "Restrizioni per namespace",
+    "listgrouprights-namespaceprotection-namespace": "Namespace",
+    "listgrouprights-namespaceprotection-restrictedto": "Diritto che consente all'utente di modificare",
+    "trackingcategories": "Categorie di monitoraggio",
+    "trackingcategories-summary": "Questa pagina elenca le categorie di monitoraggio che vengono popolate automaticamente dal software MediaWiki. I loro nomi possono essere cambiati modificando i relativi messaggi di sistema nel namespace {{ns:8}}.",
+    "trackingcategories-msg": "Categoria di monitoraggio",
     "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.",
+    "noindex-category-desc": "La pagina non è indicizzata dai robot perché contiene la parola magica <code><nowiki>__NOINDEX__</nowiki></code> e si trova in un namespace dove tale flag è consentito.",
+    "index-category-desc": "La pagina contiene <code><nowiki>__INDEX__</nowiki></code> (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 <code>$wgMaxArticleSize</code>, 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 <code>{{{Foo}}})</code>, la pagina sarà più grande di <code>$wgMaxArticleSize</code>.",
+    "expensive-parserfunction-category-desc": "La pagina usa troppe funzioni parser (come <code>#ifexist</code>). Vedi [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+    "broken-file-category-desc": "Categoria aggiunta se la pagina contiene un collegamento interrotto ad un file (un collegamento per incorporare un file quando questo non esiste).",
+    "hidden-category-category-desc": "Questa è una categoria che contiene <code><nowiki>__HIDDENCAT__</nowiki></code>, il quale impedisce che venga mostrata, in modo predefinito, nel riquadro dei collegamenti alle categorie delle pagine.",
     "trackingcategories-nodesc": "Nessuna descrizione disponibile.",
     "trackingcategories-disabled": "La categoria è disabilitata",
     "mailnologin": "Nessun indirizzo cui inviare il messaggio",
     "emailuser-title-notarget": "Invia una email a un utente",
     "emailpage": "Invia un messaggio email all'utente",
     "emailpagetext": "Usare il modulo sottostante per inviare un messaggio e-mail all'{{GENDER:$1|utente}} indicato. L'indirizzo specificato nelle [[Special:Preferences|preferenze]] del mittente apparirà nel campo \"Da:\" del messaggio per consentire al destinatario di rispondere direttamente.",
-    "usermailererror": "L'oggetto mail ha restituito l'errore:",
     "defemailsubject": "Messaggio da {{SITENAME}} dall'utente \"$1\"",
     "usermaildisabled": "e-mail utente disabilitata",
     "usermaildisabledtext": "Non è possibile inviare e-mail ad altri utenti su questo wiki",
     "noemailtitle": "Nessun indirizzo e-mail",
     "noemailtext": "Questo utente non ha indicato un indirizzo e-mail valido.",
-    "nowikiemailtitle": "E-mail non permessa",
     "nowikiemailtext": "Questo utente ha scelto di non ricevere messaggi di posta elettronica dagli altri utenti.",
     "emailnotarget": "Nome utente del destinatario inesistente o non valido.",
     "emailtarget": "Inserisci il nome utente del destinatario",
     "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",
     "watching": "Aggiunta agli osservati speciali...",
     "unwatching": "Eliminazione dagli osservati speciali...",
     "watcherrortext": "Si è verificato un errore durante la modifica degli osservati speciali per \"$1\".",
-    "enotif_mailer": "Sistema di notifica via e-mail di {{SITENAME}}",
     "enotif_reset": "Segna tutte le pagine come già visitate",
     "enotif_impersonal_salutation": "Utente di {{SITENAME}}",
     "enotif_subject_deleted": "La pagina $1 di {{SITENAME}} è stata cancellata da {{gender:$2|$2}}",
     "excontent": "il contenuto era: '$1'",
     "excontentauthor": "il contenuto era: '$1' (e l'unico contributore era '[[Special:Contributions/$2|$2]]')",
     "exbeforeblank": "Il contenuto prima dello svuotamento era: '$1'",
-    "exblank": "la pagina era vuota",
     "delete-confirm": "Cancella \"$1\"",
     "delete-legend": "Cancella",
     "historywarning": "'''Attenzione:''' La pagina che stai per cancellare ha una cronologia con approssimativamente $1 {{PLURAL:$1|revisione|revisioni}}:",
     "importunknownsource": "Tipo di origine sconosciuto per l'importazione",
     "importcantopen": "Impossibile aprire il file di importazione",
     "importbadinterwiki": "Collegamento inter-wiki errato",
-    "importnotext": "Testo vuoto o mancante",
     "importsuccess": "Importazione riuscita.",
-    "importhistoryconflict": "La cronologia contiene delle versioni in conflitto (questa pagina potrebbe essere già stata importata)",
     "importnosources": "Non è stata definita una fonte per l'importazione transwiki; l'importazione diretta della cronologia non è attiva.",
     "importnofile": "Non è stato caricato nessun file per l'importazione.",
     "importuploaderrorsize": "Caricamento del file per l'importazione non riuscito. Il file supera le dimensioni massime consentite per l'upload.",
     "specialpages-group-users": "Utenti e diritti",
     "specialpages-group-highuse": "Pagine molto usate",
     "specialpages-group-pages": "Elenchi di pagine",
-    "specialpages-group-pagetools": "Strumenti utili per le pagine",
+    "specialpages-group-pagetools": "Strumenti per le pagine",
     "specialpages-group-wiki": "Dati e strumenti",
-    "specialpages-group-redirects": "Pagine speciali di redirect",
+    "specialpages-group-redirects": "Pagine speciali che reindirizzano",
     "specialpages-group-spam": "Strumenti contro lo spam",
     "blankpage": "Pagina vuota",
     "intentionallyblankpage": "Questa pagina è lasciata volutamente vuota.",
index 2516d5c..ca4e4cc 100644 (file)
     "accountcreatedtext": "利用者アカウント [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|トーク]]) を作成しました。",
     "createaccount-title": "{{SITENAME}}のアカウント作成",
     "createaccount-text": "誰か (おそらくあなた) が、{{SITENAME}} ($4) にあなたのメールアドレスのアカウントを作成しました。\nアカウント名「$2」、パスワード「$3」です。\n今すぐログインしてパスワードを変更してください。\n\nこのアカウントが何かの手違いで作成された場合は、このメッセージを無視してください。",
-    "usernamehasherror": "利用者名には番号記号を含めることができません",
     "login-throttled": "ログインの失敗が制限回数を超えました。\n$1待ってから再度試してください。",
     "login-abort-generic": "ログインに失敗しました - 中止",
     "loginlanguagelabel": "言語: $1",
     "prefs-skin": "外装",
     "skin-preview": "プレビュー",
     "datedefault": "選択なし",
-    "prefs-beta": "ベータ版機能",
     "prefs-datetime": "日付と時刻",
     "prefs-labs": "ラボの機能",
     "prefs-user-pages": "利用者ページ",
     "upload-permitted": "許可されているファイル形式: $1。",
     "upload-preferred": "推奨されているファイル形式: $1。",
     "upload-prohibited": "禁止されているファイル形式: $1。",
-    "uploadlog": "アップロード記録",
     "uploadlogpage": "アップロード記録",
     "uploadlogpagetext": "以下はファイルアップロードの最近の記録です。\n画像付きで見るには[[Special:NewFiles|新規ファイルの一覧]]をご覧ください。",
     "filename": "ファイル名",
     "filereuploadsummary": "ファイルの変更:",
     "filestatus": "著作権情報:",
     "filesource": "出典:",
-    "uploadedfiles": "アップロードされたファイル",
     "ignorewarning": "警告を無視してファイルを保存",
     "ignorewarnings": "警告を無視",
     "minlength1": "ファイル名には少なくとも1文字必要です。",
     "overwroteimage": "「[[$1]]」の新しい版をアップロードしました",
     "uploaddisabled": "アップロード機能は無効になっています。",
     "copyuploaddisabled": "URL からのアップロードは無効になっています。",
-    "uploadfromurl-queued": "アップロードがキューに追加されました。",
     "uploaddisabledtext": "ファイルのアップロードは、無効になっています。",
     "php-uploaddisabledtext": "ファイルのアップロードがPHPで無効化されています。\nfile_uploadsの設定を確認してください。",
     "uploadscripted": "このファイルは、ウェブブラウザーが誤って解釈してしまうおそれがあるHTMLまたはスクリプトコードを含んでいます。",
     "upload-misc-error": "不明なアップロードエラー",
     "upload-misc-error-text": "アップロード中に不明なエラーが発生しました。\n指定した URL が正しいこととアクセスできることを確認して、もう一度試してください。\nそれでもこのエラーが発生する場合は、[[Special:ListUsers/sysop|管理者]]に連絡してください。",
     "upload-too-many-redirects": "そのURLに含まれるリダイレクトが多すぎます",
-    "upload-unknown-size": "サイズ不明",
     "upload-http-error": "HTTP エラー発生: $1",
     "upload-copy-upload-invalid-domain": "このドメインからのアップロードは許可されていません。",
     "backend-fail-stream": "ファイル $1 をストリームできませんでした。",
     "img-auth-streaming": "「$1」を転送中。",
     "img-auth-public": "img_auth.phpの機能は、非公開ウィキからのファイルの出力です。\nこのウィキは公開ウィキとして構成されています。\n最適なセキュリティのため、img_auth.phpを無効にしています。",
     "img-auth-noread": "利用者は「$1」の読み取り権限を持っていません。",
-    "img-auth-bad-query-string": "URLの中に無効なクエリ文字列があります。",
     "http-invalid-url": "無効なURL: $1",
     "http-invalid-scheme": "スキーム「$1」の URL には未対応です。",
     "http-request-error": "不明なエラーによりHTTPリクエストに失敗しました。",
     "filehist-dimensions": "寸法",
     "filehist-filesize": "ファイルサイズ",
     "filehist-comment": "コメント",
-    "filehist-missing": "ファイルがありません",
     "imagelinks": "ファイルの使用状況",
     "linkstoimage": "以下の{{PLURAL:$1|ページ|​&#32;$1 ページ}}がこのファイルにリンクしています:",
     "linkstoimage-more": "このファイルへは $1 を超える数のページからリンクがあります。\n以下の一覧ではこのファイルにリンクしている最初の $1 ページのみを表示しています。\n[[Special:WhatLinksHere/$2|完全な一覧]]も参照してください。",
     "trackingcategories-summary": "このページでは、MediaWiki ソフトウェアが自動的に追加した追跡用カテゴリを列挙します。これらの名前は、{{ns:8}} 名前空間内の対応するシステム メッセージを修正することで変更できます。",
     "trackingcategories-msg": "追跡用カテゴリ",
     "trackingcategories-name": "メッセージ名",
+    "post-expand-template-inclusion-category-desc": "テンプレートを展開したあとのページ サイズが <code>$wgMaxArticleSize</code> よりも大きいため、一部のテンプレートが展開されなかった",
+    "post-expand-template-argument-category-desc": "テンプレート引数 (<code>{{{Foo}}}</code> のような三重中括弧部分) を展開したあとのページが <code>$wgMaxArticleSize</code> よりも大きい",
+    "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": "<code><nowiki>__HIDDENCAT__</nowiki></code> を含むカテゴリ。このカテゴリは、既定ではページのカテゴリ リンク ボックス内に表示されません。",
     "trackingcategories-nodesc": "説明はありません。",
     "mailnologin": "送信アドレスがありません",
     "mailnologintext": "他の利用者宛にメールを送信するためには、[[Special:UserLogin|ログイン]]し、[[Special:Preferences|個人設定]]で有効なメールアドレスを設定する必要があります。",
     "emailuser-title-notarget": "利用者にメールを送信",
     "emailpage": "利用者にメールを送信",
     "emailpagetext": "以下のフォームを使用してこの{{GENDER:$1|利用者}}にメールを送信できます。\n「差出人」として、[[Special:Preferences|利用者の個人設定]]で入力したメールアドレスが設定されます。これにより、受信者があなたに直接返信できるようになります。",
-    "usermailererror": "メールが以下のエラーを返しました:",
     "defemailsubject": "{{SITENAME}} 利用者「$1」からのメール",
     "usermaildisabled": "利用者メール機能は無効です",
     "usermaildisabledtext": "このウィキでは他の利用者にメールを送信できません",
     "noemailtitle": "メールアドレスがありません",
     "noemailtext": "この利用者は有効なメールアドレスを登録していません。",
-    "nowikiemailtitle": "メールは許可されていません",
     "nowikiemailtext": "この利用者は他の利用者からメールを受け取らない設定にしています。",
     "emailnotarget": "受信者の利用者名が存在しない、あるいは無効です。",
     "emailtarget": "受信者の利用者名を入力してください",
     "nowatchlist": "ウォッチリストには何も項目がありません。",
     "watchlistanontext": "ウォッチリストにある項目を閲覧または編集するには、$1してください。",
     "watchnologin": "ログインしていません",
-    "watchnologintext": "ウォッチリストを変更するためには、[[Special:UserLogin|ログイン]]している必要があります。",
     "addwatch": "ウォッチリストに追加",
     "addedwatchtext": "ページ「[[:$1]]」を[[Special:Watchlist|ウォッチリスト]]に追加しました。\nこのページまたはそのトークページが変更されると、ウォッチリストに表示されます。",
     "removewatch": "ウォッチリストから除去",
     "watching": "ウォッチリストに追加中...",
     "unwatching": "ウォッチリストから除去中...",
     "watcherrortext": "ウォッチリストの「$1」の設定を変更中にエラーが発生しました。",
-    "enotif_mailer": "{{SITENAME}} 通知メール",
     "enotif_reset": "すべてのページを訪問済みにする",
     "enotif_impersonal_salutation": "{{SITENAME}}の利用者",
     "enotif_subject_deleted": "{{SITENAME}} ページ $1 を $2 が{{GENDER:$2|削除しました}}",
     "excontent": "内容:「$1」",
     "excontentauthor": "内容:「$1」(投稿者は「[[Special:Contributions/$2|$2]]」のみ)",
     "exbeforeblank": "白紙化前の内容:「$1」",
-    "exblank": "白紙ページ",
     "delete-confirm": "「$1」の削除",
     "delete-legend": "削除",
     "historywarning": "<strong>警告:</strong> 削除しようとしているページには、約$1版の履歴があります:",
     "importunknownsource": "取り込み元のタイプが不明です",
     "importcantopen": "取り込みファイルが開けませんでした",
     "importbadinterwiki": "ウィキ間リンクが正しくありません",
-    "importnotext": "内容が空、または本文がありません",
     "importsuccess": "取り込みが完了しました!",
-    "importhistoryconflict": "取り込み時にいくつかの版が競合しました (以前に同じページが取り込まれているかもしれません)",
     "importnosources": "ウィキ間移動の取り込み元が定義されていないため、履歴の直接アップロードは無効になっています。",
     "importnofile": "取り込みファイルはアップロードされませんでした。",
     "importuploaderrorsize": "取り込みファイルのアップロードに失敗しました。\nファイルが、アップロードできるサイズを超えています。",
index 6c2e421..3d72b45 100644 (file)
     "disclaimers": "nunxusra lo za'i na fuzme",
     "disclaimerpage": "Project:kampu nunxusra be lo za'i na fuzme",
     "edithelp": "stika nunsidju",
-    "helppage": "Help:lo se vasru",
     "mainpage": "Ralju Ckupau",
     "mainpage-description": "ralju ckupau",
     "portal": "bende ckupau",
index 3a4142e..0dbe6ed 100644 (file)
     "disclaimers": "Førbeholt",
     "disclaimerpage": "Project:Huses førbeholt",
     "edithelp": "Hjælp til redigærenge",
-    "helppage": "Help:Hjælpførside",
     "mainpage": "Førsit",
     "mainpage-description": "Førsit",
     "policy-url": "Project:Politik",
index 64dae2e..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",
index fe169c9..bc36adb 100644 (file)
     "accountcreatedtext": "მომხმარებლის ანგარიში [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|განხილვა]]) შექმნილია.",
     "createaccount-title": "ანგარიშის შექმნა {{SITENAME}}-თვის",
     "createaccount-text": "ვიღაცამ შექმნა ანგარიში სახელით „$2“ და პაროლით „$3“ თქვენი ელექტრონული ფოსტისთვის {{SITENAME}}-ში ($4). გთხოვთ დარეგისტრირდეთ და შეცვალოთ პაროლი.\n\nშეგიძლიათ ყურადღება არ მიაქციოთ ამ შეტყობინებას, თუ ანგარიში შეცდომით შეიქმნა.",
-    "usernamehasherror": "მომხმარებლის სახელი არ უნდა შეიცავდეს დიეზის სიმბოლოს.",
     "login-throttled": "You have made too many recent login attempts.\nPlease wait $1 before trying again.",
     "login-abort-generic": "თქვენი ავტორიზაცია წარუმატებელია – გაუქმდა",
     "loginlanguagelabel": "ენა: $1",
     "prefs-skin": "გარეკანი",
     "skin-preview": "წინასწარი გადახედვა",
     "datedefault": "წყარო მითითებული არაა",
-    "prefs-beta": "ბეტა შესაძლებლობები",
     "prefs-datetime": "თარიღი და დრო",
     "prefs-labs": "ექსპერიმენტალური ფუნქციები",
     "prefs-user-pages": "მომხმარებლის გვერდები",
     "rclistfrom": "ახალი ცვლილებების ჩვენება დაწყებული $1-დან",
     "rcshowhideminor": "მცირე რედაქტირების $1",
     "rcshowhidebots": "რობოტების  $1",
+    "rcshowhidebots-show": "ჩვენება",
+    "rcshowhidebots-hide": "დამალვა",
     "rcshowhideliu": "$1 რეგისტრირებული მომხმარებელი",
     "rcshowhideanons": "ანონიმური მომხმარებლების $1",
     "rcshowhidepatr": "გაკონტროლებული ცვლილებების $1",
     "upload-permitted": "მიღებული ფაილის ტიპები: $1.",
     "upload-preferred": "სასურველი ფაილის ტიპები: $1.",
     "upload-prohibited": "აკრძალული ფაილის ტიპები: $1.",
-    "uploadlog": "გადმოტვირთვის რეგისტრაცია",
     "uploadlogpage": "გადმოტვირთვის რეგისტრაცია",
     "uploadlogpagetext": "ქვემოთ არის ყველაზე ბოლოს ატვირთული ფაილების სია.",
     "filename": "ფაილის სახელი",
     "filereuploadsummary": "ფაილის ცვლილებები:",
     "filestatus": "საავტორო უფლებების სტატუსი:",
     "filesource": "წყარო:",
-    "uploadedfiles": "ფაილების დამატება",
     "ignorewarning": "გაფრთხილება უგულებელყავი და მაინც შეინახე ფაილი.",
     "ignorewarnings": "უგულებელყავი ნებისმიერი გაფრთხილება",
     "minlength1": "ფაილის სახელი უნდა იყოს არანაკლებ ერთი ასო.",
     "overwroteimage": "ატვირთულია „[[$1]]-ის“ ახალი ვერსია",
     "uploaddisabled": "ატვირთვა გამორთულია.",
     "copyuploaddisabled": "URL ატვირთვა გაღიშულია",
-    "uploadfromurl-queued": "თქვენი ატვირთვა რიგში ჩადგა.",
     "uploaddisabledtext": "ფაილების ატვირთვა შეუძლებელია.",
     "php-uploaddisabledtext": "ფაილების ატვირთვა შეჩერებულია PHP-ით. გთხოვთ შეამოწმოთ file_uploads-ის მნიშვნელობა.",
     "uploadscripted": "ფაილი შეიცავს HTML-კოდს, ან სკრიპტს, რომელიც ბროუზერმა შეიძლება არასწორედ გაანალიზოს.",
     "upload-misc-error": "უცნობია ატვირთვის შეცდომა",
     "upload-misc-error-text": "ატვირთვისას უცნობი სახის შეცდომა გაიპარა.\nგთხოვთ შეამოწმოთ თუ URL სწორია და ხელმისაწვდომია და ისევ სცადოთ.\nთუ პრობლემა ვერ გადაიჭრა, მიმართეთ [[Special:ListUsers/sysop|ადმინისტრატორს]].",
     "upload-too-many-redirects": "URL შეიცავს ძალიან ბევრ გადამისამართებებს",
-    "upload-unknown-size": "უცნობი ზომა",
     "upload-http-error": "მოხდა HTTP შეცდომა: $1",
     "upload-copy-upload-invalid-domain": "ამ დომენში ატვირთვების კოპირება არ არის ხელმისაწვდომი.",
     "backend-fail-stream": "ფაილი $1 ტრანსლირება ვერ მოხერხდა.",
     "img-auth-streaming": "ნაკადური გადაცემა «$1».",
     "img-auth-public": "img_auth.php-ის დანიშვნა გამოიწვევს ფაილების დახურული ვიკიდან გაოტანას.\nეს ვიკი გამართულია როგორც საზოგადი.\nუსაფრთხოების ოპტიმიზააციისთვის img_auth.php გათიშულია.",
     "img-auth-noread": "მომხმარებელს არა აქვს ნებართვა \"$1\"-ის წასაკითხად.",
-    "img-auth-bad-query-string": "URL შეიცავს არასწორ მოთხოვნას.",
     "http-invalid-url": "არასწორი ბმული: $1",
     "http-invalid-scheme": "«$1» სქემის მქონე მისამართები მხარდაჭერილები არ არიან.",
     "http-request-error": "HTTP მოთხოვნის შეცდომა უცნობი მიზეზის გამო.",
     "filehist-dimensions": "განზომილებები",
     "filehist-filesize": "ფაილის ზომა",
     "filehist-comment": "კომენტარი",
-    "filehist-missing": "ფაილი ვერ მოიძებნა",
     "imagelinks": "ფაილის გამოყენება",
     "linkstoimage": "მომდევნო {{PLURAL:$1|გვერდი|გვერდები}} ებმის ამ ფაილს:",
     "linkstoimage-more": "$1-ზე მეტი {{PLURAL:$1|გვერდები|გვერდების|გვერდები}} რომლებსაც აქვთ ბმულები ამ ფაილზე.\nმოცემულ სიაში {{PLURAL:$1|წარმოდგენილია მხოლოდ $1 ბმული|წარმოდგენილია მხოლოდ $1 ბმულები|წარმოდგენილია მხოლოდ $1 ბმულების}} ამ ფაილზე.\nშეგიძლიათ ნახოთ ასევე [[Special:WhatLinksHere/$2|სრული სია]].",
     "emailuser-title-notarget": "ელ. ფოსტის გაგზავნა მომხმარებელთან",
     "emailpage": "ელ. ფოსტა მომხმარებელს",
     "emailpagetext": "თუ ამ მომხმარებელმა თავის პარამეტრებში ელ. ფოსტის მოქმედი მისამართი მიუთითა, ქვემოთ მოყვანილი ფორმის შევსებისას შეგიძლიათ {{GENDER:$1|მისთვის}} შეტყობინების გაგზავნა. ელ. ფოსტის მისამართი, რომელიც [[Special:Preferences|თქვენს პარამეტრებში]] მიუთითეთ, დაფიქსირდება „გამომგზავნის“ ველში, რათა ადრესატმა პასუხის გაცემა შეძლოს.",
-    "usermailererror": "ელ. ფოსტა დაბრუნდა შეცდომის გამო:",
     "defemailsubject": "ელ-ფოსტა საიტის {{SITENAME}} მომხმარებლისგან „$1“",
     "usermaildisabled": "მომხმარებლის e-mail გათიშულია",
     "usermaildisabledtext": "თქვენ ვერ გაგზავნით e-mail-ს.",
     "noemailtitle": "ელ. ფოსტის მისამართი მითითებული არ არის",
     "noemailtext": "მომხმარებელმა არ მიუთითა მოქმედი ელ. ფოსტის მისამართი.",
-    "nowikiemailtitle": "წერილების გაგზავნის უფლება არ გაქვთ.",
     "nowikiemailtext": "ამ მომხმარებელს არ სურს წერილების მიღება სხვა მომხმარებლებისაგან.",
     "emailnotarget": "არარსებული ან არასწორი მომხმარებლის სახელი.",
     "emailtarget": "შეიყვანეთ მომხმარებლის სახელი ელ-ფოსტის გასაგზავნად.",
     "nowatchlist": "თქვენი კონტროლის სია ცარიელია.",
     "watchlistanontext": "$1\n\nიხილეთ ან რედაქტირება გაუკეთეთ თქვენი კონტროლის სიაში შეტანილ ერთეულებს.",
     "watchnologin": "რეგისტრაცია ვერ შესრულდა",
-    "watchnologintext": "თქვენ უნდა მოახდინოთ [[Special:UserLogin|რეგისტრაცია]] თქვენი კონტროლის სიის მოდიფიცირებისათვის.",
     "addwatch": "კონტროლის სიაში დამატება",
     "addedwatchtext": "გვერდი „[[:$1]]“ დაემატა თქვენს [[Special:Watchlist|კონტროლის სიას]].\nამ და მასთან დაკავშირებული განხილვის გვერდის შემდგომი ცვლილებები აისახება იქ.",
     "removewatch": "კონტროლის სიიდან წაშლა",
     "watching": "კონტროლებადი...",
     "unwatching": "არაკონტროლირებადი...",
     "watcherrortext": "\"$1\"–თვის კონტროლის სიის პარამეტრების ცვლილებისას მოხდა შეცდომა.",
-    "enotif_mailer": "{{SITENAME}}. ელ. ფოსტით შეტყობინების სამსახური",
     "enotif_reset": "აღნიშნე ყველა გვერდი, როგორც გადასინჯული",
     "enotif_impersonal_salutation": "ვიკიპედიის მომხმარებელი",
     "enotif_subject_deleted": "გვერდი პროექტიდან „{{SITENAME}}“ სახელწოდებით „$1“ წაშალა {{gender:$2|მომხმარებელმა}} $2",
     "excontent": "შინაარსი იყო: „$1“",
     "excontentauthor": "შინაარსი იყო: „$1“ (და ერთადერთი ავტორი იყო „[[Special:Contributions/$2|$2]]“)",
     "exbeforeblank": "გვერდის შინაარსი წაშლამდე იყო შემდეგი: „$1“",
-    "exblank": "გვერდი ცარიელი იყო",
     "delete-confirm": "„$1“-ის წაშლა",
     "delete-legend": "წაშლა",
     "historywarning": "'''ყურადღება:''' გვერდს, რომლის წაშლასაც აპირებთ, აქვს დიდი ისტორია: ($1)",
     "importunknownsource": "იმპორტის წყაროს ტიპი უცნობია",
     "importcantopen": "იმპორტირებული ფაილი არ გაიხსნა",
     "importbadinterwiki": "არასწორი ინტერვიკი ბმული",
-    "importnotext": "ცარიელია",
     "importsuccess": "იმპორტი განხორციელდა!",
-    "importhistoryconflict": "არსებულ ვერსიათა კონფლიქტი. შესაძლოა იგი უკვე იქნა იმპორტირებული.",
     "importnosources": "ტრანსვიკი იმპორტის წყარო არ არის არჩეული. ცვლილებათა ისტორიის პირდაპირი ატვირთვა გათიშულია.",
     "importnofile": "საიმპორტო ფაილის ატვირთვა ვერ მოხერხდა.",
     "importuploaderrorsize": "ვერ მოხერხდა ფაილის ატვირთვა ან იმპორტირება. ფაილის ზომ არღვევს მითითებულ ზღვარს.",
index 2d904b7..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",
index 4c90cd4..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",
index 257fb68..aad4a1c 100644 (file)
     "currentevents": "Mâmbu ya malu-malu",
     "currentevents-url": "Lukanu:Mâmbu ya malu-malu",
     "edithelp": "Lusadisu ya kusoba",
-    "helppage": "Lusadisu:Mâmbu",
     "mainpage": "Mukânda ya ngudi",
     "mainpage-description": "Mukânda ya ngudi",
     "portal": "Mbôngi",
index 84caf33..0a2f07f 100644 (file)
     "accountcreated": "Hesab vırajiya",
     "accountcreatedtext": "Serba $1i hesabê karberi vırajiya.",
     "createaccount-title": "Serba {{SITENAME}}i vırajiyaene hesabê karberi",
-    "usernamehasherror": "Namê karberi de karakteri gunê têwerte ra mebê",
     "loginlanguagelabel": "Zon: $1",
     "changepassword": "Parola bıvurne",
     "resetpass_header": "Parola hesabi bıvurne",
     "updated": "(Bi rozane)",
     "note": "'''Not:'''",
     "previewnote": "Teme! ena teyna verqeyda.'''\nVurnayışê tu hama qeyd nıbiyo!",
-    "editing": "$1 Vurnayis",
+    "editing": "$1 vurino",
     "editingsection": "Vurnaena $1 (qısım)",
     "editingcomment": "$1 vurnino (qısımo newe)",
-    "editconflict": "Têverabiyaena vurnaişi: $1",
+    "editconflict": "Têverabiyayena vurnayişi: $1",
     "yourtext": "Metnê to",
     "storedversion": "Metıno qeydkerde",
     "yourdiff": "Ferqi",
     "permissionserrorstext-withaction": "Desturê to be $2 çino, serba {{PLURAL:$1|na sebebi|nê sebebu}} ra:",
     "recreate-moveddeleted-warn": "'''Hişyari: no pel o ke şıma vırazeni vere cû vırazyayo.'''\n\nDiqet bıkeri no vurnayişê şıma re gerek esto:",
     "moveddeleted-notice": "Ma ena pele wederna.\nQe referansi logê wedernayışi bın de mocnayiya.",
-    "edit-conflict": "Têverabiyaena vurnaişi.",
+    "edit-conflict": "Têverabiyayena vurnayişi.",
     "post-expand-template-inclusion-warning": "'''Teme''': Zerrekê şabloni zaf gırso.\nTaê şabloni ilawe nêbenê.",
     "post-expand-template-inclusion-category": "Pelê ke tede gırşênia şabloni serde sono",
     "post-expand-template-argument-warning": "Hişyari: No pel de tewr tay yew şablono herayi esto.",
     "upload_directory_missing": "İndeksê bar-kerdena ($1)i çino u terefê ''webserver''i ra nêşikino ke bıaferiyo.",
     "upload_directory_read_only": "İndeksê bar-kerdena ($1)i terefê ''webserver''i nênuşino.",
     "uploaderror": "Xeta bar-kerdene",
-    "uploadlog": "qeydê barkerdene",
     "uploadlogpage": "Qeydê dosya barkerdene",
     "filename": "Namê dosya",
     "filedesc": "Xulasa",
     "filereuploadsummary": "Vurnaisê dosya:",
     "filestatus": "Halê heqa telifi:",
     "filesource": "Çıme:",
-    "uploadedfiles": "Dosyê barkerdey",
     "empty-file": "Dosya ke ti şawit veng biy.",
     "savefile": "Dosya qeyd ke",
     "uploadedimage": "\"[[$1]]\" bar bi",
     "filehist-dimensions": "Budi",
     "filehist-filesize": "Gırşênia dosya",
     "filehist-comment": "Areze-kerdene",
-    "filehist-missing": "Dosya vindbiyaiya",
     "imagelinks": "Gurenaisê dosya",
     "linkstoimage": "Ano {{PLURAL:$1|girê pele|$1 girê pelu}} be na dosya:",
     "nolinkstoimage": "Pelanê ser ena dosyayê link biyê çin o.",
index 88bf1c5..42b4448 100644 (file)
     "nowatchlist": "باقىلاۋ تىزىمىڭىزدە ەش دانا جوق",
     "watchlistanontext": "باقىلاۋ تىزىمىڭىزدەگى دانالاردى قاراۋ, نە وڭدەۋ ٴۇشىن $1 كەرەك.",
     "watchnologin": "كىرمەگەنسىز",
-    "watchnologintext": "باقىلاۋ ٴتىزىمىڭىزدى وزگەرتۋ ٴۇشىن [[Special:UserLogin|كىرۋىڭىز]] ٴجون.",
     "addedwatchtext": "«[[:$1]]» بەتى [[{{#special:Watchlist}}|باقىلاۋ تىزىمىڭىزگە]] ۇستەلدى.\nبۇل بەتتىڭ جانە بايلانىستى تالقىلاۋ بەتىنىڭ كەلەشەكتەگى وزگەرىستەرى مىندا تىزىمدەلىنەدى دە, جانە بەتتىڭ اتاۋى جەڭىل تابىلۋ ٴۇشىن [[{{#special:Recentchanges}}|جۋىقتاعى وزگەرىستەر تىزىمىندە]] '''جۋان ارپىمەن''' كورسەتىلەدى.",
     "removedwatchtext": "«[[:$1]]» بەتى باقىلاۋ تىزىمىڭىزدەن الاستالدى.",
     "watch": "باقىلاۋ",
index 4eedd42..c3dac10 100644 (file)
     "hidetoc": "жасыру",
     "collapsible-collapse": "Түру",
     "collapsible-expand": "Жазу",
-    "thisisdeleted": "$1 қарайсыз ба, немесе қалпына келтіресіз бе?",
+    "thisisdeleted": "$1 қарайсыз ба немесе қалпына келтіресіз бе?",
     "viewdeleted": "$1 қарайсыз ба?",
-    "restorelink": "{{PLURAL:$1|жойылған өңдеме|$1 жойылған өңдемелер}}",
+    "restorelink": "{{PLURAL:$1|жойылған өңдемені|$1 жойылған өңдемені}}",
     "feedlinks": "Арна:",
     "feed-invalid": "Жарамсыз жазылымды арна түрі.",
     "feed-unavailable": "Синдикация таспалары қолжетімсіз",
     "accountcreatedtext": "[[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|талқылауы]]) үшін жаңа қатысушы тіркелгісі жасалды.",
     "createaccount-title": "{{SITENAME}} үшін тіркелу",
     "createaccount-text": "Кейбіреу е-пошта мекенжайыңызды пайдаланып {{SITENAME}} жобасында ($4) «$2» атауымен, «$3» құпия сөзімен тіркелгі жасаған.\nЖобаға кіріуіңіз және құпия сөзіңізді өзгертуіңіз тиісті.\n\nЕгер бұл тіркелгі қателікпен жасалса, осы хабарға елемеуіңіз мүмкін.",
-    "usernamehasherror": "Қатысушы есіміне тор белгі нышаны енгізілмейді.",
     "login-throttled": "Сіз жүйеге кіру үшін тым көп талпыныс жасадыңыз. Өтінемін, қайта кірмес бұрын $1 күте тұрыңыз.",
     "login-abort-generic": "Жүйеге кіру үшін сәтсіз талпыныс жасадыңыз.",
     "loginlanguagelabel": "Тіл: $1",
     "prefs-skin": "Мәнерлер",
     "skin-preview": "Қарап шығу",
     "datedefault": "Еш қалаусыз",
-    "prefs-beta": "Beta мүмкіндік",
     "prefs-datetime": "Уақыт",
     "prefs-labs": "Тәжірибелік мүмкіндіктер",
     "prefs-user-pages": "Қатысушы беттері",
     "upload-permitted": "Рұқсат етілген файл түрлері: $1.",
     "upload-preferred": "Ұнамды файл түрлері $1.",
     "upload-prohibited": "Рұқсат етілмеген файл түрлері: $1.",
-    "uploadlog": "жүктеу журналы",
     "uploadlogpage": "Жүктеу журналы",
     "uploadlogpagetext": "Төменде ең соңғы жүктелген файлдар тізімі.\nТағы көрнекі қарап шығу үшін [[Special:NewFiles|жаңа файлдар көрмесі]] дегенді қараңыз.",
     "filename": "Файл атауы",
     "filereuploadsummary": "Файлдағы өзгерістер",
     "filestatus": "Ауторлық құқықтар күйі:",
     "filesource": "Қайнар көзі:",
-    "uploadedfiles": "Жүктелген файлдар",
     "ignorewarning": "Ескетуді елеме де файлды қалайда сақта.",
     "ignorewarnings": "Ескертулерді елемеу",
     "minlength1": "Файл атауында ең кемінде бір әріп болуы жөн.",
     "overwroteimage": "«[[$1]]» деген файлдың жаңа нұсқасын жүктеді",
     "uploaddisabled": "Жүктеу өшірілген",
     "copyuploaddisabled": "URL арқылы жүктеу өшірілген.",
-    "uploadfromurl-queued": "Сіздің жүктеулеріңіз кезекте тұр.",
     "uploaddisabledtext": "Файл жүктеу өшірілген.",
     "uploadscripted": "Бұл файлда веб шолғышты қателікпен талдатқызатын HTML не әмір коды бар.",
     "uploadvirus": "Бұл файлда вирус бар! Егжей-тегжейлері: $1",
     "upload-misc-error": "Жүктеу кезіндегі белгісіз қате",
     "upload-misc-error-text": "Жүктеу кезінде белгісіз қатеге ұшырасты.\nURL жарамды және қатынаулы екенін тексеріп шығыңыз да қайта байқап көріңіз.\nЕгер бұл мәселе әлде де қалса, [[Special:ListUsers/sysop|жүйе әкімшімен]] қатынасыңыз.",
     "upload-too-many-redirects": "URL шектен тыс жылжытуларға ие",
-    "upload-unknown-size": "Белгісіз өлшем",
     "backend-fail-delete": "«$1» файлы жойылмайды.",
     "backend-fail-describe": "\"$1\" файлы үшін метадерегі өзгертілмейді.",
     "backend-fail-alreadyexists": "\"$1\" файлы бұрыннан бар.",
     "filehist-dimensions": "Өлшемдері",
     "filehist-filesize": "Файл өлшемі",
     "filehist-comment": "Пікір",
-    "filehist-missing": "Жоғалған файл",
     "imagelinks": "Файл қолданылуы",
     "linkstoimage": "Бұл файлға келесі {{PLURAL:$1|беттер|$1 бет}} сілтейді:",
     "nolinkstoimage": "Бұл файлға еш бет сілтемейді.",
     "emailuser-title-notarget": "Қатысушы е-поштасы",
     "emailpage": "Қатысушыға хат жазу",
     "emailpagetext": "Төмендегі пішін арқылы бұл {{GENDER:$1|қатысушыға}} е-пошта хабарламасын жөнелтуге болады.\n[[Special:Preferences|Қатысушы баптауыңызда]] енгізген е-пошта мекенжайыңыз «Кімнен» деген бас жолағында көрінеді, сондықтан хат алушысы тура жауап бере алады.",
-    "usermailererror": "Mail нысаны қате қайтарды:",
     "defemailsubject": "\"$1\" есімді қатысушының {{SITENAME}} е-поштасының хаты",
     "usermaildisabled": "Қатысушының электронды поштасы қосылмаған",
     "usermaildisabledtext": "Бұл уикиде басқа қатысушыларға хат жібере алмайсыз",
     "nowatchlist": "Бақылау тізіміңізде еш дана жоқ",
     "watchlistanontext": "Бақылау тізіміңіздегі даналарды қарау не өңдеу үшін $1.",
     "watchnologin": "Кірмегенсіз",
-    "watchnologintext": "Бақылау тізіміңізді өзгерту үшін [[Special:UserLogin|кіріңіз]].",
     "addwatch": "Бақылау тізіміңізге қосу",
     "addedwatchtext": "«[[:$1]]» беті [[Special:Watchlist|бақылау тізіміңізге]] қосылды.\nБұл беттің және байланысты талқылау бетінің келешектегі өзгерістері мында тізімделінеді де, және беттің атауы жеңіл табылу үшін [[{{#special:Recentchanges}}|жуықтағы өзгерістер тізімінде]] '''жуан әрпімен''' көрсетіледі.",
     "removewatch": "Бақылау тізіміңізден аластату",
     "watchlist-options": "Бақылау тізімінің баптаулары",
     "watching": "Бақылауда…",
     "unwatching": "Бақыламауда…",
-    "enotif_mailer": "{{SITENAME}} ескерту хат жіберу қызметі",
     "enotif_reset": "Барлық бет келіп-кетілді деп белгіле",
     "enotif_impersonal_salutation": "{{SITENAME}} қатысушысы",
     "enotif_subject_deleted": "{{SITENAME}} $1 бетін $2 қатысушысы {{GENDER:$2|жойған}}",
     "excontent": "болған мағлұматы: '$1'",
     "excontentauthor": "болған мағлұматы (тек \"[[Special:Contributions/$2|$2]]\" үлесі): \"$1\"",
     "exbeforeblank": "тазарту алдындағы болған мағлұматы: \"$1\"",
-    "exblank": "бет бос болды",
     "delete-confirm": "«$1» дегенді жою",
     "delete-legend": "Жою",
     "historywarning": "'''Ескету:'' Жоюы көзделген бетте бет тарихында шамамен $1 {{PLURAL:$1|түзетілуі|түзетілулері}} бар:",
     "viewdeletedpage": "Жойылған беттерді қарау",
     "undeletepagetext": "Келесі {{PLURAL:$1|бет жойылған бірақ|$1 бет жойылған бірақ}} мағлұматы мұрағатта бар\nжәне қалпына келтіруге болады. Мұрағат ұдайы тазаланып тұруы мүмкін.",
     "undelete-fieldset-title": "Нұсқаларды қалпына келтіру",
-    "undeleteextrahelp": "Ð\91үкÑ\96л Ð±ÐµÑ\82Ñ\82Ñ\96 Ò\9bалпÑ\8bна ÐºÐµÐ»Ñ\82Ñ\96Ñ\80Ñ\83 Ò¯Ñ\88Ñ\96н, Ð±Ð°Ñ\80лÑ\8bÒ\9b Ò\9bÒ±Ñ\81белгÑ\96 ÐºÓ©Ð·Ð´ÐµÑ\80дÑ\96 Ð±Ð¾Ñ\81аÑ\82Ñ\8bп '''''{{int:Ò\9aалпÑ\8bна ÐºÐµÐ»Ñ\82Ñ\96Ñ\80!}}''''' Ð±Ð°Ñ\82Ñ\8bÑ\80маÑ\81Ñ\8bн Ð½Ò±Ò\9bÑ\8bÒ£Ñ\8bз.\nÐ\91өлекÑ\82еÑ\83мен Ò\9bалпÑ\8bна ÐºÐµÐ»Ñ\82Ñ\96Ñ\80Ñ\83 Ð¾Ñ\80Ñ\8bндаÑ\83 Ò¯Ñ\88Ñ\96н, ÐºÐµÐ»Ñ\82Ñ\96Ñ\80емÑ\96н Ð´ÐµÐ³ÐµÐ½ Ñ\82үзеÑ\82Ñ\83леÑ\80Ñ\96не Ñ\81Ó\99йкеÑ\81 ÐºÓ©Ð·Ð´ÐµÑ\80ге Ò\9bÒ±Ñ\81белгÑ\96 Ñ\81алÑ\8bÒ£Ñ\8bз Ð´Ð°, Ð¶Ó\99не '''''{{int:Ò\9aалпÑ\8bна ÐºÐµÐ»Ñ\82Ñ\96Ñ\80!}}''''' Ñ\82үймеÑ\81Ñ\96н Ð½Ò±Ò\9bÑ\8bÒ£Ñ\8bз. '''''Ò\9aайÑ\82а Ò\9bой''''' Ñ\82үймеÑ\81Ñ\96н Ð½Ò±Ò\9bÑ\8bÒ\93анда Ð¼Ó\99ндеме Ð°Ñ\83маÒ\93Ñ\8b Ñ\82азаÑ\80Ñ\82адÑ\8b Ð¶Ó\99не Ð±Ð°Ñ\80лÑ\8bÒ\9b Ò\9bÒ±Ñ\81белгÑ\96 ÐºÓ©Ð·Ð´ÐµÑ\80Ñ\96н Ð±Ð¾Ñ\81аÑ\82адÑ\8b.",
+    "undeleteextrahelp": "ТолÑ\8bÒ\9b Ð±ÐµÑ\82 Ñ\82аÑ\80иÑ\85Ñ\8bн Ò\9bалпÑ\8bна ÐºÐµÐ»Ñ\82Ñ\96Ñ\80Ñ\83 Ò¯Ñ\88Ñ\96н Ð±Ð°Ñ\80лÑ\8bÒ\9b Ò\9bÒ±Ñ\81белгÑ\96 ÐºÓ©Ð·Ð´ÐµÑ\80дÑ\96 Ð±Ð¾Ñ\81аÑ\82Ñ\8bп <strong><em>{{int:undeletebtn}}</em></strong> Ð±Ð°Ñ\82Ñ\8bÑ\80маÑ\81Ñ\8bн Ð½Ò±Ò\9bÑ\8bÒ£Ñ\8bз.\nÐ\91өлекÑ\82еÑ\83мен Ò\9bалпÑ\8bна ÐºÐµÐ»Ñ\82Ñ\96Ñ\80Ñ\83дÑ\96 Ð¾Ñ\80Ñ\8bндаÑ\83 Ò¯Ñ\88Ñ\96н Ò\9bалпÑ\8bна ÐºÐµÐ»Ñ\82Ñ\96Ñ\80Ñ\83 ÐºÐµÑ\80ек Ñ\82үзеÑ\82Ñ\83леÑ\80Ñ\96не Ñ\81Ó\99йкеÑ\81 ÐºÓ©Ð·Ð´ÐµÑ\80ге Ò\9bÒ±Ñ\81белгÑ\96мен Ð±ÐµÐ»Ð³Ñ\96леп <strong><em>{{int:undeletebtn}}</em></strong> Ð±Ð°Ñ\82Ñ\8bÑ\80маÑ\81Ñ\8bн Ð±Ð°Ñ\81Ñ\8bÒ£Ñ\8bз.",
     "undeleterevisions": "$1 түзету мұрағатталды",
     "undeletehistory": "Егер бет мағлұматын қалпына келтірсеңіз, тарихында барлық түзетулер да\nқайтарылады. Егер жоюдан соң дәл солай атауымен жаңа бет басталса, қалпына келтірілген түзетулер\nтарихтың алдында көрсетіледі. Тағы да файл түзетулерін қалпына келтіргенде тиымдары жойылатын ескеріңіз.",
     "undeleterevdel": "Егер бұл үстіңгі бетте аяқталса, не файл түзетуі жарым-жартылай жойылған болса, жою болдырмауы орындалмайды.\nОсындай жағдайларда, ең жаңа жойылған түзетуін алып тастауыңыз не жасыруын болдырмауыңыз жөн.",
     "undeletebtn": "Қалпына келтір!",
     "undeletelink": "қарау/қалпына келтіру",
     "undeleteviewlink": "қарау",
-    "undeleteinvert": "ТаңдалÒ\93андÑ\8b Ð°Ð»Ð¼Ð°Ñ\81Ñ\82ыру",
+    "undeleteinvert": "ТаңдалÒ\93андÑ\8b Ð¶Ð°Ñ\81ыру",
     "undeletecomment": "Себебі:",
     "undeletedrevisions": "{{PLURAL:$1|1 түзету|$1 түзету}} қалпына келтірілді",
     "undeletedrevisions-files": "{{PLURAL:$1|1 түзету|$1 түзету}} және {{PLURAL:$2|1 файл|$2 файл}} қалпына келтірілді",
     "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}} жобасында беттерді жылжытуға рұқсатыңыз жоқ.",
     "importunknownsource": "Cырттан алынатын қайнар түрі белгісіз",
     "importcantopen": "Сырттан алынатын файл ашылмайды",
     "importbadinterwiki": "Жарамсыз уики-аралық сілтеме",
-    "importnotext": "Бұл бос, немесе мәтіні жоқ",
     "importsuccess": "Сырттан алу аяқталды!",
-    "importhistoryconflict": "Тарихында қақтығысты түзету бар (бұл бет алдында сырттан алынған сияқты)",
     "importnosources": "Уики-апару үшін сырттан алынатын еш қайнар көзі анықталмаған, және тарихын тікелей қотарып беруі өшірілген.",
     "importnofile": "Сырттан алынған файл жүктелген жоқ.",
     "importuploaderrorsize": "Сырттан алынған файлдың жүктелуі сәтсіз өтті. Файл мөлшері рұқсат етілгеннен мөлшерден асады.",
index 00615ee..fb64486 100644 (file)
     "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",
index 20ff74c..b6d6856 100644 (file)
     "currentevents": "Maannakkut pisut",
     "disclaimers": "Aalajangersagaq",
     "edithelp": "Ikiuutit",
-    "helppage": "Help:Ikiuutit",
     "mainpage": "Saqqaa",
     "mainpage-description": "Saqqaa",
     "portal": "Allattartup saqqaa",
index 93785ec..6eafe4f 100644 (file)
@@ -36,7 +36,8 @@
             "Yknok29",
             "לערי ריינהארט",
             "관인생략",
-            "아라"
+            "아라",
+            "Keysuck"
         ]
     },
     "tog-underline": "링크에 밑줄:",
     "print": "인쇄",
     "view": "보기",
     "edit": "편집",
+    "edit-local": "로컬 설명 편집",
     "create": "만들기",
+    "create-local": "로컬 설명 추가",
     "editthispage": "이 문서 편집하기",
     "create-this-page": "이 문서 만들기",
     "delete": "삭제",
     "accountcreatedtext": "[[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|토론]]) 사용자 계정이 만들어졌습니다.",
     "createaccount-title": "{{SITENAME}} 계정 만들기",
     "createaccount-text": "누군가가 {{SITENAME}} ($4)에서 사용자 이름 \"$2\", 비밀번호 \"$3\"로 당신의 이메일 주소가 등록된 계정을 만들었습니다. \n지금 로그인하여 비밀번호를 바꾸십시오.\n\n실수로 계정을 잘못 만들었다면 이 메시지는 무시해도 됩니다.",
-    "usernamehasherror": "사용자 계정 이름에는 해시 문자가 들어갈 수 없습니다",
     "login-throttled": "로그인에 연속으로 실패하였습니다.\n$1 기다렸다가 다시 시도하세요.",
     "login-abort-generic": "로그인에 실패했습니다 - 중지됨",
     "loginlanguagelabel": "언어: $1",
     "prefs-skin": "스킨",
     "skin-preview": "미리 보기",
     "datedefault": "기본 값",
-    "prefs-beta": "베타 기능",
     "prefs-datetime": "날짜와 시각",
     "prefs-labs": "실험 중인 기능",
     "prefs-user-pages": "사용자 문서",
     "upload-permitted": "허용하는 파일 확장자: $1",
     "upload-preferred": "권장하는 파일 확장자: $1",
     "upload-prohibited": "금지하는 파일 확장자: $1",
-    "uploadlog": "올리기 기록",
     "uploadlogpage": "올리기 기록",
     "uploadlogpagetext": "최근 올라온 파일 목록입니다.\n갤러리 형식으로 확인하고 싶으시다면 [[Special:NewFiles|새 파일 목록]]을 보세요.",
     "filename": "파일 이름",
     "filereuploadsummary": "파일의 바뀜:",
     "filestatus": "저작권 상태:",
     "filesource": "출처:",
-    "uploadedfiles": "파일 올리기",
     "ignorewarning": "경고를 무시하고 파일 저장",
     "ignorewarnings": "모든 경고 무시하기",
     "minlength1": "파일 이름은 적어도 1글자 이상이어야 합니다.",
     "overwroteimage": "사용자가 \"[[$1]]\" 파일의 새 판을 올렸습니다.",
     "uploaddisabled": "올리기 비활성화됨",
     "copyuploaddisabled": "URL로 파일 올리기가 비활성화되어 있습니다.",
-    "uploadfromurl-queued": "올리기 명령이 대기열에 추가됐습니다.",
     "uploaddisabledtext": "파일 올리기 기능이 비활성화되어 있습니다.",
     "php-uploaddisabledtext": "PHP 파일 올리기가 비활성화되었습니다. 파일 올리기 설정을 확인하십시오.",
     "uploadscripted": "이 파일에는 HTML이나 다른 스크립트 코드가 포함되어 있어, 웹 브라우저에서 오류를 일으킬 수 있습니다.",
     "upload-misc-error": "알 수 없는 파일 올리기 오류",
     "upload-misc-error-text": "파일을 올리는 중 알 수 없는 오류가 발생했습니다.\nURL이 올바르고 접근 가능한지를 확인하고 다시 시도하세요.\n문제가 계속되면 [[Special:ListUsers/sysop|관리자]]에게 연락해주세요.",
     "upload-too-many-redirects": "URL이 너무 많은 넘겨주기를 포함하고 있습니다.",
-    "upload-unknown-size": "크기를 알 수 없음",
     "upload-http-error": "HTTP 오류 발생: $1",
     "upload-copy-upload-invalid-domain": "이 도메인에 속하지 않는 웹사이트의 파일을 올릴 수 없습니다.",
     "backend-fail-stream": "\"$1\" 파일을 스트림할 수 없습니다.",
     "img-auth-streaming": "\"$1\" 파일을 전송하는 중입니다.",
     "img-auth-public": "img_auth.php는 개인 위키 파일을 바깥 사이트로 전송하는 기능입니다.\n이 기능은 기본적으로 공개적인 위키에서 사용하도록 설계되어 있습니다.\n보안적인 문제로 기본적으로 img_auth.php 기능은 비활성화되어 있습니다.",
     "img-auth-noread": "\"$1\" 파일을 볼 권한이 없습니다.",
-    "img-auth-bad-query-string": "URL에 잘못된 쿼리 문자열이 있습니다.",
     "http-invalid-url": "잘못된 URL: $1",
     "http-invalid-scheme": "\"$1\"로 시작하는 URL은 지원되지 않습니다.",
     "http-request-error": "알 수 없는 오류로 HTTP 요청에 실패했습니다.",
     "filehist-dimensions": "크기",
     "filehist-filesize": "파일 크기",
     "filehist-comment": "덧글",
-    "filehist-missing": "파일이 없음",
     "imagelinks": "이 파일을 사용하는 문서",
     "linkstoimage": "다음 {{PLURAL:$1|문서 $1개}}가 이 파일을 가리키고 있습니다:",
     "linkstoimage-more": "$1개 이상의 {{PLURAL:$1|문서}}가 이 파일을 가리키고 있습니다.\n다음 목록은 이 파일을 {{PLURAL:$1|가리키는 처음 문서 $1개}}만 보여주고 있습니다.\n이 파일을 가리키는 [[Special:WhatLinksHere/$2|모든 문서 목록]]을 볼 수 있습니다.",
     "listgrouprights-removegroup-self": "자신에게서 다음 {{PLURAL:$2|권한}}을 해제: $1",
     "listgrouprights-addgroup-self-all": "자신에게 모든 권한을 부여",
     "listgrouprights-removegroup-self-all": "자신의 계정에서 모든 권한을 해제",
+    "trackingcategories-name": "메시지명",
     "mailnologin": "보낼 이메일 주소가 없음",
     "mailnologintext": "다른 사용자에게 이메일을 보내려면 [[Special:UserLogin|로그인]]한 다음 [[Special:Preferences|사용자 환경 설정]]에서 자신의 이메일 주소를 저장해야 합니다.",
     "emailuser": "이메일 보내기",
     "emailuser-title-notarget": "사용자에게 이메일 보내기",
     "emailpage": "사용자에게 이메일 보내기",
     "emailpagetext": "이 {{GENDER:$1|사용자}}가 환경 설정에 올바른 이메일 주소를 적었다면, 아래 양식을 통해 이메일을 보낼 수 있습니다.\n이메일을 받은 사용자가 바로 답장할 수 있도록 하기 위해 [[Special:Preferences|사용자 환경 설정]]에 적은 이메일 주소가 \"보내는 사람\" 정보에 들어갑니다. 따라서 받는 사람이 당신에게 직접 답장을 보낼 수 있습니다.",
-    "usermailererror": "메일 개체에서 오류 발생:",
     "defemailsubject": "\"$1\" 사용자가 보낸 {{SITENAME}} 이메일",
     "usermaildisabled": "사용자 이메일 비활성화됨",
     "usermaildisabledtext": "이 위키에서 다른 사용자에게 메일을 보낼 수 없습니다",
     "noemailtitle": "이메일 주소 없음",
     "noemailtext": "이 사용자는 올바른 이메일 주소를 입력하지 않았습니다.",
-    "nowikiemailtitle": "이메일이 허용되지 않음",
     "nowikiemailtext": "이 사용자는 다른 사용자로부터의 이메일을 받지 않도록 설정하였습니다.",
     "emailnotarget": "없는 사용자를 받는 이로 지정하였거나 사용자 이름이 잘못되었습니다.",
     "emailtarget": "받는 사용자 이름 입력",
     "nowatchlist": "주시하는 문서가 아직 없습니다.",
     "watchlistanontext": "주시문서 목록을 보거나 고치려면 $1 하세요.",
     "watchnologin": "로그인하지 않음",
-    "watchnologintext": "주시문서 목록을 고치려면 [[Special:UserLogin|로그인]]해야 합니다.",
     "addwatch": "주시문서 목록에 추가",
     "addedwatchtext": "\"[[:$1]]\" 문서를 [[Special:Watchlist|주시문서 목록]]에 추가했습니다.\n앞으로 이 문서나 관련된 토론 문서가 바뀌면 보일 것입니다.",
     "removewatch": "주시문서 목록에서 제거",
     "watching": "주시 추가 중…",
     "unwatching": "주시 해제 중…",
     "watcherrortext": "\"$1\" 문서에 대한 주시 여부를 바꾸는 중 오류가 발생했습니다.",
-    "enotif_mailer": "{{SITENAME}} 자동 알림 메일",
     "enotif_reset": "모든 문서를 방문한 것으로 표시하기",
     "enotif_impersonal_salutation": "{{SITENAME}} 사용자",
     "enotif_subject_deleted": "{{SITENAME}} $1 문서를 $2 사용자가 {{GENDER:$2|삭제했습니다}}",
     "excontent": "내용: \"$1\"",
     "excontentauthor": "내용: \"$1\" (유일한 편집자는 \"[[Special:Contributions/$2|$2]]\")",
     "exbeforeblank": "비우기 전의 내용: \"$1\"",
-    "exblank": "빈 문서",
     "delete-confirm": "\"$1\" 삭제",
     "delete-legend": "삭제",
     "historywarning": "'''경고:''' 삭제하려는 문서에 이전 {{PLURAL:$1|편집 역사}} 약 $1개가 있습니다:",
     "movepage-page-moved": "\"$1\" 문서를 \"$2\" 문서로 옮겼습니다.",
     "movepage-page-unmoved": "$1 문서를 $2 문서로 옮길 수 없습니다.",
     "movepage-max-pages": "{{PLURAL:$1|문서}}를 최대 $1개 옮겼으며 나머지 문서는 자동으로 옮기지 않습니다.",
-    "movelogpage": "ì\9d´ë\8f\99 기록",
+    "movelogpage": "ì\98®ê¸°ê¸° 기록",
     "movelogpagetext": "아래는 옮겨진 모든 문서의 목록입니다.",
     "movesubpage": "{{PLURAL:$1|하위 문서}}",
     "movesubpagetext": "이 문서에는 다음 {{PLURAL:$1|하위 문서}} $1개가 있습니다.",
     "importunknownsource": "알 수 없는 가져오기 원본 유형",
     "importcantopen": "파일을 열 수 없습니다.",
     "importbadinterwiki": "인터위키 링크가 잘못되었습니다.",
-    "importnotext": "내용이 없습니다",
     "importsuccess": "가져오기 완료!",
-    "importhistoryconflict": "문서 역사가 충돌하는 판이 있습니다. (이전에 이 문서를 가져온 적이 있을 수도 있습니다)",
     "importnosources": "문서를 가져올 출처가 정의되지 않았고 문서 역사 올리기가 비활성화되었습니다.",
     "importnofile": "가져오기용 파일이 올려지지 않았습니다.",
     "importuploaderrorsize": "파일 올리기를 통한 가져오기에 실패했습니다.\n파일이 허용된 크기 제한보다 큽니다.",
index e74b94b..8b71870 100644 (file)
     "disclaimers": "Мийö сöстöмöсь йöз одзын",
     "disclaimerpage": "Project:Мийö сöстöмöсь йöз одзын",
     "edithelp": "Уджкерись понда отсöт",
-    "helppage": "Help:Отсöт",
     "mainpage": "Пондöтчан листбок",
     "mainpage-description": "Пондöтчан листбок",
     "privacy": "Астор дорьян йылiсь",
index abd7894..afbf0ab 100644 (file)
     "accountcreatedtext": "$1 къошулуучугъа тергеу джазыу (аккаунт) къуралды.",
     "createaccount-title": "{{SITENAME}}: тергеу джазыу (аккаунт) къурау",
     "createaccount-text": "Ким эсе да, электрон почтагъызны адресин джазыб  {{SITENAME}} ($4) проектде «$3» пароль бла «$2» тергеу джазыу (аккаунт) къурагъанды. Сиз кириб паролну тюрлендирсегиз тыйыншлыды.\n\nТергеу джазыуну (аккаунтну) халат бла къурагъан эсегиз, игнор этигиз да къоюгъуз бу билдириуню.",
-    "usernamehasherror": "Къошулуучуну атында «#» символ болургъа джарамайда.",
     "login-throttled": "Сиз асыры кёб кере кирирге кюрешгенсиз.\nДжангыдан кёргюнчю бираз заман ётдюрюгюз.",
     "login-abort-generic": "Системагъа кириу джетишимсиз болду",
     "loginlanguagelabel": "Тил: $1",
     "suspicious-userlogout": "Терс браузер неда кэш этиучу прокси берген соруугъа ушагъаны ючюн, Сизни чыгъаргъа сорууугъуз алынмагъанды.",
     "pt-login": "Кириу",
+    "pt-login-button": "Кириу",
     "pt-createaccount": "Аккаунт къурау",
     "pt-userlogout": "Чыгъыу",
     "php-mail-error-unknown": "PHP's mail() функцияда белгили болмагъан халат",
     "prefs-skin": "Джасауу",
     "skin-preview": "Ал къарау",
     "datedefault": "Сайлау джокъду",
-    "prefs-beta": "Бета-амалла",
     "prefs-datetime": "Дата бла сагъат",
     "prefs-labs": "Эксперимент амалла",
     "prefs-user-pages": "Къошулуучуну бетлери",
     "rcshowhideliu-show": "кёргюз",
     "rcshowhideliu-hide": "джашыр",
     "rcshowhideanons": "анонимленикилени $1",
-    "rcshowhidepatr": "$1 патруль этилиннген тюрлендириуле",
+    "rcshowhideanons-show": "кёргюз",
+    "rcshowhideanons-hide": "джашыр",
+    "rcshowhidepatr": "тинтилгенлени $1",
+    "rcshowhidepatr-show": "кёргюз",
+    "rcshowhidepatr-hide": "джашыр",
     "rcshowhidemine": "кесими тюрлендириулерими $1",
     "rcshowhidemine-show": "кёргюз",
     "rcshowhidemine-hide": "джашыр",
     "upload-permitted": "Эркинлик берилген файлланы типлери: $1.",
     "upload-preferred": "Изленнген файлланы типлери: $1.",
     "upload-prohibited": "Джасакъ этилген файлланы типлери: $1.",
-    "uploadlog": "Джюклеулени журналы",
     "uploadlogpage": "Джюклеулени журналы",
     "uploadlogpagetext": "Тюбюнде эм ахыр къошулгъан файлланы тизмеси барды.\nДагъыда [[Special:NewFiles|dosyalджангы файлланы галереясына]] къара, анда джангы джюклеулени юсюнден билгиле толу кёрюгюзюлгендиле.",
     "filename": "Файлны аты",
     "filereuploadsummary": "Файлны тюрлениулери:",
     "filestatus": "Джайылыу хакълары:",
     "filesource": "Къайнакъ:",
-    "uploadedfiles": "Джюкленнген файлла",
     "ignorewarning": "Эсгертиулеге къарамай сакълат файлны",
     "ignorewarnings": "Эсгертиулеге къарама",
     "minlength1": "Файлны аты эм азы бла бир харифден болургъа керекди.",
     "overwroteimage": "«[[$1]]» суратны джангы версиясы джюкленнгенди",
     "uploaddisabled": "Джюклеуге эркинлик джокъду",
     "copyuploaddisabled": "URL кёре джюклеу джукъланыбды.",
-    "uploadfromurl-queued": "Сизни джюклеуюгюз кёзюуге салыннганды.",
     "uploaddisabledtext": "Файлланы джюклеу мадар джукъланыбды",
     "php-uploaddisabledtext": "PHP-да файл джюклеу амал джукъланыбды.\nfile_uploads джарашдырыулагъа бир къарагъыз.",
     "uploadscripted": "Бу файл, браузер бла халатлы таныргъа боллукъ, HTML-код неда скрипт джюрютеди.",
     "upload-misc-error": "Билинмеген джюклеу халат",
     "upload-misc-error-text": "Джюклеуню кёзюуюнде билинмеген халат болду.\nURL-адрес тюз болгъанын осмакълагъыз эмда джангыдан сынагъыз.\nПроблема джангыдан чыкъса, [[Special:ListUsers/sysop|администраторгъа]] джазыгъыз.",
     "upload-too-many-redirects": "URL асыры кёб джибериу тутады",
-    "upload-unknown-size": "Билинмеген ёлчем",
     "upload-http-error": "HTTP хата болду: $1",
     "backend-fail-stream": "«$1» файл окъулмады.",
     "backend-fail-backup": "«$1» файлны резерв копиясын этерге болмайды.",
     "filehist-dimensions": "Ёлчеми",
     "filehist-filesize": "Файлны ёлчеми",
     "filehist-comment": "Эсгериу",
-    "filehist-missing": "Файл джокъду",
     "imagelinks": "Файлны хайырланыуу",
     "linkstoimage": "Бу файлгъа {{PLURAL:$1|1=бет|$1 бет}} джибередиле:",
     "linkstoimage-more": "$1 дегенден артыкъ {{PLURAL:$1|бет}} бу файлгъа джибериу береди.\nБу тизмеде бу файлгъа {{PLURAL:$1|къуру $1 джибериу}} кёргюзюледи.\n[[Special:WhatLinksHere/$2|Толу тизме]] да барды.",
     "emailuser-title-notarget": "Электрон джазма джазыу",
     "emailpage": "Къошулуучугъа письмо джибер",
     "emailpagetext": "Бу къошулуучуну почтасына письмо джиберир ючюн бу форманы толтурургъа боллукъсуз.\nЫзына адрес болуб, сиз [[Special:Preferences|джарашдырыуларыгъызда]] джазгъан адрес белгиленникди, ол себебден сизни письмогъузну аллыкъ сизге тюз джууаб берирге мадарлы боллукъду.",
-    "usermailererror": "Халат ючюн элетктрон письмо ызына къайтды:",
     "defemailsubject": "{{SITENAME}} — $1 къошулуучудан билдириу",
     "usermaildisabled": "Къошулуучуну электрон почтасы джукъланыбды",
     "usermaildisabledtext": "Сиз бу викини башха къошулуучуларына электрон письмола джиберелмейсиз",
     "noemailtitle": "Электрон почтаны адреси джокъду",
     "noemailtext": "Бу къошулуучу керти электрон адресин бермегенди.",
-    "nowikiemailtitle": "Электрон письмо джиберирге эркинлик джокъду",
     "nowikiemailtext": "Бу къошулуучу, башха къошулуучуладан электрон писмо алыргъа излемегенин билдиргенди.",
     "emailtarget": "Аллыкъ къошулуучуну атын джазыгъыз",
     "emailusername": "Къошулуучуну аты:",
     "nowatchlist": "Кёзюгюзде тургъан тизмегиз бошду.",
     "watchlistanontext": "Кёзюгюзде тургъан тизмегизни статьяларын кёрюр неда тюрлендирир ючюн бери ётюгюз: $1.",
     "watchnologin": "Системагъа кирирге керекди.",
-    "watchnologintext": "Кёзюгюзде тургъан тизмегизни тюрлендирир ючюн [[Special:UserLogin|системагъа кирирге керексиз]].",
     "addwatch": "Кёзде тургъан тизмеге къош",
     "addedwatchtext": "«[[:$1]]» бет [[Special:Watchlist|кёзюгюзде тургъан тизмегизге]] къошулду.\nБу бетни эмда муну бла байламлы сюзюу бетни тюрлениулери ол тизмеде белгиленникдиле, [[Special:RecentChanges|джангы тюрлениулени тизмесини]] бетинде уа къалын шрифт бла чертилинникдиле, кёрюрге тынчыракъ болурча.",
     "removewatch": "Кёзде тургъан тизмеден кетер",
     "watchlist-options": "Кёзде тургъан тизмени джарашдырыулары",
     "watching": "Кёзде тургъан тизмеге къошуу...",
     "unwatching": "Кёзде тургъан тизмеден кетериу...",
-    "enotif_mailer": "{{SITENAME}} Билдириу Почта",
     "enotif_reset": "Бютеу бетлени къаралгъанча белгиле",
     "enotif_impersonal_salutation": "{{SITENAME}} къошулуучу",
     "enotif_lastvisited": "Ахыр кириуюгюзден бу кереге дери болгъан бютеу тюрлениулени кёрюр ючюн $1-ге къара.",
     "excontent": "ичиндеги: $1",
     "excontentauthor": "ичиндеги: «$1» (юлюш къошхан джангыз къошулуучу [[Special:Contributions/$2|$2]] эди)",
     "exbeforeblank": "Кетериуню алындагъы ичи: '$1'",
-    "exblank": "бет бош эди",
     "delete-confirm": "«$1» — кетериу",
     "delete-legend": "Кетер",
     "historywarning": "'''Эсгериу:''' кетериле тургъан бетни $1 {{PLURAL:$1|1=версиялы|версиялы}} тарихи барды:",
     "importunknownsource": "Билинмеген импорт къайнакъ типи",
     "importcantopen": "Импорт этилген файл ачылалмады",
     "importbadinterwiki": "Терс интер-вики джибериу",
-    "importnotext": "Бош неда текст джокъду",
     "importsuccess": "Импорт этилиб бошады!",
-    "importhistoryconflict": "Бар болгъан версияланы арасында уруш (бу бет алгъаракъ импорт этилген болур)",
     "importnosources": "Викиле арасы къайнакъ сайланмагъанды эм  тюрлендириулени тарихини тюз джюклеую джукъланыбды.",
     "importnofile": "Импорт ючюн файл джюкленмегенди.",
     "importuploaderrorsize": "Импорт этилген  файлны джюклеую джетишимсиз болду.\nФайл, эркинлик берилген джюклеу ёлчеминден уллуду.",
index bcbcb53..01ba585 100644 (file)
     "disclaimers": "Disklamardèm",
     "disclaimerpage": "Projèkt:Jènèral disklamar",
     "edithelp": "Èdithèp",
-    "helppage": "Help:Kòntèntdèm",
     "mainpage": "Men Pej",
     "mainpage-description": "Men Pej",
     "policy-url": "Project:Pòlisia",
index 923cc66..d2c81e3 100644 (file)
     "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",
index a689a32..1efa02f 100644 (file)
     "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 db5c1be..b74d19f 100644 (file)
     "print": "Drécken",
     "view": "Weisen",
     "edit": "Änneren",
+    "edit-local": "Lokal Beschreiwung änneren",
     "create": "Uleeën",
+    "create-local": "Lokal Beschreiwung derbäisetzen",
     "editthispage": "Dës Säit änneren",
     "create-this-page": "Dës Säit uleeën",
     "delete": "Läschen",
     "accountcreatedtext": "De Benotzerkont fir [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|Diskussioun]]) gouf geschaf.",
     "createaccount-title": "Opmaache vun engem Benotzerkont op {{SITENAME}}",
     "createaccount-text": "Et gouf e Benotzerkont \"$2\" fir Iech op {{SITENAME}} ($4) ugeluecht mat dem Passwuert \"$3\".\nDir sollt Iech aloggen an Äert Passwuert elo änneren.\n\nWann dëse Benotzerkont ongewollt ugeluecht gouf, kënnt Dir dës Noriicht einfach ignoréieren.",
-    "usernamehasherror": "Am Benotzernumm däerfe keng ''hash'' Zeeche sinn",
     "login-throttled": "Dir hutt zevill dacks versicht Iech anzeloggen.\nWaart w.e.g. $1 ier Dir et nach eng Kéier probéiert.",
     "login-abort-generic": "Dir sidd net ageloggt - Aloggen ofgebrach",
     "loginlanguagelabel": "Sprooch: $1",
     "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",
     "upload-permitted": "Erlaabt Formater vun de Fichieren: $1.",
     "upload-preferred": "Fichierszorten déi am beschte funktionéieren: $1.",
     "upload-prohibited": "Verbuede Fichiers Formater: $1.",
-    "uploadlog": "Lëscht vun den eropgeluedene Fichieren",
     "uploadlogpage": "Logbuch vum Eroplueden",
     "uploadlogpagetext": "Dëst ass d'Lëscht vun de rezente Fichieren déi eropgeluede goufen.\nKuckt [[Special:NewFiles|d'Gallerie vun de neie Fichieren]] wann Dir méi e visuellen Iwwerbléck wëllt",
     "filename": "Numm vum Fichier",
     "filereuploadsummary": "Ännerunge vum Fichier:",
     "filestatus": "Copyright Status:",
     "filesource": "Quell:",
-    "uploadedfiles": "Eropgeluede Fichieren",
     "ignorewarning": "Warnung ignoréieren an de Fichier nawell späicheren",
     "ignorewarnings": "Ignoréier all Iwwerschreiwungswarnungen",
     "minlength1": "D'Nimm vu Fichiere musse mindestens e Buschtaf am Numm hunn.",
     "overwroteimage": "huet eng nei Versioun vun \"[[$1]]\" eropgelueden",
     "uploaddisabled": "Pardon, d'Eropluede vu Fichieren ass ausgeschalt.",
     "copyuploaddisabled": "D'Eroplueden iwwer URL ass desaktivéiert.",
-    "uploadfromurl-queued": "Dat wat Dir eropgelueden hutt gouf an d'Waardelëscht agedroen.",
     "uploaddisabledtext": "D'Eropluede vu Fichieren ass ausgeschalt.",
     "php-uploaddisabledtext": "D'Eropluede vu Fichieren ass am PHP desaktivéiert. Kuckt w.e.g. d'Astellung ''file_uploads'' no.",
     "uploadscripted": "An dësem Fichier ass HTML- oder Scriptcode, dee vun engem Webbrowser falsch interpretéiert kéint ginn.",
     "upload-misc-error": "Onbekannte Feeler beim Eroplueden",
     "upload-misc-error-text": "Beim Eroplueden ass en onbekannte Feeler geschitt.\nKuckt d'URL w.e.g. no, a vergewëssert iech datt d'Säit online ass a probéiert et dann nach eng Kéier.\nWann de Problem weider besteet, dann un de [[Special:ListUsers/sysop|Administrateuren]].",
     "upload-too-many-redirects": "Et waren zevill Viruleedungen fir d'URL do",
-    "upload-unknown-size": "Onbekannte Gréisst",
     "upload-http-error": "Et ass en HTTP-Feeler geschitt: $1",
     "upload-copy-upload-invalid-domain": "Vun dësem Domain ass d'Eropluede vu Kopien net méiglech.",
     "backend-fail-stream": "De Fichier $1 konnt net iwwerdroe ginn.",
     "img-auth-streaming": "\"$1\" lueden.",
     "img-auth-public": "D'Funktioun img_auth.php erlaabt et fir Fichieren vun enger privater Wiki erauszeginn.\nDës Wiki ass als ëffentlech Wiki konfiguréiert.\nFir eng optimal Sécherheet ass img_auth.php ausgeschalt.",
     "img-auth-noread": "De Benotzer hut keen Zougang fir \"$1\" ze liesen",
-    "img-auth-bad-query-string": "D'URL huet eng net valabel Rei vun Zeechen.",
     "http-invalid-url": "Net-valabel URL: $1",
     "http-invalid-scheme": "URLe mam Schema \"$1\" ginn net ënnerstëtzt",
     "http-request-error": "D'HTTP-Ufro huet wéinst engem onbekannte Feeler net funktionéiert.",
     "filehist-dimensions": "Dimensiounen",
     "filehist-filesize": "Gréisst vum Fichier",
     "filehist-comment": "Bemierkung",
-    "filehist-missing": "Fichier feelt",
     "imagelinks": "Benotze vu Fichieren",
     "linkstoimage": "Dës {{PLURAL:$1|Säit benotzt|Säite benotzen}} dëse Fichier:",
     "linkstoimage-more": "Méi wéi {{PLURAL:$1|eng Säit ass|$1 Säite si}} mat dësem Fichier verlinkt.\nDës Lëscht weist nëmmen {{PLURAL:$1|den éischte Link|déi éischt $1 Linken}} op dëse Fichier.\nEng [[Special:WhatLinksHere/$2|komplett Lëscht]] ass disponibel.",
     "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",
     "emailuser-title-notarget": "Dem Benotzer eng E-Mail schécken",
     "emailpage": "Dem Benotzer eng E-Mail schécken",
     "emailpagetext": "Dir kënnt mat dësem Formulaire {{GENDER:$1|dësem Benotzer}} en E-Mail-Message schécken.\nD'E-Mail-Adress, déi Dir an [[Special:Preferences|Ären Astellungen]] aginn hutt, steet an der \"From\" Adress vun der Mail, sou datt den Destinataire Iech direkt äntwerte kann.",
-    "usermailererror": "E-Mail-Objet mellt deen heite Feeler:",
     "defemailsubject": "{{SITENAME}} E-Mail vum Benotzer \"$1\"",
     "usermaildisabled": "Benotzer E-Mail ausgeschalt",
     "usermaildisabledtext": "Dir kënnt op dëser Wiki anere Benotzer keng E-Mail schécken",
     "noemailtitle": "Keng E-Mailadress",
     "noemailtext": "Dëse Benotzer huet keng valabel E-Mail-Adress uginn.",
-    "nowikiemailtitle": "Keng E-Mail erlaabt",
     "nowikiemailtext": "Dëse Benotzer wëllt keng E-Maile vun anere Benotzer kréien.",
     "emailnotarget": "Et gëtt keen oder just een net valabele Benotzernumm fir den Empfänger.",
     "emailtarget": "Gitt de Benotzernumm vum Empfänger an",
     "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",
     "watching": "Iwwerwaachen …",
     "unwatching": "Net méi iwwerwaachen …",
     "watcherrortext": "Beim Ännere vun den Astellunge vun der Iwwerwaachungslëscht fir \"$1\" ass e Feeler geschitt.",
-    "enotif_mailer": "{{SITENAME}} E-Mail-Informatiounssystem",
     "enotif_reset": "All Säiten als besicht markéieren",
     "enotif_impersonal_salutation": "{{SITENAME}}-Benotzer",
     "enotif_subject_deleted": "D'{{SITENAME}}-Säit $1 gouf vum {{gender:$2|$2}} geläscht",
     "excontent": "Inhalt war: '$1'",
     "excontentauthor": "Op der Säit stoung: '$1' (An als eenzegen dru geschriwwen hat de Benotzer '[[Special:Contributions/$2|$2]]').",
     "exbeforeblank": "Den Inhalt virum Läsche war: '$1'",
-    "exblank": "D'Säit war eidel",
     "delete-confirm": "Läsche vu(n) \"$1\"",
     "delete-legend": "Läschen",
     "historywarning": "'''Opgepasst:''' Déi Säit déi Dir läsche wëllt huet en Historique mat ongeféier $1 {{PLURAL:$1|Versioun|Versiounen}}:",
     "importunknownsource": "Onbekannt Importquell",
     "importcantopen": "De Fichier dee sollt importéiert gi konnt net opgemaach ginn",
     "importbadinterwiki": "Falschen Interwiki-Link",
-    "importnotext": "Eidel oder keen Text",
     "importsuccess": "Den Import ass fäerdeg!",
-    "importhistoryconflict": "Et gëtt Konflikter am Historique vun de Versiounen, (méiglecherweis gouf dës Säit virdrun importéiert).",
     "importnosources": "Fir den Transwiki-Import si keng Quellen definéiert an et ass net méiglech fir Säite mat alle Versiounen aus dem Transwiki-Tëschespäicher eropzelueden.",
     "importnofile": "Et gouf keen importéierte Fichier eropgelueden",
     "importuploaderrorsize": "D'Eropluede vum importéierte Fichier huet net funktionéiert. De Fichier ass méi grouss wéi maximal erlaabt.",
index 333ce85..bb43de7 100644 (file)
     "prefs-skin": "Къайдадиз ттунин тема",
     "skin-preview": "Сифтедин килигун",
     "datedefault": "Туькlуьрмир",
-    "prefs-beta": "Бета-мумкинвилер",
     "prefs-datetime": "Нумра ва вахт",
     "prefs-labs": "Экспериментдин мумкинвилер",
     "prefs-personal": "Уртахдин профил",
index 1e9a87c..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",
index 4d99866..f91cd20 100644 (file)
     "disclaimers": "Kūondõkst",
     "disclaimerpage": "Project:Kūondõkst",
     "edithelp": "Redigīerimiz opātõks",
-    "helppage": "Help:Sižāli",
     "mainpage": "Eḑḑilēḑ",
     "mainpage-description": "Eḑḑilēḑ",
     "portal": "Kubgõnd vǟrõd",
index b1d0b91..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",
index 4d7cc6b..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",
index 88c67fa..30a0807 100644 (file)
     "accountcreated": "Konts izveidots",
     "accountcreatedtext": "Lietotāja konts priekš $1 tika izveidots.",
     "createaccount-title": "Lietotāja konta izveidošana {{grammar:lokatīvs|{{SITENAME}}}}",
-    "usernamehasherror": "Lietotājvārds nevar saturēt hash simbolus",
     "login-throttled": "Jūs esat veicis pārāk daudz pieslēgšanās mēģinājumus.\nLūdzu, uzgaidiet $1 pirms mēģiniet vēlreiz.",
     "login-abort-generic": "Jūsu pieteikšanās bija neveiksmīga — Darbība pārtraukta",
     "loginlanguagelabel": "Valoda: $1",
     "showhideselectedversions": "Rādīt/slēpt izvēlētās versijas",
     "editundo": "atcelt",
     "diff-empty": "(Nav atšķirību)",
+    "diff-multi-sameuser": "({{PLURAL:$1|Viena starpversija|$1 starpversijas}}, ko izdarījis viens lietotājs, nav parādīta{{PLURAL:$1||s}})",
+    "diff-multi-otherusers": "({{PLURAL:$1|Viena starpversija|$1 starpversijas}}, ko {{PLURAL:$2|saglabājis|saglabājuši}} {{PLURAL:$2|viens cits lietotājs|$2 lietotāji}}, nav parādīta{{PLURAL:$1||s}})",
+    "diff-multi-manyusers": "({{PLURAL:$1|Viena starpversija|$1 starpversijas}}, ko saglabājuši vairāk nekā $2 {{PLURAL:$2|lietotājs|lietotāji}}, nav parādīta{{PLURAL:$1||s}})",
     "searchresults": "Meklēšanas rezultāti",
     "searchresults-title": "Meklēšanas rezultāti \"$1\"",
     "toomanymatches": "Tika atgriezti poārāk daudzi rezultāti, lūdzu pamēģini citādāku pieprasījumu",
     "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",
     "upload-permitted": "Atļautie failu tipi: $1.",
     "upload-preferred": "Ieteicamie failu tipi: $1.",
     "upload-prohibited": "Aizliegtie failu tipi: $1.",
-    "uploadlog": "augšupielādes reģistrs",
     "uploadlogpage": "Augšupielādes reģistrs",
     "uploadlogpagetext": "Zemāk ir redzams jaunāko augšuplādēto failu saraksts.\nPārskatāmāka versija ir pieejama [[Special:NewFiles|jauno attēlu galerijā]].",
     "filename": "Faila nosaukums",
     "filereuploadsummary": "Faila izmaiņas:",
     "filestatus": "Autortiesību statuss:",
     "filesource": "Izejas kods:",
-    "uploadedfiles": "Augšupielādēja failus",
     "ignorewarning": "Ignorēt brīdinājumu un saglabāt failu",
     "ignorewarnings": "Ignorēt visus brīdinājumus",
     "minlength1": "Failu vārdiem jābūt vismaz vienu simbolu gariem.",
     "overwroteimage": "augšupielādēta jauna \"[[$1]]\" versija",
     "uploaddisabled": "Augšupielāde atslēgta",
     "copyuploaddisabled": "URL augšupielādes nav atļautas.",
-    "uploadfromurl-queued": "Tava augšupielāde tika pievienota rindā.",
     "uploaddisabledtext": "Failu augšupielāde ir atslēgta.",
     "php-uploaddisabledtext": "Failu augšupielāde ir atslēgta PHP.\nLūdzu, pārbaudi file_uploads uzstādījumu.",
     "uploadscripted": "Šis fails satur HTML vai skriptu kodu, kuru, interneta pārlūks, var kļūdas pēc, mēģināt interpretēt (ar potenciāli sliktām sekām).",
     "upload-file-error-text": "Iekšējā kļūda, mēģinot izveidot pagaidu failu uz servera.\nLūdzu, sazinieties ar [[Special:ListUsers/sysop|administratoru.]]",
     "upload-misc-error": "Nezināma augšupielādes kļūda",
     "upload-too-many-redirects": "URL sastāvēja pārāk daudz pāradresāciju",
-    "upload-unknown-size": "Nezināms izmērs",
     "upload-http-error": "HTTP kļūda: $1",
     "backend-fail-stream": "Nevar straumēt failu $1.",
     "backend-fail-backup": "Nevar dublēt failu $1.",
     "filehist-dimensions": "Izmēri",
     "filehist-filesize": "Faila izmērs",
     "filehist-comment": "Komentārs",
-    "filehist-missing": "Fails pazudis",
     "imagelinks": "Faila lietojums",
     "linkstoimage": "{{PLURAL:$1|Šajā lapā ir saite|Šajās $1 lapās ir saites}} uz šo failu:",
     "nolinkstoimage": "Nevienā lapā nav norāžu uz šo attēlu.",
     "emailuser-title-notarget": "Sūtīt e-pastu lietotājam",
     "emailpage": "Sūtīt e-pastu lietotājam",
     "emailpagetext": "Ar šo veidni ir iespējams nosūtīt e-pastu šim lietotājam.\nTā e-pasta adrese, kuru tu esi norādījis [[Special:Preferences|savā izvēļu lapā]], parādīsies e-pasta \"From\" lauciņā, tādejādi saņēmējs varēs tev atbildēt.",
-    "usermailererror": "Pasta objekts atgrieza kļūdu:",
     "defemailsubject": "{{SITENAME}} e-pasts no lietotāja \"$1\"",
     "usermaildisabled": "Lietotāja e-pasts atslēgts",
     "usermaildisabledtext": "Jūs nevarat sūtīt e-pastu citiem lietotājiem šajā viki",
     "noemailtitle": "Nav e-pasta adreses",
     "noemailtext": "Šis lietotājs nav norādījis derīgu e-pasta adresi.",
-    "nowikiemailtitle": "E-pasts nav atļauts",
     "nowikiemailtext": "Šis lietotājs ir vēlējies nesaņemt e-pastu no citiem lietotājiem.",
     "emailnotarget": "Neeksistējošs vai nederīgs saņēmēja lietotājvārds.",
     "emailtarget": "Ievadiet saņēmēja lietotājvārdu",
     "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",
     "watchlist-options": "Uzraugāmo rakstu saraksta opcijas",
     "watching": "Uzrauga...",
     "unwatching": "Neuzrauga...",
-    "enotif_mailer": "{{SITENAME}} paziņojumu izsūtīšana",
     "enotif_reset": "Atzīmēt visas lapas kā apskatītas",
     "enotif_impersonal_salutation": "{{SITENAME}} lietotājs",
     "enotif_lastvisited": "$1 lai apskatītos visas izmaiņas kopš tava pēdējā apmeklējuma.",
     "excontent": "lapas saturs bija: '$1'",
     "excontentauthor": "saturs bija: \"$1\" (vienīgais autors: [[Special:Contributions/$2|$2]])",
     "exbeforeblank": "lapas saturs pirms satura dzēšanas bija šāds: '$1'",
-    "exblank": "lapa bija tukša",
     "delete-confirm": "Dzēst \"$1\"",
     "delete-legend": "Dzēšana",
     "historywarning": "'''Brīdinājums:''' Lapai, ko tu gatavojies dzēst, ir vēsture ar aptuveni $1 {{PLURAL:$1|versiju|versijām}}:",
     "importunknownsource": "Nezināms importēšanas avota veids",
     "importcantopen": "Nevarēja atvērt importējamo failu",
     "importbadinterwiki": "Slikta starpviki saite",
-    "importnotext": "Tukšs vai nav teksta",
     "importsuccess": "Importēšana pabeigta!",
     "importnosources": "Tiešā hronoloģijas augšuplāde ir atslēgta. Nav definēts neviens ''Transwiki'' importa avots (''source'').",
     "importnofile": "Neviens importējamais fails netika augšupielādēts.",
index b06b29b..119314f 100644 (file)
     "accountcreatedtext": "[[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|書]])簿增矣。",
     "createaccount-title": "於{{SITENAME}}增簿",
     "createaccount-text": "有人於{{SITENAME}}用爾之電郵增名為 \"$2\" 之簿 ($4),符節為 \"$3\" 。汝應登,再改符節也。\n\n如簿誤增,爾可略之。",
-    "usernamehasherror": "簿名無含切細符也",
     "login-throttled": "爾多試於此簿登中。\n請候再試之。",
     "login-abort-generic": "登簿未成——棄",
     "loginlanguagelabel": "語:$1",
     "prefs-skin": "面版",
     "skin-preview": "草覽",
     "datedefault": "原註",
-    "prefs-beta": "試灶",
     "prefs-datetime": "日時",
     "prefs-personal": "概簿",
     "prefs-rc": "近易",
     "upload-permitted": "可之物類:$1。",
     "upload-preferred": "議之物類:$1。",
     "upload-prohibited": "禁之物類:$1。",
-    "uploadlog": "誌獻",
     "uploadlogpage": "誌獻",
     "uploadlogpagetext": "近獻如下。\n看[[Special:NewFiles|新畫獻]]示獻功。",
     "filename": "名",
     "filereuploadsummary": "動:",
     "filestatus": "授權:",
     "filesource": "源:",
-    "uploadedfiles": "進獻",
     "ignorewarning": "強儲之",
     "ignorewarnings": "警略。",
     "minlength1": "名務逾一字元。",
     "overwroteimage": "新置「[[$1]]」矣",
     "uploaddisabled": "進獻已阻",
     "copyuploaddisabled": "由URL之貢被禁也。",
-    "uploadfromurl-queued": "爾之貢已排之。",
     "uploaddisabledtext": "檔之貢被禁也。",
     "php-uploaddisabledtext": "PHP之貢被禁也。查 file_uploads 之。",
     "uploadvirus": "此檔含毒也!\n詳:$1",
     "upload-warning-msg": "爾自[$2]之貢出問。爾可回[[Special:Upload/stash/$1|貢表]]修此問。",
     "upload-proto-error": "協訂錯誤",
     "upload-too-many-redirects": "網址含多轉",
-    "upload-unknown-size": "未知之積",
     "upload-http-error": "發一HTTP之錯:$1",
     "backend-fail-notexists": "無檔 $1 。",
     "backend-fail-alreadyexists": "$1 已含。",
     "filehist-dimensions": "度",
     "filehist-filesize": "檔幅",
     "filehist-comment": "註",
-    "filehist-missing": "失檔",
     "imagelinks": "檔所繫者",
     "linkstoimage": "下頁連本檔有$1:",
     "linkstoimage-more": "連檔有多於$1。\n下表示連檔之首$1。\n[[Special:WhatLinksHere/$2|整表]]可供之閱也。",
     "emailuser": "捎君",
     "emailpage": "捎書",
     "emailpagetext": "表下捎焉,以郵制君。\n署[[Special:Preferences|子簿郵]]以候往返。",
-    "usermailererror": "驛報有誤:",
     "defemailsubject": "{{SITENAME}}來書",
     "usermaildisabled": "無他人之郵",
     "usermaildisabledtext": "無發電郵於wiki上之他戶也",
     "noemailtitle": "無郵",
     "noemailtext": "此君無郵。",
-    "nowikiemailtitle": "無許之郵",
     "nowikiemailtext": "此君謝收郵之。",
     "email-legend": "發郵至{{SITENAME}}之另一簿",
     "emailfrom": "自:",
     "nowatchlist": "無哨",
     "watchlistanontext": "$1以治哨",
     "watchnologin": "未登簿",
-    "watchnologintext": "[[Special:UserLogin|登簿]]以治哨。",
     "addedwatchtext": "\"[[:$1]]\"哨派矣。後有易、議者可見於[[Special:Watchlist|哨站]],且'''粗體'''列於[[Special:RecentChanges|近易]]。",
     "removedwatchtext": "\"[[:$1]]\"[[Special:Watchlist|哨]]撤矣。",
     "watch": "派哨",
     "watchlist-options": "哨項",
     "watching": "出陣…",
     "unwatching": "收兵…",
-    "enotif_mailer": "{{SITENAME}}報",
     "enotif_reset": "令為盡閱",
     "enotif_impersonal_salutation": "貴客",
     "enotif_lastvisited": "自子出簿,有易見$1。",
     "excontent": "文乃「$1」",
     "excontentauthor": "文乃「$1」,乃「[[Special:Contributions/$2|$2]]」獨作。",
     "exbeforeblank": "清文前乃為:「$1」",
-    "exblank": "缺頁",
     "delete-confirm": "刪\"$1\"",
     "delete-legend": "刪",
     "historywarning": "警示,此頁約有誌$1:",
     "importunknownsource": "入類不明",
     "importcantopen": "入未可啟",
     "importbadinterwiki": "維基內鏈壞",
-    "importnotext": "空檔或無文",
     "importsuccess": "入匯成矣!",
-    "importhistoryconflict": "舊審沖,疑早存焉",
     "importnosources": "互匯而未定入源,審、誌不予直進。",
     "importnofile": "無匯入也。",
     "importuploaderrorsize": "檔未入匯。幅越焉。",
index 9b01e23..6446d43 100644 (file)
     "disclaimers": "Kʼabuli na var ixvenu ondepe",
     "disclaimerpage": "Project:Mtelot kʼabuli na var ixvenu ondepe",
     "edithelp": "Muçʼoşi iktirinen?",
-    "helppage": "Help:Doloxe na renanpe",
     "mainpage": "Dudi Butʼkʼa",
     "mainpage-description": "Dudi But'k'a",
     "privacy": "Şinaxeri Hakʼepe",
index bcf193b..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": "साकांक्ष सूचीसँ हटाउ",
index 5e2654b..28ceac7 100644 (file)
     "nowatchlist": "Мезеге аш тонь мельгеваномасот.",
     "watchlistanontext": "$1 тонь ванома мельгеваномаста лопат ваноманкса эли петнеманкса.",
     "watchnologin": "Апак сувак",
-    "watchnologintext": "Тондейть эряви [[Special:UserLogin|сувамс]] тонь мельгеваномацень петнеманкса.",
     "addedwatchtext": "Лопась \"[[:$1]]\" сувафнезь тонь [[Special:Watchlist|Мельгеваномасот]].\nСяда тов тя лопать ди мархтонза сюлмаф Корхнема лопать полафнематне кармайхть тякшстафтовома   тя лувомас, сяда тёждяень няевомаснонды синь тага кармайхть сёрмадовома  [[Special:RecentChanges|мекольце полафнематнень лувомас]] '''эчке тяшксса'''.\n\nУлендяряй тонь мяльце тя лопать нардамс тонь мельгеваномастот, люпштак \"аф ваномс мельге\" лопань вярдень виде ужеса.",
     "removedwatchtext": "Лопась \"[[:$1]]\" нардафоль [[Special:Watchlist|тонь мельгеванома лувомастот]].",
     "watch": "Ватт мельге",
index c2fc30d..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",
index dc2fc1e..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",
index ecbd5b9..6224762 100644 (file)
     "permalink": "Постојана врска",
     "print": "Печати",
     "view": "Преглед",
+    "view-foreign": "Погл. на $1",
     "edit": "Уреди",
+    "edit-local": "Уреди локален опис",
     "create": "Создај",
+    "create-local": "Додај локален опис",
     "editthispage": "Уреди ја страницава",
     "create-this-page": "Создај ја оваа страница",
     "delete": "Избриши",
     "accountcreatedtext": "Корисничкта сметка за [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|разговор]]) е направена.",
     "createaccount-title": "Создавање на сметка за {{SITENAME}}",
     "createaccount-text": "Некој направил сметка со вашата е-поштенска адреса на {{SITENAME}} ($4) со име „$2“ и  лозинка „$3“.\nБи требало сега да се пријавите и да ја промените вашата лозинка.\n\nМожете да ја занемарите оваа порака ако сметката била направена по грешка.",
-    "usernamehasherror": "Корисничкото име не може да содржи тараба",
     "login-throttled": "Имате премногу обиди за најава за кратко време.\nПочекајте $1 пред да се обидете повторно.",
     "login-abort-generic": "Најавата е неуспешна - Прекинато",
     "loginlanguagelabel": "Јазик: $1",
     "prefs-skin": "Руво",
     "skin-preview": "Преглед",
     "datedefault": "Небитно",
-    "prefs-beta": "Бета-можности",
     "prefs-datetime": "Датум и време",
     "prefs-labs": "Експериментални можности",
     "prefs-user-pages": "Кориснички страници",
     "upload-permitted": "Допуштени податотечни типови: $1.",
     "upload-preferred": "Претпочитани податотечни типови: $1.",
     "upload-prohibited": "Недопуштени податотечни типови: $1.",
-    "uploadlog": "дневник на подигања",
     "uploadlogpage": "Дневник на подигања",
     "uploadlogpagetext": "Наведен е список на најновите подигања на податотеки.\nПогледнете ја [[Special:NewFiles|галеријата на нови податотеки]] за визуелен преглед.",
     "filename": "Име на податотеката",
     "filereuploadsummary": "Измени во податотеката:",
     "filestatus": "Copyright статус:",
     "filesource": "Извор:",
-    "uploadedfiles": "Подигнати податотеки",
     "ignorewarning": "Занемари ги предупредувањата и зачувај ја податотеката",
     "ignorewarnings": "Занемари предупредувања",
     "minlength1": "Името на податотеката мора да содржи барем една буква.",
     "overwroteimage": "подигнато нова верзија на „[[$1]]“",
     "uploaddisabled": "Забрана за подигања",
     "copyuploaddisabled": "Подигањето од URL е оневозможено.",
-    "uploadfromurl-queued": "Вашето подигање е ставено во редица.",
     "uploaddisabledtext": "Подигањето на податотеки е оневозможено.",
     "php-uploaddisabledtext": "Подигањето на податотеки е оневозможено во PHP. \nПроверете го нагодувањето file_uploads.",
     "uploadscripted": "Податотеката содржи HTML-код или сценарио што може погрешно да се протолкува во прелистувачот.",
     "upload-misc-error": "Непозната грешка при подигањето",
     "upload-misc-error-text": "Се појави грешка при подигањето.\nПроверете дали URL-адресата е правилна и достапна, па обидете се повторно.\nАко пак се појави проблем, обратете се кај некој [[Special:ListUsers/sysop|администратор]].",
     "upload-too-many-redirects": "Оваа URL адреса содржеше премногу пренасочувања",
-    "upload-unknown-size": "Непозната големина",
     "upload-http-error": "HTTP грешка: $1",
     "upload-copy-upload-invalid-domain": "Примероци од подигањата не се достапни на овој домен.",
     "backend-fail-stream": "Не можев да ја емитувам податотеката $1.",
     "img-auth-streaming": "Емитување „$1“.",
     "img-auth-public": "Функцијата на img_auth.php служи за излез на податотеки од лични викија.\nОва вики е нагодено како јавно вики.\nОд причини на оптимална сигурност, img_auth.php е оневозможен.",
     "img-auth-noread": "Корисникот нема пристап за читање на „$1“.",
-    "img-auth-bad-query-string": "URL-адресата има неважечка низа за барање.",
     "http-invalid-url": "Неважечка URL: $1",
     "http-invalid-scheme": "Не се поддржани URL-адреси со шема „$1“",
     "http-request-error": "Неуспешно HTTP барање поради непозната грешка.",
     "filehist-dimensions": "Димензии",
     "filehist-filesize": "Големина",
     "filehist-comment": "Коментар",
-    "filehist-missing": "Непостоечка податотека",
     "imagelinks": "Употреба на податотеката",
     "linkstoimage": "До оваа податотека {{PLURAL:$1|води следнава страница|водат следниве $1 страници}}:",
     "linkstoimage-more": "Повеќе од {{PLURAL:$1|една страница е поврзана|$1 страници се поврзани}} со оваа податотека.\nСледниов список {{PLURAL:$1|ја прикажува само првата поврзана страница|ги прикажува само првите $1 поврзани страници}} до оваа податотека.\nЦелосен список може да добиете [[Special:WhatLinksHere/$2|тука]].",
     "listgrouprights-removegroup-self": "Може да брише {{PLURAL:$2|група|групи}} од сопствената корисничка сметка: $1",
     "listgrouprights-addgroup-self-all": "Може да ги додаде сите групи на сопствената корисничка сметка",
     "listgrouprights-removegroup-self-all": "Може да ги избрише сите групи од сопствената корисничка сметка",
+    "listgrouprights-namespaceprotection-header": "Ограничувања за именски простори",
+    "listgrouprights-namespaceprotection-namespace": "Именски простор",
+    "listgrouprights-namespaceprotection-restrictedto": "Права што им овозможуваат на корисниците да уредуваат",
     "trackingcategories": "Следачки категории",
     "trackingcategories-summary": "На страницава се наведени следачки категории што автоматски се пополнуваат од програмот на МедијаВики. Нивните називи можат да се сменат со измена на соодветните системски пораки во именскиот простор {{ns:8}}.",
     "trackingcategories-msg": "Следачка категорија",
     "trackingcategories-name": "Назив на пораката",
     "trackingcategories-desc": "Критериуми за вклучување",
-    "noindex-category-desc": "СÑ\82Ñ\80аниÑ\86аÑ\82а Ñ\81одÑ\80жи Ð²Ð¾Ð»Ñ\88ебен Ð·Ð±Ð¾Ñ\80 <nowiki>__NOINDEX__</nowiki> (и Ñ\81е Ð½Ð°Ð¾Ñ\93а Ð²Ð¾ Ð¸Ð¼ÐµÐ½Ñ\81ки Ð¿Ñ\80оÑ\81Ñ\82оÑ\80 ÐºÐ°Ñ\98Ñ\88Ñ\82о Ðµ Ð´Ð¾Ð·Ð²Ð¾Ð»ÐµÐ½), Ð¿Ð° Ð·Ð°Ñ\82оа Ð½Ðµ Ñ\81е Ð¸Ð½Ð´ÐµÐºÑ\81иÑ\80а Ð¾Ð´ Ñ\80обоÑ\82и.",
-    "index-category-desc": "Страницата содржи <nowiki>__INDEX__</nowiki> (и се наоѓа во именски простор кајшто ова е дозволено), па затоа се индексира од роботи, што инаку не би било.",
-    "post-expand-template-inclusion-category-desc": "По проширувањето на сите шаблони, страницата е поголема од $wgMaxArticleSize, па затоа некои шаблони не се проширени.",
-    "post-expand-template-argument-category-desc": "По проширување на шаблонски аргумент (нешто во тројни кадрави загради, како на пр. {{{Foo}}}), страницата е поголема од $wgMaxArticleSize.",
+    "noindex-category-desc": "РобоÑ\82иÑ\82е Ð½Ðµ Ñ\98а Ð¸Ð½Ð´ÐµÐºÑ\81иÑ\80ааÑ\82 Ñ\81Ñ\82Ñ\80аниÑ\86ава Ð±Ð¸Ð´ÐµÑ\98Ñ\9cи Ð³Ð¾ Ñ\81одÑ\80жи Ð²Ð¾Ð»Ñ\88ебниоÑ\82 Ð·Ð±Ð¾Ñ\80 <code><nowiki>__NOINDEX__</nowiki></code> Ð¸ Ñ\81е Ð½Ð°Ð¾Ñ\93а Ð²Ð¾ Ð¸Ð¼ÐµÐ½Ñ\81ки Ð¿Ñ\80оÑ\81Ñ\82оÑ\80 ÐºÐ°Ñ\98Ñ\88Ñ\82о Ðµ Ð´Ð¾Ð·Ð²Ð¾Ð»ÐµÐ½.",
+    "index-category-desc": "Страницата содржи <code><nowiki>__INDEX__</nowiki></code> (и се наоѓа во именски простор кајшто ова е дозволено), па затоа се индексира од роботи, што инаку не би било.",
+    "post-expand-template-inclusion-category-desc": "По проширувањето на сите шаблони, страницата е поголема од <code>$wgMaxArticleSize</code>, па затоа некои шаблони не се проширени.",
+    "post-expand-template-argument-category-desc": "По проширување на шаблонски аргумент (нешто во тројни кадрави загради, како на пр. <code>{{{Foo}}})</code>, страницата е поголема од <code>$wgMaxArticleSize</code>.",
     "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>, што значи дека по основно не се прикажува во страниците.",
+    "hidden-category-category-desc": "Ова е категорија што содржи <code><nowiki>__HIDDENCAT__</nowiki></code>, што значи дека по основно не се прикажува во страниците.",
     "trackingcategories-nodesc": "Нема опис.",
     "trackingcategories-disabled": "Категоријата е оневозможена",
     "mailnologin": "Нема адреса за праќање",
     "emailuser-title-notarget": "Е-пошта за корисникот",
     "emailpage": "Е-пошта",
     "emailpagetext": "Можете да го употребите следниов образец за да му испратите е-пошта на овој {{GENDER:$1|корисник}}.\nАдреса која ја имате наведено во [[Special:Preferences|вашите нагодувања]] ќе се прикаже во полето „Од“ на пораката, со што примачот ќе може да ви одговори директно вам.",
-    "usermailererror": "Настана следната грешка при праќање е-пошта:",
     "defemailsubject": "{{SITENAME}} — писмо од корисникот „$1“",
     "usermaildisabled": "Корисничката е-пошта е оневозможена",
     "usermaildisabledtext": "Не можете да испратите е-порака до дрги корисници на ова вики",
     "noemailtitle": "Нема е-поштенска адреса",
     "noemailtext": "Овој корисник нема наведено важечка е-поштенска адреса.",
-    "nowikiemailtitle": "Не е допуштено користење на е-пошта",
     "nowikiemailtext": "Овој корисник избрал да не прима е-пошта од други корисници.",
     "emailnotarget": "Непостоечко или неважечко корисничко име за примачот.",
     "emailtarget": "Внесете го корисничкото име на примачот",
     "nowatchlist": "Немате ништо во списокот на набљудувања.",
     "watchlistanontext": "Треба да сте $1 за да можете да го прегледувате и уредувате списокот на набљудувања.",
     "watchnologin": "Не сте најавени",
-    "watchnologintext": "Мора да сте [[Special:UserLogin|најавени]] за да го менувате списокот на набљудувања.",
     "addwatch": "Додај во списокот на набљудувања",
     "addedwatchtext": "Страницата „[[:$1]]“ е додадена во [[Special:Watchlist|списокот на набљудувања]].\nИдните промени на оваа страница и нејзината страница за разговор ќе се прикажуваат таму.",
     "removewatch": "Отстрани од списокот на набљудувања",
     "watching": "Набљудување...",
     "unwatching": "Отстранувам од набљудувани...",
     "watcherrortext": "Се појави грешка при менувањето на вашите нагодувања списокот на набљудувања за „$1“.",
-    "enotif_mailer": "{{SITENAME}} Систем за известување",
     "enotif_reset": "Означи ги сите страници како посетени",
     "enotif_impersonal_salutation": "Википедија корисник",
     "enotif_subject_deleted": "Страницата $1 на {{SITENAME}} е избришана од {{gender:$2|$2}}",
     "excontent": "содржината беше: '$1'",
     "excontentauthor": "содржината беше: '$1' (и единствениот автор беше '$2')",
     "exbeforeblank": "содржината пред бришењето беше: '$1'",
-    "exblank": "страницата беше празна",
     "delete-confirm": "Избриши „$1“",
     "delete-legend": "Бришење",
     "historywarning": "'''Предупредување:''' Страницата што сакате да ја избришете има историја со околу $1 {{PLURAL:$1|преработка|преработки}}:",
     "importunknownsource": "Непознат тип за внесување",
     "importcantopen": "Не може да се отвори увезената податотека",
     "importbadinterwiki": "Лоша меѓувики-врска",
-    "importnotext": "Празно или без текст",
     "importsuccess": "Увезувањето е завршено!",
-    "importhistoryconflict": "Постои конфликтна историја на верзиите (можно е страницата веќе да била внесена)",
     "importnosources": "Нема определено меѓувики-извори за увоз и директните подигања на историја се оневозможени.",
     "importnofile": "Нема подигнато увозна податотека.",
     "importuploaderrorsize": "Подигањето на увозната податотека не успеа.\nПодатотеката ја надминува допуштената големина.",
index e576e7e..86c4c12 100644 (file)
     "permalink": "സ്ഥിരംകണ്ണി",
     "print": "അച്ചടിയ്ക്കുക",
     "view": "കാണുക",
+    "view-foreign": "$1 സംരംഭത്തിൽ കാണുക",
     "edit": "തിരുത്തുക",
+    "edit-local": "ഇവിടുത്തെ വിവരണം തിരുത്തുക",
     "create": "ഈ താൾ സൃഷ്ടിക്കുക",
+    "create-local": "ഇവിടെ വിവരണം ചേർക്കുക",
     "editthispage": "ഈ താൾ തിരുത്തുക",
     "create-this-page": "ഈ താൾ സൃഷ്ടിക്കുക",
     "delete": "മായ്ക്കുക",
     "pool-timeout": "പൂട്ട് മാറാനുള്ള കാത്തിരിപ്പ് സമയം",
     "pool-queuefull": "പൂൾ ക്യൂ നിറഞ്ഞിരിക്കുന്നു",
     "pool-errorunknown": "അപരിചിതമായ പിഴവ്",
+    "pool-servererror": "പൂൾ കൗണ്ടർ സേവനം ലഭ്യമല്ല ($1).",
     "aboutsite": "{{SITENAME}} സം‌രംഭത്തെക്കുറിച്ച്",
     "aboutpage": "Project:വിവരണം",
     "copyright": "പ്രത്യേകം പറയാത്ത പക്ഷം ഉള്ളടക്കം $1 പ്രകാരം ലഭ്യം.",
     "accountcreatedtext": "[[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|talk]]) എന്ന ഉപയോക്താവിനായി അംഗത്വം സൃഷ്ടിക്കപ്പെട്ടിരിക്കുന്നു.",
     "createaccount-title": "{{SITENAME}} സംരംഭത്തിൽ അംഗത്വം സൃഷ്ടിക്കൽ",
     "createaccount-text": "{{SITENAME}} സംരംഭത്തിൽ ($4) താങ്കളുടെ ഇമെയിൽ വിലാസത്തിൽ ആരോ ഒരു അംഗത്വം \"$2\" എന്ന ഉപയോക്തൃനാമത്തിൽ ഉണ്ടാക്കിയിരിക്കുന്നു (രഹസ്യവാക്ക്: \"$3\").  താങ്കൾ ഇപ്പോൾ ലോഗിൻ ചെയ്തു രഹസ്യവാക്ക് മാറ്റേണ്ടതാകുന്നു.\n\nഅംഗത്വം അബദ്ധവശാൽ ഉണ്ടാക്കിയതാണെങ്കിൽ താങ്കൾക്ക് ഈ സന്ദേശം നിരാകരിക്കാവുന്നതാണ്‌.",
-    "usernamehasherror": "ഉപയോക്തൃനാമത്തിൽ ഹാഷ് ലിപികൾ ഉൾപ്പെടുത്തരുത്",
     "login-throttled": "താങ്കൾ നിരവധി പ്രാവശ്യം ലോഗിൻ ചെയ്യാൻ ശ്രമിച്ചിരിക്കുന്നു.\nപുതിയതായി ശ്രമിക്കുന്നതിനു മുമ്പ് $1 ദയവായി കാത്തിരിക്കുക.",
     "login-abort-generic": "താങ്കളുടെ പ്രവേശിക്കൽ പരാജയപ്പെട്ടു - റദ്ദാക്കപ്പെട്ടിരിക്കുന്നു",
     "loginlanguagelabel": "ഭാഷ: $1",
     "prefs-skin": "ദൃശ്യരൂപം",
     "skin-preview": "എങ്ങനെയുണ്ടെന്നു കാണുക",
     "datedefault": "ക്രമീകരണങ്ങൾ വേണ്ട",
-    "prefs-beta": "പരീക്ഷണാടിസ്ഥാനത്തിലുള്ള സൗകര്യങ്ങൾ",
     "prefs-datetime": "ദിവസവും സമയവും",
     "prefs-labs": "പരീക്ഷണശാലയിൽ തയ്യാറാകുന്ന സൗകര്യങ്ങൾ",
     "prefs-user-pages": "ഉപയോക്തൃതാളുകൾ",
     "upload-permitted": "അനുവദനീയമായ പ്രമാണ തരങ്ങൾ: $1.",
     "upload-preferred": "പ്രോത്സാഹിപ്പിക്കുന്ന പ്രമാണ തരങ്ങൾ: $1.",
     "upload-prohibited": "നിരോധിക്കപ്പെട്ട തരം പ്രമാണങ്ങൾ: $1.",
-    "uploadlog": "അപ്‌ലോഡ് പ്രവർത്തനരേഖ",
     "uploadlogpage": "അപ്‌ലോഡ് രേഖ",
     "uploadlogpagetext": "സമീപകാലത്ത് അപ്‌ലോഡ് ചെയ്ത പ്രമാണങ്ങളുടെ പട്ടിക താഴെ കാണാം.",
     "filename": "പ്രമാണത്തിന്റെ പേര്",
     "filereuploadsummary": "പ്രമാണത്തിലെ മാറ്റങ്ങൾ:",
     "filestatus": "പകർപ്പവകാശത്തിന്റെ സ്ഥിതി:",
     "filesource": "സ്രോതസ്സ്:",
-    "uploadedfiles": "അപ്‌ലോഡ് ചെയ്ത പ്രമാണങ്ങൾ",
     "ignorewarning": "മുന്നറിയിപ്പ് അവഗണിച്ച് പ്രമാണം സേവ് ചെയ്യുക",
     "ignorewarnings": "അറിയിപ്പുകൾ അവഗണിക്കുക",
     "minlength1": "പ്രമാണത്തിന്റെ പേരിൽ ഒരക്ഷരമെങ്കിലും ഉണ്ടാവണം.",
     "overwroteimage": "\"[[$1]]\" എന്ന പ്രമാണത്തിന്റെ പുതിയ പതിപ്പ് അപ്‌ലോഡ് ചെയ്തിരിക്കുന്നു",
     "uploaddisabled": "അപ്‌ലോഡുകൾ പ്രവർത്തനരഹിതമാക്കിയിരിക്കുന്നു.",
     "copyuploaddisabled": "യൂ.ആർ.എൽ. വഴിയുള്ള അപ്‌‌ലോഡ് നിർജ്ജീവമാക്കിയിരിക്കുന്നു.",
-    "uploadfromurl-queued": "താങ്കളുടെ അപ്‌‌ലോഡ് നിർവഹിക്കാൻ ഉൾപ്പെടുത്തിയിരിക്കുന്നു.",
     "uploaddisabledtext": "പ്രമാണം അപ്‌ലോഡ് ചെയ്യുന്നതു സാദ്ധ്യമല്ലാതാക്കിയിരിക്കുന്നു.",
     "php-uploaddisabledtext": "പി.എച്ച്.പി.യിൽ പ്രമാണ അപ്‌‌ലോഡുകൾ സാദ്ധ്യമല്ലാതാക്കിയിരിക്കുന്നു.\nദയവായി file_uploads ക്രമീകരണങ്ങൾ പരിശോധിക്കുക.",
     "uploadscripted": "ഈ പ്രമാണത്തിൽ വെബ് ബ്രൗസർ തെറ്റായി വ്യാഖ്യാനിച്ചേക്കാവുന്ന എച്ച്.റ്റി.എം.എൽ. അല്ലെങ്കിൽ സ്ക്രിപ്റ്റ് കോഡ് ഉണ്ട്.",
     "upload-misc-error": "കാരണം അജ്ഞാതമായ അപ്‌ലോഡ് പിഴവ്",
     "upload-misc-error-text": "അപ്‌ലോഡിങ്ങ് സമയത്ത് അജ്ഞാതമായ പിഴവ് സംഭവിച്ചു.\nദയവായി യൂ.ആർ.എൽ. സാധുവാണോ എന്നും അതു പ്രാപ്യമാണോ എന്നും പരിശോധിച്ചതിനു ശേഷം വീണ്ടും പരിശ്രമിക്കുക.\nതുടർന്നും പ്രശ്നം അവശേഷിക്കുകയാണെങ്കിൽ [[Special:ListUsers/sysop|കാര്യനി‌ർവാഹകരിലൊരാളെ]] സമീപിക്കുക.",
     "upload-too-many-redirects": "യൂ.ആർ.എല്ലിൽ നിരവധി തിരിച്ചുവിടലുകളുണ്ട്",
-    "upload-unknown-size": "വലിപ്പം അറിയില്ല",
     "upload-http-error": "ഒരു എച്ച്.റ്റി.റ്റി.പി. പിഴവു സംഭവിച്ചിരിക്കുന്നു: $1",
     "upload-copy-upload-invalid-domain": "ഈ ഡൊമൈനിൽ നിന്നും പകർത്തി അപ്‌ലോഡ് ചെയ്യൽ ലഭ്യമല്ല.",
     "backend-fail-stream": "$1 എന്ന പ്രമാണം സ്ട്രീം ചെയ്യാൻ കഴിഞ്ഞില്ല.",
     "img-auth-streaming": "സ്ട്രീമിങ് \"$1\".",
     "img-auth-public": "img_auth.php എന്ന ഗുണനിർവഹണം സ്വകാര്യ‌‌വിക്കികളിൽ പ്രമാണങ്ങൾ ഔട്ട്പുട്ട് ചെയ്യുന്നതിനുള്ളതാണ്.\nഈ വിക്കി ഒരു പൊതുജന വിക്കിയായാണ് ക്രമീകരിച്ചിരിക്കുന്നത്.\nസുരക്ഷയ്ക്ക് ഏറ്റവും അനുകൂലിതമായെന്നതിനാൽ img_auth.php നിർജീവമാക്കിയിരിക്കുന്നു.",
     "img-auth-noread": "\"$1\" എടുത്തുനോക്കാൻ ഉപയോക്താവിനു കഴിയില്ല.",
-    "img-auth-bad-query-string": "യൂ.ആർ.എല്ലിൽ അസാധുവായ ക്വറി പദം ഉണ്ട്.",
     "http-invalid-url": "അസാധുവായ യു.ആർ.എൽ.: $1",
     "http-invalid-scheme": "\"$1\" രീതിയിലുള്ള യു.ആർ.എല്ലുകൾ പിന്തുണയ്ക്കുന്നില്ല",
     "http-request-error": "അഭ്യർത്ഥന അയയ്ക്കുന്നതിൽ അപരിചിതമായ പിഴവ്:",
     "filehist-dimensions": "അളവുകൾ",
     "filehist-filesize": "പ്രമാണത്തിന്റെ വലിപ്പം",
     "filehist-comment": "അഭിപ്രായം",
-    "filehist-missing": "പ്രമാണം ലഭ്യമല്ല",
     "imagelinks": "പ്രമാണത്തിന്റെ ഉപയോഗം",
     "linkstoimage": "താഴെ കാണുന്ന {{PLURAL:$1|താളിൽ|$1 താളുകളിൽ}}  ഈ ചിത്രം ഉപയോഗിക്കുന്നു:",
     "linkstoimage-more": "ഈ പ്രമാണത്തിലേയ്ക്ക് {{PLURAL:$1|ഒരു താളിലധികം കണ്ണി|$1 താളിലധികം കണ്ണികൾ}} ഉണ്ട്.\nതാഴെക്കൊടുത്തിരിക്കുന്ന പട്ടിക ഈ പ്രമാണത്തിലേയ്ക്കു മാത്രമുള്ള {{PLURAL:$1|ആദ്യ താളിന്റെ കണ്ണി|ആദ്യ $1 താളുകളുടെ കണ്ണികൾ}} കാട്ടുന്നു.\n[[Special:WhatLinksHere/$2|മുഴുവൻ പട്ടികയും]] ലഭ്യമാണ്.",
     "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 എന്നതിലും കൂടുതലായി.",
+    "noindex-category-desc": "ഈ താളിൽ <code><nowiki>__NOINDEX__</nowiki></code> എന്ന മാന്ത്രികവാക്ക് ഉണ്ട്, അത് അനുവദിച്ചിട്ടുള്ള നാമമേഖലയിലും ആണ്, അതുകൊണ്ടിത് റോബോട്ടുകളാൽ സൂചികാവത്കരിക്കപ്പെടില്ല.",
+    "index-category-desc": "ഈ താളിൽ <code><nowiki>__INDEX__</nowiki></code> എന്ന മാന്ത്രികവാക്ക് ഉണ്ട് (അത് അനുവദിച്ചിട്ടുള്ള നാമമേഖലയിലും ആണ്), അതുകൊണ്ടിത്, സാധാരണഗതിയിൽ പാടില്ലാത്തതാണെങ്കിലും റോബോട്ടുകളാൽ സൂചികാവത്കരിക്കപ്പെടുന്നതാണ്.",
+    "post-expand-template-inclusion-category-desc": "എല്ലാ ഫലകങ്ങളും വികസിപ്പിച്ചു കഴിയുമ്പോൾ, താളിന്റെ വലിപ്പം <code>$wgMaxArticleSize</code> എന്നതിലും കൂടുതലാവുമെന്നതിനാൽ, ചില ഫലകങ്ങൾ വികസിപ്പിച്ചിരുന്നില്ല.",
+    "post-expand-template-argument-category-desc": "ഫലകത്തിലേയ്ക്കുള്ള ചരം വികസിപ്പിച്ച ശേഷം (<code>{{{പന}}}</code> പോലെയുള്ള മൂന്ന് കോഷ്ഠകങ്ങളിലെ എഴുത്ത്), താളിന്റെ വലിപ്പം <code>$wgMaxArticleSize</code> എന്നതിലും കൂടുതലായി.",
     "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> ഉള്ളതിനാൽ, താളുകളിലെ വർഗ്ഗങ്ങളുടെ കണ്ണികൾ കാണിക്കുന്ന പെട്ടിയിൽ സ്വതേ പ്രത്യക്ഷപ്പെടുന്നതല്ല.",
+    "hidden-category-category-desc": "ഈ വർഗ്ഗത്തിൽ <code><nowiki>__HIDDENCAT__</nowiki></code> ഉള്ളതിനാൽ, താളുകളിലെ വർഗ്ഗങ്ങളുടെ കണ്ണികൾ കാണിക്കുന്ന പെട്ടിയിൽ സ്വതേ പ്രത്യക്ഷപ്പെടുന്നതല്ല.",
     "trackingcategories-nodesc": "വിവരണം ലഭ്യമല്ല.",
     "trackingcategories-disabled": "വർഗ്ഗം നിർജ്ജീവമാക്കിയിരിക്കുന്നു",
     "mailnologin": "അയയ്ക്കാനുള്ള വിലാസം ലഭ്യമല്ല",
     "emailuser-title-notarget": "ഉപയോക്താവിന് ഇമെയിൽ അയക്കുക",
     "emailpage": "ഉപയോക്താവിന് ഇമെയിൽ അയക്കുക",
     "emailpagetext": "താഴെ കാണുന്ന ഫോം ഈ {{GENDER:$1|ഉപയോക്താവിന്‌}} ഇമെയിൽ അയക്കാൻ ഉപയോഗിക്കാവുന്നതാണ്.\n[[Special:Preferences|ഉപയോക്താവിന്റെ ക്രമീകരണങ്ങളിൽ]] കൊടുത്തിട്ടുള്ള ഇമെയിൽ വിലാസം \"ദാതാവ്\" ആയി വരുന്നതാണ്‌, അതുകൊണ്ട് സ്വീകർത്താവിന്‌ താങ്കൾക്ക് നേരിട്ട് മറുപടി അയക്കാൻ കഴിയും.",
-    "usermailererror": "മെയിലുണ്ടായ പിഴവ് തിരിച്ചയച്ചിരിക്കുന്നു:",
     "defemailsubject": "\"$1\" എന്ന ഉപയോക്താവ് അയച്ച {{SITENAME}} ഇമെയിൽ",
     "usermaildisabled": "ഉപയോക്തൃ ഇമെയിൽ പ്രവർത്തനരഹിതമാക്കിയിരിക്കുന്നു",
     "usermaildisabledtext": "ഈ വിക്കിയിലെ മറ്റുപയോക്താക്കൾക്ക് ഇമെയിൽ അയയ്ക്കാൻ താങ്കൾക്ക് കഴിയില്ല",
     "noemailtitle": "ഇമെയിൽ വിലാസം ഇല്ല",
     "noemailtext": "ഈ ഉപയോക്താവ് സാധുവായ ഇമെയിൽ വിലാസം നൽകിയിട്ടില്ല.",
-    "nowikiemailtitle": "ഇമെയിൽ അനുവദിക്കപ്പെട്ടിട്ടില്ല",
     "nowikiemailtext": "ഈ ഉപയോക്താവ് മറ്റുള്ളവരിൽ നിന്നും ഇമെയിൽ സ്വീകരിക്കുന്നത് ഒഴിവാക്കിയിരിക്കുന്നു.",
     "emailnotarget": "സ്വീകർത്താവിന്റെ ഉപയോക്തൃനാമം നിലവിലില്ല അല്ലെങ്കിൽ അസാധുവാണ്.",
     "emailtarget": "സ്വീകർത്താവിന്റെ ഉപയോക്തൃനാമം നൽകുക",
     "nowatchlist": "താങ്കൾ ശ്രദ്ധിക്കുന്ന താളുകളുടെ പട്ടികയിൽ ഇനങ്ങളൊന്നുമില്ല.",
     "watchlistanontext": "താങ്കൾ ശ്രദ്ധിക്കുന്ന താളുകളുടെ പട്ടിക കാണുവാനോ തിരുത്തുവാനോ $1.",
     "watchnologin": "ലോഗിൻ ചെയ്തിട്ടില്ല",
-    "watchnologintext": "ശ്രദ്ധിക്കുന്ന താളിന്റെ പട്ടിക തിരുത്തുവാൻ താങ്കൾ [[Special:UserLogin|ലോഗിൻ]] ചെയ്തിരിക്കണം.",
     "addwatch": "ശ്രദ്ധിക്കുന്ന താളുകളുടെ പട്ടികയിലേക്കു ചേർക്കുക",
     "addedwatchtext": "താങ്കൾ [[Special:Watchlist|ശ്രദ്ധിക്കുന്ന താളുകളുടെ പട്ടികയിലേക്ക്]] \"[[:$1]]\" എന്ന ഈ താൾ ചേർത്തിരിക്കുന്നു. ഇനി മുതൽ ഈ താളിലും ബന്ധപ്പെട്ട സം‌വാദം താളിലും ഉണ്ടാകുന്ന മാറ്റങ്ങൾ ആ പട്ടികയിൽ ദൃശ്യമാവും.",
     "removewatch": "ശ്രദ്ധിക്കുന്ന താളുകളുടെ പട്ടികയിൽ നിന്നും ഒഴിവാക്കുക",
     "watching": "ശ്രദ്ധിക്കുന്നു...",
     "unwatching": "അവഗണിക്കുന്നു...",
     "watcherrortext": "\"$1\" എന്ന താൾ ശ്രദ്ധിക്കുന്നതിന്റെ സ്ഥിതിയിൽ മാറ്റം വരുത്തിയപ്പോൾ ഒരു പിഴവുണ്ടായിരിക്കുന്നു.",
-    "enotif_mailer": "{{SITENAME}} വിജ്ഞാപന മെയിലർ",
     "enotif_reset": "എല്ലാ താളുകളും സന്ദർശിച്ചതായി രേഖപ്പെടുത്തുക",
     "enotif_impersonal_salutation": "{{SITENAME}} ഉപയോക്താവ്",
     "enotif_subject_deleted": "{{SITENAME}} സംരംഭത്തിലെ $1 എന്ന താൾ {{gender:$2|$2}} മായ്ച്ചിരിക്കുന്നു",
     "excontent": "ഉള്ളടക്കം: '$1'",
     "excontentauthor": "ഉള്ളടക്കം: '$1' ('[[Special:Contributions/$2|$2]]' മാത്രമേ ഈ താളിൽ തിരുത്തൽ നടത്തിയിട്ടുള്ളൂ)",
     "exbeforeblank": "ശൂന്യമാക്കപ്പെടുന്നതിനു മുമ്പുള്ള ഉള്ളടക്കം: '$1'",
-    "exblank": "താൾ ശൂന്യമായിരുന്നു",
     "delete-confirm": "\"$1\" മായ്ക്കുക",
     "delete-legend": "മായ്ക്കുക",
     "historywarning": "'''മുന്നറിയിപ്പ്''': താങ്കൾ മായ്ക്കുവാൻ പോകുന്ന താളിനു ഏകദേശം {{PLURAL:$1|ഒരു നാൾപ്പതിപ്പ്|$1 നാൾപ്പതിപ്പുകൾ}} ഉള്ള നാൾവഴി ഉണ്ട്:",
     "importunknownsource": "അപരിചിതമായ ഇറക്കുമതി സ്രോതസ്സ് തരം",
     "importcantopen": "ഇറക്കുമതി പ്രമാണം തുറക്കാൻ കഴിഞ്ഞില്ല",
     "importbadinterwiki": "മോശമായ അന്തർവിക്കി കണ്ണി",
-    "importnotext": "ശൂന്യം അല്ലെങ്കിൽ ഉള്ളടക്കം ഒന്നുമില്ല",
     "importsuccess": "ഇറക്കുമതി ചെയ്തുകഴിഞ്ഞു!",
-    "importhistoryconflict": "നാൾപ്പതിപ്പുകളിൽ പൊരുത്തക്കേടുണ്ട് (ഈ താൾ ഇതിനു മുൻപ് ഇറക്കുമതി ചെയ്തിട്ടുണ്ടാവാം)",
     "importnosources": "ട്രാൻസ്‌‌വിക്കി ഇറക്കുമതി സ്രോതസ്സുകളൊന്നും നിർവചിച്ചിട്ടില്ല, നേരിട്ടുള്ള നാൾവഴി അപ്‌‌ലോഡുകൾ പ്രവർത്തനരഹിതവുമാക്കിയിരിക്കുന്നു.",
     "importnofile": "ഇറക്കുമതി പ്രമാണങ്ങളൊന്നും അപ്‌‌ലോഡ് ചെയ്തിട്ടില്ല.",
     "importuploaderrorsize": "ഇറക്കുമതി ചെയ്ത പ്രമാണത്തിന്റെ അപ്‌‌ലോഡ് പരാജയപ്പെട്ടു.\nപ്രമാണം അപ്‌‌ലോഡിങ്ങിനനുവദിക്കപ്പെട്ടിരിക്കുന്ന അളവിലും വലുതാണ്.",
index d89935d..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": "Хяналтын жагсаалтаас хасах",
index 41cc245..a34eb27 100644 (file)
@@ -92,7 +92,6 @@
     "disclaimers": "Деклараций",
     "disclaimerpage": "Project:Декларацие ӂенералэ",
     "edithelp": "Ажутор пентру едитаре",
-    "helppage": "Help:Купринс",
     "mainpage": "Прима паӂина",
     "mainpage-description": "Прима паӂина",
     "privacy": "Политика де интимитате",
index cd582d3..b85882d 100644 (file)
     "disclaimers": "Вӓшештӹмӹ шая (ответственность) гӹц карангмаш",
     "disclaimerpage": "Project:Вӓшештӹмӓш (ответственность) гӹц карангмаш",
     "edithelp": "Тӧрлӓш манын палшык",
-    "helppage": "Help:Палшык",
     "mainpage": "Тӹнг ӹлӹштӓш",
     "mainpage-description": "Тӹнг ӹлӹштӓш",
     "privacy": "Весӹвлӓлӓн шайышташ ак ли ылмы политика",
index 6078092..4790f1d 100644 (file)
     "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",
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 27f4057..fedb292 100644 (file)
@@ -28,7 +28,6 @@
     "currentevents": "Imwin",
     "currentevents-url": "Project:Imwin",
     "edithelp": "Oomo/edar Ipuok",
-    "helppage": "Help:Oangan",
     "mainpage": "Bwiema peij",
     "mainpage-description": "Bwiema peij",
     "editsection": "Kiwiwid",
index 93a8e2c..5a7dc09 100644 (file)
@@ -10,7 +10,7 @@
     "tog-hideminor": "Am chòe-kīn ê sió kái-piàn",
     "tog-hidepatrolled": "Am chòe-kīn sûn koè--ê  kái-piàn",
     "tog-newpageshidepatrolled": "Sin-ia̍h ê chheng-toaⁿ am sûn koè--ê",
-    "tog-extendwatchlist": "Khok-chhiong kàm-sī-toaⁿ kàu hián-sī só͘-ū ê kái-piàn",
+    "tog-extendwatchlist": "thián-khui kàm-sī-toaⁿ, khoàⁿ choân-pō͘  kái ê, m̄-nā choè-kīn niā.",
     "tog-usenewrc": "Ka-kiông pán ê chòe-kīn-ê-kái-piàn (su-iàu JavaScript)",
     "tog-numberheadings": "Phiau-tê chū-tōng pian-hō",
     "tog-showtoolbar": "Hián-sī pian-chi̍p ke-si-tiâu (su-iàu JavaScript)",
     "filename": "Tóng-àn",
     "filedesc": "Khài-iàu",
     "fileuploadsummary": "Khài-iàu:",
-    "uploadedfiles": "Tóng-àn í-keng sàng chiūⁿ-bāng",
     "ignorewarning": "Mài chhap kéng-kò, kā tóng-àn pó-chûn khí lâi.",
     "ignorewarnings": "Mài chhap kéng-kò",
     "badfilename": "Iáⁿ-siōng ê miâ í-keng kái chò \"$1\".",
     "watchlistfor2": "予$1 $2",
     "nowatchlist": "Lí ê kàm-sī-toaⁿ bô pòaⁿ hāng.",
     "watchnologin": "Bô teng-ji̍p",
-    "watchnologintext": "Lí it-tēng ài [[Special:UserLogin|teng-ji̍p]] chiah ē-tàng siu-kái lí ê kàm-sī-toaⁿ.",
     "addedwatchtext": "\"[[:$1]]\" chit ia̍h í-keng ka-ji̍p lí ê [[Special:Watchlist|kàm-sī-toaⁿ]]. Bī-lâi chit ia̍h a̍h-sī siong-koan ê thó-lūn-ia̍h nā ū kái-piàn, ē lia̍t tī hia. Tông-sî tī [[Special:RecentChanges|Chòe-kīn ê kái-piàn]] ē iōng '''chho·-thé''' hián-sī ia̍h ê piau-tê, án-ne khah bêng-hián. Ká-sú lí beh chiōng chit ia̍h tùi lí ê kàm-sī-toaⁿ tû tiāu, khì khòng-chè-tiâu chhi̍h \"Mài kàm-sī\" chiū ē-sái-tit.",
     "removedwatchtext": "\"[[:$1]]\" chit ia̍h í-keng tùi lí ê kàm-sī-toaⁿ tû tiāu.",
     "watch": "kàm-sī",
     "excontent": "lōe-iông sī: '$1'",
     "excontentauthor": "loē-iông sī: '$1' (î-it ê kòng-hiàn-chiá sī '[[Special:Contributions/$2|$2]]')",
     "exbeforeblank": "chìn-chêng ê lōe-iông sī: '$1'",
-    "exblank": "ia̍h khang-khang",
     "historywarning": "Kéng-kò: Lí beh thâi ê ia̍h ū le̍k-sú:",
     "confirmdeletetext": "Lí tih-beh kā 1 ê ia̍h a̍h-sī iáⁿ-siōng (pau-koat siong-koan ê le̍k-sú) éng-kiú tùi chu-liāu-khò· thâi tiāu. Chhiáⁿ khak-tēng lí àn-sǹg án-ne chò, jī-chhiáⁿ liáu-kái hiō-kó, jī-chhiáⁿ bô ûi-hoán [[{{MediaWiki:Policy-url}}]].",
     "actioncomplete": "Chip-hêng sêng-kong",
index 212b973..1c022f4 100644 (file)
     "accountcreatedtext": "Brukerkontoen for [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|diskusjon]]) har blitt opprettet.",
     "createaccount-title": "Kontooppretting på {{SITENAME}}",
     "createaccount-text": "Noen opprettet en konto for din e-postadresse på {{SITENAME}} ($4) med navnet «$2», med «$3» som passord. Du burde logge inn og endre passordet nå.\n\nDu kan ignorere denne beskjeden dersom kontoen ble opprettet ved en feil.",
-    "usernamehasherror": "Brukernavn kan ikke inneholde nummertegn.",
     "login-throttled": "Du har prøvd å logge inn for mange ganger.\nVent $1 før du prøver på nytt.",
     "login-abort-generic": "Innleggingen ble avbrutt.",
     "loginlanguagelabel": "Språk: $1",
     "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",
     "upload-permitted": "Tillatte filtyper: $1.",
     "upload-preferred": "Foretrukne filtyper: $1",
     "upload-prohibited": "Forbudte filtyper: $1.",
-    "uploadlog": "opplastingslogg",
     "uploadlogpage": "Opplastingslogg",
     "uploadlogpagetext": "Her er en liste over de siste opplastede filene.\nSe [[Special:NewFiles|galleriet over nye filer]] for en mer visuell visning",
     "filename": "Filnavn",
     "filereuploadsummary": "Filendringer:",
     "filestatus": "Opphavsrettsstatus:",
     "filesource": "Kilde:",
-    "uploadedfiles": "Filer som er lastet opp",
     "ignorewarning": "Ignorer advarselen og lagre filen likevel",
     "ignorewarnings": "Ignorer eventuelle advarsler",
     "minlength1": "Filnavn må være på minst én bokstav.",
     "overwroteimage": "last opp en ny versjon av «[[$1]]»",
     "uploaddisabled": "Opplastingsfunksjonen er slått av",
     "copyuploaddisabled": "Opplasting via nettadresse deaktivert.",
-    "uploadfromurl-queued": "Opplastingen din har blitt satt i kø.",
     "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.",
     "upload-misc-error": "Ukjent opplastingsfeil",
     "upload-misc-error-text": "En ukjent feil forekom under opplastingen.\nBekreft at adressen er gyldig og tilgjengelig, og prøv igjen.\nOm problemet fortsetter, kontakt en [[Special:ListUsers/sysop|administrator]].",
     "upload-too-many-redirects": "URL-en inneholdt for mange omdirigeringer",
-    "upload-unknown-size": "Ukjent størrelse",
     "upload-http-error": "En HTTP-feil oppstod: $1",
     "upload-copy-upload-invalid-domain": "Opplasting av kopier er ikke tilgjengelig fra dette domenet.",
     "backend-fail-stream": "Kunne ikke strømme filen $1.",
     "img-auth-streaming": "Sender «$1».",
     "img-auth-public": "Funksjonen til img_auth.php er å lage filer fra en privat wiki.\nDenne wikien er satt opp som en offentlig wiki.\nFor best mulig sikkerhet er img_auth.php slått av.",
     "img-auth-noread": "Brukeren har ikke tilgang til å lese «$1».",
-    "img-auth-bad-query-string": "URL-en har en ugyldig spørrestreng.",
     "http-invalid-url": "Ugyldig internettadresse: $1",
     "http-invalid-scheme": "Internettadresser med «$1»-formen støttes ikke",
     "http-request-error": "HTTP-forespørselen feilet på grunn av en ukjent feil.",
     "filehist-dimensions": "Dimensjoner",
     "filehist-filesize": "Filstørrelse",
     "filehist-comment": "Kommentar",
-    "filehist-missing": "Fil mangler",
     "imagelinks": "Filbruk",
     "linkstoimage": "Følgende {{PLURAL:$1|side|$1 sider}} har lenker til denne filen:",
     "linkstoimage-more": "Mer enn $1 {{PLURAL:$1|side|sider}} lenker til denne filen.\nFølgende liste viser {{PLURAL:$1|den første siden|de $1 første sidene}}.\nEn [[Special:WhatLinksHere/$2|fullstendig liste]] er tilgjengelig.",
     "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.",
+    "noindex-category-desc": "Denne siden er påført et <code><nowiki>__NOINDEX__</nowiki></code> 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 <code><nowiki>__INDEX__</nowiki></code> 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 <code>$wgMaxArticleSize</code>, så noen maler er ikke ekspandert.",
+    "post-expand-template-argument-category-desc": "Etter ekspandering av et malargument (noe i trippel krøllparentes, slik som <code>{{{Foo}}})</code>, så er siden større en <code>$wgMaxArticleSize</code>.",
     "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.",
+    "hidden-category-category-desc": "Dette er en kategori som er påført et <code><nowiki>__HIDDENCAT__</nowiki></code> 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",
     "emailuser-title-notarget": "E-post til bruker",
     "emailpage": "E-post til bruker",
     "emailpagetext": "Du kan bruke skjemaet under for å sende en e-post til denne {{GENDER:$1|brukeren}}.\nE-postadressen du har satt i [[Special:Preferences|innstillingene dine]] vil vises i «Fra»-feltet i e-posten, slik at mottakeren kan svare deg direkte.",
-    "usermailererror": "E-postobjekt returnerte feilen:",
     "defemailsubject": "E-post fra {{SITENAME}}-brukeren «$1»",
     "usermaildisabled": "Brukerepost deaktivert",
     "usermaildisabledtext": "Du kan ikke sende epost til andre brukere på denne wikien",
     "noemailtitle": "Ingen e-postadresse",
     "noemailtext": "Dene brukeren har ikke oppgitt en gyldig e-postadresse.",
-    "nowikiemailtitle": "Ingen e-post tillatt",
     "nowikiemailtext": "Denne brukeren har valgt å ikke motta e-post fra andre brukere.",
     "emailnotarget": "Ikke-eksisterende eller ugyldig brukernavn for mottaker.",
     "emailtarget": "Skriv inn brukernavnet på mottakeren",
     "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",
     "watching": "Overvåker…",
     "unwatching": "Fjerner fra overvåkningsliste…",
     "watcherrortext": "Det oppsto en feil under endring av overvåkningsinnstillingene dine for «$1».",
-    "enotif_mailer": "{{SITENAME}}s påminnelsessystem",
     "enotif_reset": "Merk alle sider som besøkt",
     "enotif_impersonal_salutation": "{{SITENAME}}-bruker",
     "enotif_subject_deleted": "{{SITENAME}}-siden $1 har blitt slettet av {{gender:$2|$2}}",
     "excontent": "Innholdet var: «$1»",
     "excontentauthor": "innholdet var «$1» (og eneste bidragsyter var [[Special:Contributions/$2|$2]])",
     "exbeforeblank": "innholdet før siden ble tømt var: «$1»",
-    "exblank": "siden var tom",
     "delete-confirm": "Slett «$1»",
     "delete-legend": "Slett",
     "historywarning": "Advarsel: Siden du er i ferd med å slette har en historikk med omtrent {{PLURAL:$1|én revisjon|$1 revisjoner}}:",
     "importunknownsource": "Ukjent importkildetype",
     "importcantopen": "Kunne ikke åpne importfil",
     "importbadinterwiki": "Ugyldig interwikilenke",
-    "importnotext": "Tom eller ingen tekst",
     "importsuccess": "Importering ferdig.",
-    "importhistoryconflict": "Motstridende revisjoner finnes (siden kan ha blitt importert tidligere)",
     "importnosources": "Ingen transwikiimportkilder er angitt, og direkte historikkimporteringer er slått av.",
     "importnofile": "Ingen importfil opplastet.",
     "importuploaderrorsize": "Importfilopplasting mislyktes. Filen er større enn tillatt opplastingsstørrelse.",
index 05e5c4b..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",
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 88da6d6..730c6d6 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": "ई-मेल ठेगाना स्वीकार गर्न सकिएन किन भनें यो सही प्रारूपमा छैन, कृपया सही प्रारूपको  ठेगाना दिनुहोस्।",
     "accountcreatedtext": "[[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|वार्ता]])$1 प्रयोगकर्ताको लागि खाता खोलिएको छ ।",
     "createaccount-title": "{{SITENAME}}कोलागि खाता खोल्ने काम",
     "createaccount-text": "कसैले तपाईको इमेल ठेगानालाई {{SITENAME}} ($4) मा \"$2\" नामको खाता बनाएको छ, जसको पासवर्ड \"$3\" छ।",
-    "usernamehasherror": "प्रयोगकर्तानाममा ह्यास अक्षरहरु राख्न मिल्दैन।",
     "login-throttled": "तपाईंले भर्खरै धेरै पल्ट प्रवेशको निम्ति प्रयास गर्नुभएको छ ,कृपया $1 पर्खेर मात्र प्रयास गर्नुहोस्।",
     "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": "इतिहास",
     "upload-permitted": "अनुमति पाएका फ़ाइल प्रकार:$1.",
     "upload-preferred": "चाहिएका फ़ाइल प्रकार:$1.",
     "upload-prohibited": "निषिद्ध फ़ाइल प्रकार:$1.",
-    "uploadlog": "उर्ध्वभरण लग",
     "uploadlogpage": "उर्ध्वभरण लग",
     "uploadlogpagetext": "भर्खरै उर्ध्वभरण गरिएका फ़ाइलहरुको सूची तल दिइएकोछ ।\nविस्तृत अवलोकनको लागि [[Special:NewFiles|नयाँ फ़ाइलको ग्यालरी]]मा हेर्नुहोस्।",
     "filename": "फाइलनाम",
     "filereuploadsummary": "फ़ाइल परिवर्तनहरू:",
     "filestatus": "लेखाधिकार स्थिति:",
     "filesource": "स्रोत:",
-    "uploadedfiles": "उर्ध्वभरण गरिएका फाइलहरू",
     "ignorewarning": "चेतावनीलाई अनदेखा गर्दै जसरि भएपनि फाइल संग्रह गर्ने",
     "ignorewarnings": "कुनै चेतावनीप्रति ध्यान नदिने",
     "minlength1": "फाइलको नाम कम्तिमा एक अक्षरको हुनैपर्छ।",
     "overwroteimage": " \"[[$1]]\"को एउटा नयाँ संस्करण उर्ध्वभरण गरियो",
     "uploaddisabled": "उर्ध्वभरण अक्षम पारिएकोछ",
     "copyuploaddisabled": " URL प्रयोग गरी उर्ध्वभरण निश्कृय पारिएको छ।",
-    "uploadfromurl-queued": "तपाईको उर्ध्वभरणलाई प्रतिक्षा सुचिमा राखिएको छ।",
     "uploaddisabledtext": "फाइल उर्ध्वभरण अक्षम पारिएकोछ",
     "php-uploaddisabledtext": "PHP मा फाइल उर्ध्वभरण अक्षम गरिएकोछ।\nकृपया फाइल उर्ध्वभरण व्यवस्था(setting) जाँच्नुहोस्।",
     "uploadvirus": "फाइलमा भाइरस छ!\nविवरण:$1",
     "upload-file-error": "आन्तरिक त्रुटि",
     "upload-misc-error": "अज्ञात अपलोड त्रुटि",
     "upload-too-many-redirects": "यस URL मा धेरै पुननिर्देशनहरु छन् ।",
-    "upload-unknown-size": "अज्ञात  आकार",
     "upload-http-error": "HTTP त्रुटि भयो: $1",
     "backend-fail-delete": " $1 फाइल मेट्न सकिएन ।",
     "backend-fail-alreadyexists": " $1 पहिके देखि नै रहेको छ ।",
     "listfiles_search_for": "मिडिया नामको लागि खोज्नुहोस:",
     "imgfile": "फाइल",
     "listfiles": "फाइल सूची",
+    "listfiles_thumb": "थम्बनेल",
     "listfiles_date": "मिति",
     "listfiles_name": "नाम",
     "listfiles_user": "प्रयोगकर्ता",
     "filehist-dimensions": "आकारहरू",
     "filehist-filesize": "फाइल आकार",
     "filehist-comment": "टिप्पणी",
-    "filehist-missing": "फाइल हराइरहेको छ",
     "imagelinks": "फाइलको प्रयोगहरु",
     "linkstoimage": "यस फाइलमा निम्न{{PLURAL:$1|पृष्ठ जोडिन्छ|$1 पृष्ठहरु जोडिन्छन}}:",
     "nolinkstoimage": "यो फाईलसंग लिंकभएको कुनै पृष्ठ छैन.",
     "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:सामूहिक अधिकारहरु",
     "emailuser": "यो प्रयोगकर्तालाई ई-मेल पठाउनुहोस्",
     "emailuser-title-notarget": "प्रयोगकर्तालाई इमेल गर्नुहोस्",
     "emailpage": "प्रयोगकर्तालाई इमेल गर्नुहोस्",
-    "usermailererror": "मेल अब्जेक्टले देखाएको त्रुटि:",
     "defemailsubject": "{{SITENAME}} प्रयपोगकर्ता \"$1\" बाट इमेल",
     "usermaildisabled": "प्रयोगकर्ता इमेल निरस्त गरिएको",
     "usermaildisabledtext": "यस विकिमा तपाईं अरु प्रयोगकर्तालाई ई-मेल पठाउन सक्नुहुन्न",
     "noemailtitle": "ईमेल ठेगाना नभएको",
     "noemailtext": "प्रयोगकर्ताले सही ई-मेल ठेगाना दर्शाएको छैन।",
-    "nowikiemailtitle": "ई-मेलको अनुमति छैन",
     "nowikiemailtext": "यी प्रयोगकर्ताले अरु प्रयोगकर्ताहरुबाट ई-मेल स्वीकार नगर्ने छनोट गरेकाछन्।",
     "emailnotarget": "प्राप्तकर्ताको रुपमा नभएको अथवा अमान्य प्रयोगकर्ता।",
     "emailtarget": "प्राप्तकर्ताको प्रयोगकर्ता नाम हाल्नुहोस्",
     "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|पृष्ठ|पृष्ठहरु}}रहेका छन् ।",
     "watching": "निगरानी गर्दै...",
     "unwatching": "निगरानीबाट हटाउँदै...",
     "watcherrortext": "\"$1\"को लागि तपाइँको निगरानी सुची परिवर्तन गर्ने क्रममा यौटा त्रुटी भएको छ।",
-    "enotif_mailer": "{{SITENAME}} जानकारी प्रेषक",
     "enotif_reset": "सबै पृष्ठहरु भनी दाग दिने",
     "enotif_impersonal_salutation": "{{SITENAME}} प्रयोगकर्ता",
     "enotif_lastvisited": "अघिल्लो हेराइपछिका सबै परिवर्तनहरुको निम्ति हेर्नुहोस्: $1",
     "excontent": "लेख थियो: '$1'",
     "excontentauthor": "लेखेको थियो:\"$1\" (र  योगदान कर्ता थिए \"[[Special:Contributions/$2|$2]]\")",
     "exbeforeblank": "खालि गर्नु भन्दा अघिको सामग्री थियो: \"$1\"",
-    "exblank": "पृष्ठ खाली छ",
     "delete-confirm": "मेट्नुहोस् \"$1\"",
     "delete-legend": "मेट्नुहोस्",
     "historywarning": " चेतावनी: तपाईंले मेटाउन लाग्नुभएको पृष्ठको इतिहासको लगभग $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.",
     "importunknownsource": "अज्ञात आयात स्रोत प्रकार ।",
     "importcantopen": "आयात गर्ने स्रोत फाइल खोल्न सकिएन ।",
     "importbadinterwiki": "खराव अन्तर विकि लिंक",
-    "importnotext": "पाठ नभएको या  खाली",
     "importsuccess": "आयात सम्पन्न भयो!",
-    "importhistoryconflict": "पुनरावलोकन इतिहासमा द्वन्द रहेको छ (तपाईँले यो पृष्ठ पहिलेनै आयात गरिसक्नु भएको हुनुपर्दछ )",
     "importnofile": "कुनै पनि आयात फाइल अपलोड गरिएन ।",
     "importuploaderrorsize": "आयात फाइलको अपलोड असफल भयो।\nफाइल अनुमति दिइए भन्दा ठूलो छ।",
     "importuploaderrorpartial": "आयात फाइलको अपलोड असफल भयो।\nफाइल आंशिकरुपमा अपलोड भयो।",
index 1169fb1..73314c6 100644 (file)
     "disclaimers": "डिस्क्लेमर्स",
     "disclaimerpage": "Project:साधारण डिस्क्लेमर्स",
     "edithelp": "सम्पादन ग्वहालि",
-    "helppage": "Help:धलःपौ",
     "mainpage": "मू पौ",
     "mainpage-description": "मू पौ",
     "policy-url": "Project:नीति",
index c5feb40..7cbd573 100644 (file)
@@ -64,7 +64,6 @@
     "aboutpage": "Project: Hagaao",
     "currentevents": "Tau Fakaholoaga Mogonei",
     "edithelp": "Lagomatai ke he Fakahakohako",
-    "helppage": "Help: Ke lata mo e tau mena i loto",
     "mainpage": "Matapatu Lau",
     "mainpage-description": "Matapatu Lau",
     "portal": "Maaga ke Matutaki",
index ce0dcca..de3eccf 100644 (file)
     "permalink": "Permanente koppeling",
     "print": "Afdrukken",
     "view": "Lezen",
+    "view-foreign": "Bekijken op $1",
     "edit": "Bewerken",
+    "edit-local": "Lokale beschrijving bewerken",
     "create": "Aanmaken",
+    "create-local": "Lokale beschrijving toevoegen",
     "editthispage": "Deze pagina bewerken",
     "create-this-page": "Deze pagina aanmaken",
     "delete": "Verwijderen",
     "pool-timeout": "De maximaal te wachten tijd voor het wachten op een lock is verstreken",
     "pool-queuefull": "De wachtrij van de poel is vol",
     "pool-errorunknown": "Er is een onbekende fout opgetreden",
+    "pool-servererror": "De dienst \"pool counter\" is niet beschikbaar ($1).",
     "aboutsite": "Over {{SITENAME}}",
     "aboutpage": "Project:Info",
     "copyright": "De inhoud is beschikbaar onder de $1 tenzij anders aangegeven.",
     "accountcreatedtext": "De gebruiker [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|overleg]]) is aangemaakt.",
     "createaccount-title": "Gebruikers registreren voor {{SITENAME}}",
     "createaccount-text": "Iemand heeft een gebruiker op {{SITENAME}} ($4) aangemaakt met de naam \"$2\" en uw e-mailadres.\nHet wachtwoord voor \"$2\" is \"$3\".\nMeld u aan en wijzig uw wachtwoord.\n\nNegeer dit bericht als deze gebruiker zonder uw medeweten is aangemaakt.",
-    "usernamehasherror": "Een gebruikersnaam mag het teken hekje (\"#\") niet bevatten.",
     "login-throttled": "U heeft recentelijk te veel mislukte aanmeldpogingen gedaan.\nWacht alstublieft $1 voordat u het opnieuw probeert.",
     "login-abort-generic": "U bent niet aangemeld. De procedure is afgebroken.",
     "loginlanguagelabel": "Taal: $1",
     "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",
     "upload-permitted": "Toegelaten bestandstypes: $1.",
     "upload-preferred": "Aangewezen bestandstypes: $1.",
     "upload-prohibited": "Verboden bestandstypes: $1.",
-    "uploadlog": "uploadlogboek",
     "uploadlogpage": "Uploadlogboek",
     "uploadlogpagetext": "Hieronder staan de nieuwste bestanden.\nZie de [[Special:NewFiles|galerij met nieuwe bestanden]] voor een visueler overzicht.",
     "filename": "Bestandsnaam",
     "filereuploadsummary": "Bestandswijzigingen:",
     "filestatus": "Auteursrechtenstatus:",
     "filesource": "Bron:",
-    "uploadedfiles": "Geüploade bestanden",
     "ignorewarning": "Deze waarschuwing negeren en het bestand toch opslaan",
     "ignorewarnings": "Alle waarschuwingen negeren",
     "minlength1": "Bestandsnamen moeten minstens één letter bevatten.",
     "overwroteimage": "heeft een nieuwe versie van \"[[$1]]\" toegevoegd",
     "uploaddisabled": "Uploaden is uitgeschakeld",
     "copyuploaddisabled": "Het uploaden van bestanden via een URL is uitgeschakeld.",
-    "uploadfromurl-queued": "Uw upload is in de wachtrij geplaatst.",
     "uploaddisabledtext": "Het uploaden van bestanden is uitgeschakeld.",
     "php-uploaddisabledtext": "Het uploaden van bestanden is uitgeschakeld in PHP.\nControleer de instelling \"file_uploads\".",
     "uploadscripted": "Dit bestand bevat HTML- of scriptcode die foutief door uw browser kan worden weergegeven.",
     "upload-misc-error": "Onbekende uploadfout",
     "upload-misc-error-text": "Er is tijdens het uploaden een onbekende fout opgetreden.\nControleer of de URL correct en beschikbaar is en probeer het opnieuw.\nAls het probleem aanhoudt, neem dan contact op met een [[Special:ListUsers/sysop|moderator]].",
     "upload-too-many-redirects": "De URL bevatte te veel doorverwijzingen",
-    "upload-unknown-size": "Onbekende grootte",
     "upload-http-error": "Er is een HTTP-fout opgetreden: $1",
     "upload-copy-upload-invalid-domain": "Uploaden per kopie is niet beschikbaar vanuit dit domein.",
     "backend-fail-stream": "Het was niet mogelijk het bestand $1 te streamen.",
     "img-auth-streaming": "Bezig met het streamen van \"$1\".",
     "img-auth-public": "Het doel van img_auth.php is de uitvoer van bestanden van een besloten wiki.\nDeze wiki is ingesteld als publieke wiki.\nOm beveiligingsreden is img_auth.php uitgeschakeld.",
     "img-auth-noread": "De gebruiker heeft geen leestoegang tot \"$1\".",
-    "img-auth-bad-query-string": "De URL bevat een ongeldige querystring.",
     "http-invalid-url": "Ongeldige URL: $1",
     "http-invalid-scheme": "URL's met de opmaak \"$1\" worden niet ondersteund",
     "http-request-error": "Fout bij het verzenden van het verzoek.",
     "filehist-dimensions": "Afmetingen",
     "filehist-filesize": "Bestandsgrootte",
     "filehist-comment": "Opmerking",
-    "filehist-missing": "Het bestand is niet aangetroffen",
     "imagelinks": "Bestandsgebruik",
     "linkstoimage": "Dit bestand wordt op de volgende {{PLURAL:$1|pagina|$1 pagina's}} gebruikt:",
     "linkstoimage-more": "Er {{PLURAL:$2|is|zijn}} meer dan $1 {{PLURAL:$1|koppeling|koppelingen}} naar dit bestand.\nDe volgende lijst geeft alleen de eerste {{PLURAL:$1|koppeling|$1 koppelingen}} naar dit bestand weer.\nEr is ook een [[Special:WhatLinksHere/$2|volledige lijst]].",
     "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",
+    "listgrouprights-namespaceprotection-header": "Naamruimtebeperkingen",
+    "listgrouprights-namespaceprotection-namespace": "Naamruimte",
+    "listgrouprights-namespaceprotection-restrictedto": "Recht(en) waardoor gebruiker kan bewerken",
     "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.",
+    "noindex-category-desc": "De pagina bevat het magische woord <code><nowiki>__NOINDEX__</nowiki></code> (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 <code><nowiki>__INDEX__</nowiki></code> (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>.",
+    "post-expand-template-argument-category-desc": "Na het uitbreiden van een sjabloonparameter (iets in de drievoudige accolades, zoals <code>{{{Foo}}})</code>), 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.",
+    "hidden-category-category-desc": "Dit is een categoriepagina die het magische woord <code><nowiki>__HIDDENCAT__</nowiki></code> 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",
     "emailuser-title-notarget": "Gebruiker e-mailen",
     "emailpage": "Gebruiker e-mailen",
     "emailpagetext": "Via dit formulier kunt u een e-mail aan {{GENDER:$1|deze gebruiker}} verzenden.\nHet e-mailadres dat u hebt opgegeven bij [[Special:Preferences|uw voorkeuren]] wordt als afzender gebruikt.\nDe ontvanger kan dus direct naar u reageren.",
-    "usermailererror": "Foutmelding bij het verzenden:",
     "defemailsubject": "E-mail van {{SITENAME}}-gebruiker \"$1\"",
     "usermaildisabled": "Gebruikerse-mail uitgeschakeld",
     "usermaildisabledtext": "U kunt geen e-mail verzenden naar andere gebruikers op deze wiki",
     "noemailtitle": "Van deze gebruiker is geen e-mailadres bekend",
     "noemailtext": "Deze gebruiker heeft geen geldig e-mailadres opgegeven.",
-    "nowikiemailtitle": "E-mail is niet toegestaan",
     "nowikiemailtext": "Deze gebruiker wil geen e-mail ontvangen van andere gebruikers.",
     "emailnotarget": "Niet-bestaande of ongeldige ontvanger.",
     "emailtarget": "Voer de geadresseerde in",
     "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",
     "watching": "Bezig met plaatsen op volglijst…",
     "unwatching": "Bezig met verwijderen van volglijst…",
     "watcherrortext": "Er is een fout opgetreden tijdens het wijzigen van uw volglijstinstellingen voor \"$1\".",
-    "enotif_mailer": "{{SITENAME}}-berichtensysteem",
     "enotif_reset": "Alle pagina's markeren als bezocht",
     "enotif_impersonal_salutation": "gebruiker van {{SITENAME}}",
     "enotif_subject_deleted": "{{SITENAME}}: pagina $1 is verwijderd door {{GENDER:$2|$2}}",
     "excontent": "De inhoud was: \"$1\"",
     "excontentauthor": "De inhoud was: \"$1\" ([[Special:Contributions/$2|$2]] was de enige auteur)",
     "exbeforeblank": "De inhoud was: \"$1\"",
-    "exblank": "pagina was leeg",
     "delete-confirm": "\"$1\" verwijderen",
     "delete-legend": "Verwijderen",
     "historywarning": "'''Waarschuwing:''' de pagina die u wilt verwijderen heeft ongeveer $1 {{PLURAL:$1|versie|versies}}:",
     "importunknownsource": "Onbekend importbrontype",
     "importcantopen": "Kon het importbestand niet openen",
     "importbadinterwiki": "Verkeerde interwikikoppeling",
-    "importnotext": "Leeg of geen tekst",
     "importsuccess": "Import afgerond!",
-    "importhistoryconflict": "Er zijn conflicten in de geschiedenis van de pagina (is misschien eerder geïmporteerd)",
     "importnosources": "Er zijn geen transwiki-importbronnen gedefinieerd en directe geschiedenis-uploads zijn uitgeschakeld.",
     "importnofile": "Er is geen importbestand geüpload.",
     "importuploaderrorsize": "Upload van het importbestand in mislukt.\nHet bestand is groter dan de ingestelde limiet.",
     "version-entrypoints": "URL's voor ingangen",
     "version-entrypoints-header-entrypoint": "Ingang",
     "version-entrypoints-header-url": "URL",
-    "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]",
+    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath Paginapad]",
+    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath Scriptpad]",
     "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 16b9a9b..299f976 100644 (file)
     "accountcreatedtext": "Brukarkontoen til [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|diskusjon]]) er oppretta.",
     "createaccount-title": "Oppretting av brukarkonto på {{SITENAME}}",
     "createaccount-text": "Nokon oppretta ein brukarkonto for $2 på {{SITENAME}} ($4). Passordet til «$2» er «$3». Du bør logge inn og endre passordet ditt med ein gong.\n\nDu kan sjå bort frå denne meldinga dersom kontoen vart oppretta med eit uhell.",
-    "usernamehasherror": "Brukarnamn kan ikkje innehalda nummerteikn.",
     "login-throttled": "Du har prøvd å logge inn for mange gonger. Ver venleg og vent før du prøver igjen.",
     "login-abort-generic": "Innlogginga er avbroten.",
     "loginlanguagelabel": "Språk: $1",
     "prefs-skin": "Drakt",
     "skin-preview": "førehandsvis",
     "datedefault": "Standard",
-    "prefs-beta": "Betafunksjonar",
     "prefs-datetime": "Dato og klokkeslett",
     "prefs-labs": "Testfunksjonar",
     "prefs-user-pages": "Brukarsider",
     "upload-permitted": "Godtekne filtypar: $1.",
     "upload-preferred": "Føretrekte filtypar: $1.",
     "upload-prohibited": "Ikkje godtekne filtypar: $1.",
-    "uploadlog": "opplastingslogg",
     "uploadlogpage": "Opplastingslogg",
     "uploadlogpagetext": "Dette er ei liste over filer som nyleg er lasta opp.",
     "filename": "Filnamn",
     "filereuploadsummary": "Filendringar:",
     "filestatus": "Opphavsrettsstatus:",
     "filesource": "Kjelde:",
-    "uploadedfiles": "Filer som er opplasta",
     "ignorewarning": "Sjå bort frå åtvaringa og lagre fila likevel",
     "ignorewarnings": "Oversjå åtvaringar",
     "minlength1": "Filnamn må ha minst eitt teikn.",
     "overwroteimage": "lasta opp ein ny versjon av «[[$1]]»",
     "uploaddisabled": "Beklagar, funksjonen for opplasting er deaktivert på denne nettenaren.",
     "copyuploaddisabled": "Opplasting gjennom URL er slege av.",
-    "uploadfromurl-queued": "Opplastinga di er sett i kø.",
     "uploaddisabledtext": "Filopplasting er slått av.",
     "php-uploaddisabledtext": "PHP-filopplasting er deaktivert. Sjå innstillinga for file_uploads.",
     "uploadscripted": "Fila inneheld HTML- eller skriptkode som feilaktig kan bli tolka og køyrd av nettlesarar.",
     "upload-misc-error": "Ukjend feil ved opplastinga",
     "upload-misc-error-text": "Ein ukjend feil oppstod under opplastinga. Ver venleg og stadfest at nettadressa er gyldig og tilgjengeleg, og prøv ein gong til. Dersom problemet held fram, ta kontakt med ein [[Special:ListUsers/sysop|administrator]].",
     "upload-too-many-redirects": "URL-en inneheldt for mange omdirigeringar",
-    "upload-unknown-size": "Ukjend storleik",
     "upload-http-error": "Ein HTTP-feil oppstod: $1",
     "upload-copy-upload-invalid-domain": "Kopiopplastingar er ikkje tilgjengelege frå dette domenet.",
     "backend-fail-stream": "Kunne ikkje strøyma fila «$1».",
     "img-auth-streaming": "Sendar \"$1\".",
     "img-auth-public": "Funksjonen til img_auth.php er å laga filer frå ein privat wiki.\nDenne wikien er sett opp som ein ålmennt tilgjengeleg wiki.\nFor best tryggleik, er img_auth.php sett ut av funksjon.",
     "img-auth-noread": "Brukaren har ikkje rettar til å lesa «$1».",
-    "img-auth-bad-query-string": "URL-en har ein ugild spørjestreng.",
     "http-invalid-url": "Ugyldig URL: $1",
     "http-invalid-scheme": "URL-ar med  «$1»-førestavinga er ikkje støtta.",
     "http-request-error": "HTTP-førespurnaden feila grunna ein ukjend feil.",
     "filehist-dimensions": "Oppløysing",
     "filehist-filesize": "Filstorleik",
     "filehist-comment": "Kommentar",
-    "filehist-missing": "Fila manglar",
     "imagelinks": "Filbruk",
     "linkstoimage": "{{PLURAL:$1|Den følgjande sida|Dei følgjande $1 sidene}} har lenkjer til denne fila:",
     "linkstoimage-more": "Meir enn $1 {{PLURAL:$1|side|sider}} lenkjer til denne fila.\nFølgjande liste viser {{PLURAL:$1|den første sida|dei $1 første sidene}}.\nEi [[Special:WhatLinksHere/$2|fullstendig liste]] er tilgjengeleg.",
     "emailuser-title-notarget": "Send e-post åt brukar",
     "emailpage": "Send e-post åt brukar",
     "emailpagetext": "Du kan nytte skjemaet nedanfor til å sende ein e-post til denne {{GENDER:$1|brukaren}}.\nE-postadressa du har sett i [[Special:Preferences|innstillingane dine]] vil dukke opp i «frå»-feltet på denne e-posten, så mottakaren er i stand til å svare.",
-    "usermailererror": "E-post systemet gav feilmelding:",
     "defemailsubject": "{{SITENAME}} epost frå brukar \"$1\"",
     "usermaildisabled": "Brukare-post slegen av",
     "usermaildisabledtext": "Du kan ikkje senda e-postar til andre brukarar på wikien",
     "noemailtitle": "Inga e-postadresse",
     "noemailtext": "Denne brukaren har ikkje oppgjeve ei gyldig e-postadresse.",
-    "nowikiemailtitle": "Ingen e-post tillaten",
     "nowikiemailtext": "Denne brukaren har vald å ikkje motta e-postar frå andre brukarar.",
     "emailnotarget": "Ikkje-eksisterande eller ugyldig brukarnamn for mottakar.",
     "emailtarget": "Skriv inn brukarnamnet til mottakaren",
     "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",
     "watching": "Overvakar...",
     "unwatching": "Fjernar frå overvakinglista...",
     "watcherrortext": "Det oppstod ein feil under endringa av overvakingsinnstillingane dine for «$1».",
-    "enotif_mailer": "{{SITENAME}}-endringsmeldingssendar",
     "enotif_reset": "Merk alle sidene som vitja",
     "enotif_impersonal_salutation": "{{SITENAME}}-brukar",
     "enotif_subject_deleted": "{{SITENAME}}-sida $1 har vorte sletta av {{gender:$2|$2}}",
     "excontent": "innhaldet var: «$1»",
     "excontentauthor": "innhaldet var: «$1» (og den einaste bidragsytaren var «[[Special:Contributions/$2|$2]]»)",
     "exbeforeblank": "innhaldet før sida vart tømd var: «$1»",
-    "exblank": "sida var tom",
     "delete-confirm": "Slett «$1»",
     "delete-legend": "Slett",
     "historywarning": "'''Åtvaring:''' Sida du held på å slette har ein historikk med om lag $1 {{PLURAL:$1|versjon|versjonar}}:",
     "importunknownsource": "Ukjend importkjeldetype",
     "importcantopen": "Kunne ikkje opne importfil",
     "importbadinterwiki": "Ugyldig interwikilenkje",
-    "importnotext": "Tom eller ingen tekst",
     "importsuccess": "Importeringa er ferdig!",
-    "importhistoryconflict": "Det kan vera at det er konflikt i historikken (kanskje sida vart importert før)",
     "importnosources": "Ingen kjelder for transwikiimport er oppgjevne og funksjonen for opplasting av historikk er deaktivert.",
     "importnofile": "Inga importfil er lasta opp.",
     "importuploaderrorsize": "Opplastinga av importfila var mislukka. Fila er større enn det som er lov å laste opp.",
index 221b236..c516f05 100644 (file)
     "currentevents": "Nuni eventes",
     "currentevents-url": "Project:Nuni eventes",
     "edithelp": "Helpo pri modifiko de pagines",
-    "helppage": "Help:Kontenaje",
     "mainpage": "Chefi pagine",
     "mainpage-description": "Chefi pagine",
     "portal": "Li komun chambre",
index 2f3bbc7..69410b4 100644 (file)
@@ -90,7 +90,6 @@
     "aboutpage": "Project: baa haneʼ",
     "copyright": "Díí naaltsoos bikáaʼgi saad shijaaʼígíí \"$1\" beehazʼą́ąnii bikʼehgo choidííłįįł",
     "edithelp": "anáʼálwoʼ",
-    "helppage": "Help:Bee hadítʼéhígíí",
     "mainpage": "Íiyisíí Naaltsoos",
     "mainpage-description": "Íiyisíí Naaltsoos",
     "retrievedfrom": "\"$1\" bitsʼą́ą́dę́ę́ʼ",
index 82e76c7..bc5125b 100644 (file)
     "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",
     "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",
index d3080b7..652e0b1 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": "ଦେଖଣା ତାଲିକାରୁ ହଟାଇବେ",
index fd88bed..57e52a5 100644 (file)
@@ -53,7 +53,6 @@
     "currentevents": "Saray nagagawa natan",
     "currentevents-url": "Project:Saray nagagawa natan",
     "edithelp": "Tolong nipakar ed panagbalo na artikulo",
-    "helppage": "Help:Saray Laman",
     "mainpage": "Arapan ya Bolong",
     "mainpage-description": "Arapan ya Bolong",
     "portal": "Pwerta na komyunidad",
index 11c6ec4..d690593 100644 (file)
     "disclaimers": "Deklarashon di Liberashon for di Responsabilidatnan",
     "disclaimerpage": "Project:Deklarashon di Liberashon for di Responsabilidat General",
     "edithelp": "Ayudo ku editamentu",
-    "helppage": "Help:Kontenido",
     "mainpage": "Página Prinsipal",
     "mainpage-description": "Página Prinsipal",
     "policy-url": "Project:Pólisa",
index 92bf0e5..2a5329b 100644 (file)
     "disclaimers": "Impressum",
     "disclaimerpage": "Project:Impressum",
     "edithelp": "Help tom Beoabeide",
-    "helppage": "Help:Enhault",
     "mainpage": "Hauptsied",
     "mainpage-description": "Hauptsied",
     "policy-url": "Project:Policy",
index 6e370a0..3aabf75 100644 (file)
@@ -25,7 +25,6 @@
     "talk": "diskushun",
     "currentevents": "Dem Kurent Iwent",
     "currentevents-url": "Project:Dem Kurent Iwent",
-    "helppage": "Help:Dem Kontent",
     "mainpage": "Mien Paij",
     "mainpage-description": "Mien Paij",
     "portal": "Trii'nohlij",
index 78f0b92..4ace4aa 100644 (file)
@@ -61,7 +61,8 @@
             "Wpedzich",
             "Ymar",
             "Žekřil71pl",
-            "לערי ריינהארט"
+            "לערי ריינהארט",
+            "Pan Cube"
         ]
     },
     "tog-underline": "Podkreślenie linków:",
@@ -87,7 +88,7 @@
     "tog-enotifminoredits": "Wyślij e‐mail także w przypadku drobnych zmian na stronach lub w plikach",
     "tog-enotifrevealaddr": "Nie ukrywaj mojego adresu e‐mail w powiadomieniach",
     "tog-shownumberswatching": "Pokaż liczbę użytkowników obserwujących stronę",
-    "tog-oldsig": "Twój obecny podpis",
+    "tog-oldsig": "Twój obecny podpis:",
     "tog-fancysig": "Traktuj podpis jako wikikod (nie linkuj automatycznie całości)",
     "tog-uselivepreview": "Używaj dynamicznego podglądu (eksperymentalny)",
     "tog-forceeditsummary": "Informuj o niewypełnieniu opisu zmian",
     "underline-always": "zawsze",
     "underline-never": "nigdy",
     "underline-default": "według ustawień skórki lub przeglądarki",
-    "editfont-style": "Styl czcionki w polu edycyjnym",
+    "editfont-style": "Styl czcionki w polu edycyjnym:",
     "editfont-default": "domyślny przeglądarki",
     "editfont-monospace": "czcionka o stałej szerokości",
     "editfont-sansserif": "czcionka bezszeryfowa",
     "print": "Drukuj",
     "view": "Podgląd",
     "edit": "Edytuj",
+    "edit-local": "Edytuj lokalny opis",
     "create": "Utwórz",
+    "create-local": "Dodaj lokalny opis",
     "editthispage": "Edytuj tę stronę",
     "create-this-page": "Utwórz tę stronę",
     "delete": "Usuń",
     "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.",
     "userlogin-yourname": "Nazwa użytkownika",
     "userlogin-yourname-ph": "Wprowadź swoją nazwę użytkownika",
     "createacct-another-username-ph": "Wprowadź nazwę użytkownika",
-    "yourpassword": "Hasło",
+    "yourpassword": "Hasło:",
     "userlogin-yourpassword": "Hasło",
     "userlogin-yourpassword-ph": "Wpisz swoje hasło",
     "createacct-yourpassword-ph": "Wprowadź hasło",
     "accountcreatedtext": "Konto dla [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|dyskusja]]) zostało utworzone.",
     "createaccount-title": "Utworzenie konta w {{GRAMMAR:MS.lp|{{SITENAME}}}}",
     "createaccount-text": "Ktoś utworzył w {{GRAMMAR:MS.lp|{{SITENAME}}}} ($4), podając Twój adres e‐mail, konto „$2”. Aktualnym hasłem jest „$3”.\nZaloguj się teraz i je zmień.\n\nMożesz zignorować tę wiadomość, jeśli konto zostało utworzone przez pomyłkę.",
-    "usernamehasherror": "Nazwa użytkownika nie może zawierać znaków kratki „#”",
     "login-throttled": "Zbyt wiele razy próbowałeś zalogować się na to konto.\nOdczekaj $1 zanim ponowisz próbę.",
     "login-abort-generic": "Logowanie nieudane – przerwano",
     "loginlanguagelabel": "Język: $1",
     "search-error": "Wystąpił błąd podczas wyszukiwania:$1",
     "preferences": "Preferencje",
     "mypreferences": "Preferencje",
-    "prefs-edits": "Liczba edycji",
+    "prefs-edits": "Liczba edycji:",
     "prefsnologintext2": "Musisz $1 aby ustawić preferencje.",
     "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",
     "prefs-watchlist": "Obserwowane",
     "prefs-watchlist-days": "Liczba dni widocznych na liście obserwowanych",
     "prefs-watchlist-days-max": "Maksimum $1 {{PLURAL:$1|dzień|dni}}",
-    "prefs-watchlist-edits": "Liczba edycji pokazywanych w rozszerzonej liście obserwowanych",
+    "prefs-watchlist-edits": "Liczba edycji pokazywanych w rozszerzonej liście obserwowanych:",
     "prefs-watchlist-edits-max": "Maksymalnie 1000",
     "prefs-watchlist-token": "Identyfikator listy obserwowanych:",
     "prefs-misc": "Ustawienia różne",
     "saveprefs": "Zapisz",
     "restoreprefs": "Przywróć wszystkie domyślne preferencje (we wszystkich zakładkach)",
     "prefs-editing": "Edycja",
-    "rows": "Wiersze",
+    "rows": "Wiersze:",
     "columns": "Kolumny",
     "searchresultshead": "Wyszukiwanie",
     "stub-threshold": "Maksymalny (w bajtach) rozmiar strony oznaczanej jako <a href=\"#\" class=\"stub\">zalążek (stub)</a>",
     "prefs-help-recentchangescount": "Uwzględnia ostatnie zmiany, historię stron i rejestry.",
     "prefs-help-watchlist-token2": "To jest tajny klucz umożliwiający dostęp do kanału internetowego zmian w obserwowanych przez ciebie stronach.\nKażdy, kto go zna, będzie mógł je zobaczyć, więc zachowaj go dla siebie.\n[[Special:ResetTokens|Kliknij tu, jeśli musisz go zresetować]].",
     "savedprefs": "Twoje preferencje zostały zapisane.",
-    "timezonelegend": "Strefa czasowa",
-    "localtime": "Czas lokalny",
+    "timezonelegend": "Strefa czasowa:",
+    "localtime": "Czas lokalny:",
     "timezoneuseserverdefault": "Użyj domyślnej dla tej wiki ($1)",
     "timezoneuseoffset": "Inna (określ różnicę czasu)",
-    "servertime": "Czas serwera",
+    "servertime": "Czas serwera:",
     "guesstimezone": "Pobierz z przeglądarki",
     "timezoneregion-africa": "Afryka",
     "timezoneregion-america": "Ameryka",
     "prefs-files": "Pliki",
     "prefs-custom-css": "własny CSS",
     "prefs-custom-js": "własny JavaScript",
-    "prefs-common-css-js": "Wspólny CSS/JS dla wszystkich skórek",
+    "prefs-common-css-js": "Wspólny CSS/JS dla wszystkich skórek:",
     "prefs-reset-intro": "Na tej stronie można przywrócić domyślne ustawienia preferencji dla tej witryny.\nTej operacji nie można później cofnąć.",
-    "prefs-emailconfirm-label": "Potwierdzenie adresu e‐mail",
-    "youremail": "Twój adres e‐mail",
+    "prefs-emailconfirm-label": "Potwierdzenie adresu e‐mail:",
+    "youremail": "Twój adres e‐mail:",
     "username": "{{GENDER:$1|Nazwa użytkownika}}:",
     "uid": "{{GENDER:$1|Identyfikator użytkownika}}:",
     "prefs-memberingroups": "{{GENDER:$2|Członek}} {{PLURAL:$1|grupy|grup}}:",
-    "prefs-registration": "Data rejestracji",
-    "yourrealname": "Imię i nazwisko",
-    "yourlanguage": "Język interfejsu",
+    "prefs-registration": "Data rejestracji:",
+    "yourrealname": "Imię i nazwisko:",
+    "yourlanguage": "Język interfejsu:",
     "yourvariant": "Wariant języka treści",
     "prefs-help-variant": "Preferowany wariant ortografii, który ma zostać użyty przy wyświetlaniu treści tej wiki.",
-    "yournick": "Twój podpis",
+    "yournick": "Nowy podpis:",
     "prefs-help-signature": "Wypowiedzi na stronach dyskusji powinny być podpisywane za pomocą „<nowiki>~~~~</nowiki>”, dzięki temu automatycznie wstawiany jest Twój podpis wraz z bieżącą datą.",
     "badsig": "Nieprawidłowy podpis, sprawdź znaczniki HTML.",
     "badsiglength": "Twój podpis jest zbyt długi.\nDopuszczalna długość to $1 {{PLURAL:$1|znak|znaki|znaków}}.",
     "upload-permitted": "Dopuszczalne formaty plików: $1.",
     "upload-preferred": "Zalecane formaty plików: $1.",
     "upload-prohibited": "Zabronione formaty plików: $1.",
-    "uploadlog": "rejestr przesyłania plików",
     "uploadlogpage": "Przesłane",
     "uploadlogpagetext": "Lista ostatnio przesłanych plików.\nPrzejdź na stronę [[Special:NewFiles|galerii nowych plików]], by zobaczyć pliki jako miniaturki.",
     "filename": "Nazwa pliku",
     "filereuploadsummary": "Zmiany w pliku:",
     "filestatus": "Status prawny",
     "filesource": "Źródło",
-    "uploadedfiles": "Przesłane pliki",
     "ignorewarning": "Zignoruj ostrzeżenia i wymuś zapisanie pliku",
     "ignorewarnings": "Ignoruj wszystkie ostrzeżenia",
     "minlength1": "Nazwa pliku musi składać się co najmniej z jednej litery.",
     "overwroteimage": "przesłano nową wersję pliku „[[$1]]“",
     "uploaddisabled": "Przesyłanie plików wyłączone",
     "copyuploaddisabled": "Przesyłanie poprzez podanie adres URL jest wyłączone.",
-    "uploadfromurl-queued": "Żądanie przesłania pliku zostało dołączone do kolejki.",
     "uploaddisabledtext": "Możliwość przesyłania plików została wyłączona.",
     "php-uploaddisabledtext": "Przesyłanie plików PHP zostało zablokowane. Sprawdź ustawienie „file_uploads”.",
     "uploadscripted": "Plik zawiera kod HTML lub skrypt, który może zostać błędnie zinterpretowany przez przeglądarkę internetową.",
     "upload-misc-error": "Nieznany błąd przesyłania",
     "upload-misc-error-text": "Wystąpił nieznany błąd podczas przesyłania.\nSprawdź, czy podany adres URL jest poprawny i dostępny, a następnie spróbuj ponownie.\nJeśli problem będzie się powtarzał, skontaktuj się z [[Special:ListUsers/sysop|administratorem]].",
     "upload-too-many-redirects": "URL zawiera zbyt wiele przekierowań",
-    "upload-unknown-size": "Nieznany rozmiar",
     "upload-http-error": "Wystąpił błąd protokołu HTTP – $1",
     "upload-copy-upload-invalid-domain": "Przesyłanie kopii z tej domeny nie jest dostępne.",
     "backend-fail-stream": "Nie można odczytać pliku $1.",
     "img-auth-streaming": "Strumieniowanie „$1”.",
     "img-auth-public": "Funkcja img_auth.php służy do pobierania plików z prywatnej wiki.\nPonieważ ta wiki została skonfigurowana jako publiczna dla zapewnienia optymalnego bezpieczeństwa img_auth.php została wyłączona.",
     "img-auth-noread": "Użytkownik nie ma dostępu do odczytu „$1”.",
-    "img-auth-bad-query-string": "Adres URL zawiera nieprawidłowe zapytanie.",
     "http-invalid-url": "Niepoprawny adres URL: $1",
     "http-invalid-scheme": "Adresy „$1“ nie są obsługiwane.",
     "http-request-error": "Nieudane żądanie HTTP ze względu na nieznany błąd.",
     "filehist-dimensions": "Wymiary",
     "filehist-filesize": "Rozmiar pliku",
     "filehist-comment": "Opis",
-    "filehist-missing": "Brak pliku",
     "imagelinks": "Wykorzystanie pliku",
     "linkstoimage": "{{PLURAL:$1|Poniższa strona odwołuje|Następujące strony odwołują}} się do tego pliku:",
     "linkstoimage-more": "Więcej niż $1 {{PLURAL:$1|strona linkuje|strony linkują|stron linkuje}} do tego pliku.\nPoniższa lista pokazuje jedynie {{PLURAL:$1|pierwszy link|pierwsze $1 linki|pierwszych $1 linków}} do tego pliku.\nDostępna jest też [[Special:WhatLinksHere/$2|pełna lista]].",
     "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",
+    "listgrouprights-namespaceprotection-header": "Ograniczenia przestrzeni nazw",
+    "listgrouprights-namespaceprotection-namespace": "Przestrzeń nazw",
+    "listgrouprights-namespaceprotection-restrictedto": "Uprawnienia pozwalające użytkownikom na edytowanie",
+    "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.",
+    "post-expand-template-inclusion-category-desc": "Po rozwinięciu wszystkich szablonów, rozmiar strony jest większe niż <code>$wgMaxArticleSize</code>, 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",
     "emailuser-title-notarget": "Wyślij wiadomość e‐mail",
     "emailpage": "Wyślij e‐mail do użytkownika",
     "emailpagetext": "Możesz użyć poniższego formularza, aby wysłać wiadomość e‐mail do {{GENDER:$1|tego użytkownika|tej użytkowniczki}}.\nAdres e‐mailowy, który został przez Ciebie wprowadzony w [[Special:Preferences|Twoich preferencjach]], zostanie umieszczony w polu „Od”, dzięki czemu odbiorca będzie mógł Ci odpowiedzieć.",
-    "usermailererror": "Moduł obsługi poczty zwrócił błąd:",
     "defemailsubject": "{{SITENAME}} – e‐mail od użytkownika „$1“",
     "usermaildisabled": "E‐mail użytkownika jest wyłączony",
     "usermaildisabledtext": "Nie możesz wysyłać e‐maili do innych użytkowników tej wiki",
     "noemailtitle": "Brak adresu e‐mail",
     "noemailtext": "Ten użytkownik nie podał poprawnego adresu e‐mail.",
-    "nowikiemailtitle": "Brak zezwolenia na otrzymywanie e‐maili",
     "nowikiemailtext": "Ten użytkownik nie chce otrzymywać wiadomości e‐mail od innych użytkowników.",
     "emailnotarget": "Adresat nie istnieje lub podana nazwa użytkownika jest nieprawidłowa.",
     "emailtarget": "Wpisz nazwę użytkownika, który jest adresatem",
     "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",
     "watching": "Dodaję do obserwowanych...",
     "unwatching": "Przestaję obserwować...",
     "watcherrortext": "Wystąpił błąd podczas zmiany obecności „$1” na liście obserwowanych.",
-    "enotif_mailer": "Powiadomienie z {{GRAMMAR:D.lp|{{SITENAME}}}}",
     "enotif_reset": "Zaznacz wszystkie strony jako odwiedzone",
     "enotif_impersonal_salutation": "użytkownik {{GRAMMAR:D.lp|{{SITENAME}}}}",
     "enotif_subject_deleted": "Strona projektu {{SITENAME}} o nazwie $1 została usunięta przez {{gender:$2|$2}}",
     "excontent": "treść: „$1”",
     "excontentauthor": "treść: „$1” (jedyny autor: [[Special:Contributions/$2|$2]])",
     "exbeforeblank": "poprzednia zawartość, obecnie pustej strony: „$1”",
-    "exblank": "Strona była pusta",
     "delete-confirm": "Usuwanie „$1”",
     "delete-legend": "Usuń",
     "historywarning": "'''Uwaga!''' Strona, którą chcesz usunąć, ma w przybliżeniu {{PLURAL:$1|jedną starszą wersję|$1 starsze wersje|$1 starszych wersji}}:",
     "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",
     "importunknownsource": "Nieznany format importowanych danych",
     "importcantopen": "Nie można otworzyć importowanego pliku",
     "importbadinterwiki": "Błędny link interwiki",
-    "importnotext": "Brak tekstu lub zawartości",
     "importsuccess": "Import zakończony powodzeniem!",
-    "importhistoryconflict": "Wystąpił konflikt wersji (ta strona mogła zostać zaimportowana już wcześniej)",
     "importnosources": "Możliwość bezpośredniego importu historii została wyłączona, ponieważ nie zdefiniowano źródła.",
     "importnofile": "Importowany plik nie został przesłany.",
     "importuploaderrorsize": "Przesyłanie pliku importowanego zawiodło. Jest większy niż dopuszczalny rozmiar dla przesyłanych plików.",
     "pageinfo-firsttime": "Data utworzenia strony",
     "pageinfo-lastuser": "Autor ostatniej edycji",
     "pageinfo-lasttime": "Data ostatniej edycji",
-    "pageinfo-edits": "Liczba edycji",
+    "pageinfo-edits": "Całkowita liczba edycji",
     "pageinfo-authors": "Całkowita liczba autorów",
     "pageinfo-recent-edits": "Liczba ostatnich edycji (w przeciągu $1)",
     "pageinfo-recent-authors": "Liczba ostatnich autorów",
index be776ff..d3afed7 100644 (file)
     "accountcreatedtext": "Ël cont utent për [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|ciaciarade]]) a l'é stàit creà.",
     "createaccount-title": "Creassion d'un cont për {{SITENAME}}",
     "createaccount-text": "Cheidun a l'ha duvertà un cont për soa adrëssa ëd pòsta eletrònica ansima a {{SITENAME}} ($4) butand da stranòm «$2» e da ciav «$3». A dovrìa rintré ant ël sistema e cambiesse soa ciav pì ampressa ch'a peul.\n\nSe sòn a l'é rivà për eror, a peul lassé perde e fé gnente sensa problema.",
-    "usernamehasherror": "Lë stranòm d'utent a peul pa conten-e dij caràter ciapulà",
     "login-throttled": "A l'ha fàit tròpi tentativ recent d'intré ant ël sistema.\nPër piasì, ch'a speta $1 prima ëd prové torna.",
     "login-abort-generic": "Sò tentitiv d'intré ant ël sistema a l'é falì - Abortì",
     "loginlanguagelabel": "Lenga: $1",
     "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",
     "upload-permitted": "Sòrt d'archivi consentìe: $1.",
     "upload-preferred": "Sòrt d'archivi preferìe: $1.",
     "upload-prohibited": "Sòrt d'archivi proibìe: $1.",
-    "uploadlog": "Registr dij càrich",
     "uploadlogpage": "Registr dij càrich",
     "uploadlogpagetext": "Ambelessì-sota a-i é na lista dj'ùltim archivi carià.\nBeiché la [[Special:NewFiles|galarìa dj'archivi neuv]] për na presentassion pì visual.",
     "filename": "Nòm dl'archivi",
     "filereuploadsummary": "Modìfiche dl'archivi:",
     "filestatus": "Situassion dij drit d'autor:",
     "filesource": "Sorgiss:",
-    "uploadedfiles": "Archivi carià",
     "ignorewarning": "Lassé perde j'avis e salvé an tute le manere",
     "ignorewarnings": "Lassé perde j'avis",
     "minlength1": "Ij nòm ëd j'archivi a devo esse longh almanch un caràter.",
     "overwroteimage": "a l'ha carìa na version neuva ëd \"[[$1]]\"",
     "uploaddisabled": "Càrich blocà.",
     "copyuploaddisabled": "Ël càrich për mojen ëd n'adrëssa dl'aragnà a l'é disabilità.",
-    "uploadfromurl-queued": "Sò càrich a l'é stàit butà an coa.",
     "uploaddisabledtext": "La possibilità ëd carié dj'archivi a l'é staita disabilità.",
     "php-uploaddisabledtext": "Ij cariament d'archivi a son disabilità an PHP.\nPër piasì, ch'a controla l'ampostassion file_uploads.",
     "uploadscripted": "St'archivi-sì a l'ha andrinta chèich-còs (dël còdes HTML ò pura un senari) che a podrìa esse travajà mal da chèich programa ëd navigassion.",
     "upload-misc-error": "Eror nen identificà antramentr ch'as cariava",
     "upload-misc-error-text": "A l'é staie n'eror nen identificà dëmentrè ch'as cariava chèich-còs.\nPër piasì, ch'a varda che soa anliura a sia bon-a e che a rësponda e peuj ch'a preuva torna.\nSe a-i riva sossì n'àotra vira, ch'as buta an comunicassion con n'[[Special:ListUsers/sysop|aministrator]].",
     "upload-too-many-redirects": "L'adrëssa dl'aragnà a l'avìa tròpe ridiression",
-    "upload-unknown-size": "Dimension pa conossùa",
     "upload-http-error": "A l'é staje n'eror HTTP: $1.",
     "upload-copy-upload-invalid-domain": "Cariagi ëd cobie a l'é pa disponìbil da sto domini.",
     "backend-fail-stream": "A peul pa sequensialisé l'archivi $1.",
     "img-auth-streaming": "Letura an continuà ëd \"$1\".",
     "img-auth-public": "La funsion d'img_auth.php a l'é dë smone dj'archivi da na wiki privà.\nSta wiki-sì a l'é configurà com na wiki pùblica.\nPër na sicurëssa otimal, img_auth.php a l'é disabilità.",
     "img-auth-noread": "L'utent a l'ha pa ij privilegi për lese \"$1\".",
-    "img-auth-bad-query-string": "L'anliura a l'ha na stringa d'arcesta pa bon-a.",
     "http-invalid-url": "Adrëssa dl'aragnà pa bon-a: $1.",
     "http-invalid-scheme": "J'adrësse dl'aragnà con ël prefiss \"$1\" a son pa mantnùe.",
     "http-request-error": "L'arcesta Http a l'é falìa për n'eror pa conossù.",
     "filehist-dimensions": "Amzure",
     "filehist-filesize": "Amzure dl'archivi",
     "filehist-comment": "Coment",
-    "filehist-missing": "Archivi mancant",
     "imagelinks": "Usagi dl'archivi",
     "linkstoimage": "{{PLURAL:$1|La pàgina sì-sota a l'ha|Le $1 pàgine sì-sota a l'han}} andrinta dj'anliure a cost archivi:",
     "linkstoimage-more": "Pì che $1 {{PLURAL:$1|pàgina|pàgine}} a l'han dj'anliure a cost archivi.\nLa lista sì-sota a smon mach {{PLURAL:$1|la prima pàgina ch'a l'ha|le prime $1 pàgine ch'a l'han}} d'anliure a s'archivi.\nA l'é disponìbil na [[Special:WhatLinksHere/$2|lista completa]].",
     "emailuser-title-notarget": "Mandeje un mëssagi ëd pòsta eletrònica a st'utent-sì",
     "emailpage": "Mandeje un mëssagi ëd pòsta eletrònica a st'utent-sì",
     "emailpagetext": "A peul dovré ël formolari sì-sota për mandé un mëssagi ëd pòsta eletrònica a st'{{GENDER:$1|utent}}-sì.\nL'adrëssa ëd pòsta eletrònica ch'a l'ha butà ant ij [[Special:Preferences|sò gust]] a sarà butà ant l'adrëssa «Da» ëd sò mëssagi, parèj chi ch'a l'arsèiv a podrà rësponde diretament a chiel.",
-    "usermailererror": "L'oget che a goèrna la pòsta eletrònica a l'ha dàit eror:",
     "defemailsubject": "Mëssagi da l'utent \"$1\"",
     "usermaildisabled": "Pòsta eletrònica dl'utent disabilità",
     "usermaildisabledtext": "A peul pa mandé ëd mëssagi ëd pòsta eletrònica a d'àutri utent ansima a costa wiki",
     "noemailtitle": "Gnun-a adrëssa ëd pòsta eletrònica",
     "noemailtext": "Cost utent-sì a l'ha pa spessificà n'adrëssa ëd pòsta eletrònica vàlida.",
-    "nowikiemailtitle": "Gnun mëssagi ëd pòsta eletrònica a l'é autorisà",
     "nowikiemailtext": "Cost utent a l'ha sërnù ëd nen arsèive dij mëssagi ëd pòsta eletrònica da j'àutri utent.",
     "emailnotarget": "Stranòm dël destinatari pa esistent o pa bon.",
     "emailtarget": "Ch'a anserissa lë stranòm dël destinatari",
     "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",
     "watching": "Sot-euj...",
     "unwatching": "Ën gavand da lòn ch'as ten sot-euj...",
     "watcherrortext": "A l'é capitaje n'eror durant la modìfica ëd j'ampostassion ëd lòn ch'as ten sot-euj për «$1».",
-    "enotif_mailer": "{{SITENAME}} - Servissi ëd Notìfica Postal",
     "enotif_reset": "Marché tute le pàgine tanme visità",
     "enotif_impersonal_salutation": "utent ëd {{SITENAME}}",
     "enotif_subject_deleted": "La pàgina $1 ëd {{SITENAME}} a l'é stàita scancelà da {{gender:$2|$2}}",
     "excontent": "Ël contnù a l'era: '$1'",
     "excontentauthor": "ël contnù a l'era: «$1» (e l'ùnich contributor a l'era stàit «[[Special:Contributions/$2|$2]]»)",
     "exbeforeblank": "anans d'esse dësvujdà ël contnù a l'era: «$1»",
-    "exblank": "La pàgina a l'era veujda",
     "delete-confirm": "Scancelé «$1»",
     "delete-legend": "Scancelé",
     "historywarning": "'''Avis:''' La pàgina che a l'é antramentr che a scancela a l'ha na stòria con pi o men $1 {{PLURAL:$1|revision|revision}}:",
     "importunknownsource": "Sorgiss d'amportassion ëd na sòrt nen conossùa",
     "importcantopen": "L'archivi da amporté a l'é pa podusse deurbe",
     "importbadinterwiki": "Liura antra wiki diferente cioca",
-    "importnotext": "Veujd o con gnun test",
     "importsuccess": "Amportassion finìa!",
-    "importhistoryconflict": "A-i son dle stòrie dë sta pàgina-sì che as contradiso un-a con l'àutra (a peul esse che sta pàgina-sì a l'avèissa già amportala)",
     "importnosources": "A l'é pa stàita definìa gnun-a sorgiss d'amportassion da na wiki diferenta, e carié mach le stòrie as peul nen.",
     "importnofile": "Pa gnun archivi d'amportassion carià.",
     "importuploaderrorsize": "A l'é falìe la caria dl'archivi d'amporté. L'archivi a resta pì gròss che lòn ch'as peul cariesse.",
index d938512..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": "اکھ تھلیوں ہٹاؤ",
index 5610bc0..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",
index df119de..349fa77 100644 (file)
     "accountcreatedtext": "د [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|خبرې اترې]]) لپاره يو گڼون جوړ شو.",
     "createaccount-title": "د {{SITENAME}} د گڼون جوړېدنه",
     "createaccount-text": "يو چا د {{SITENAME}} په وېبځي ($4) کې ستاسې د برېښليک پتې لپاره د \"$2\" په نامه يو گڼون جوړ کړی چې پټنوم يې \"$3\" دی.\nتاسې بايد غونډال ته ورننوځۍ او همدا اوس خپل پټنوم بدل کړی.\n\nکه چېرته دا کړنه په تېروتنه کې شوی وي نو تاسې کولای شی چې دا پيغام بابېزه وگڼۍ.",
-    "usernamehasherror": "کارن-نوم نشي کېدلای چې کرښکې لوښې ولري",
     "login-throttled": "تاسې څو واره هڅه کړې چې غونډال ته ورننوځۍ.\nلطفاً د بيا هڅې نه مخکې $1 شېبې تم شۍ.",
     "login-abort-generic": "غونډال کې مو ننوتل نابريالی شو - ناڅاپي بند شو",
     "loginlanguagelabel": "ژبه: $1",
     "prefs-skin": "پوښۍ",
     "skin-preview": "مخکتنه",
     "datedefault": "هېڅ نه ټاکل",
-    "prefs-beta": "د آزمېښتي بڼې ځانگړنې",
     "prefs-datetime": "نېټه او وخت",
     "prefs-labs": "د آزمېښتون ځانگړنې",
     "prefs-user-pages": "کارن مخونه",
     "upload-permitted": "د پرېښودلو دوتنو ډولونه: $1.",
     "upload-preferred": "د غوره دوتنو ډولونه: $1.",
     "upload-prohibited": "د منع شويو دوتنو ډولونه: $1.",
-    "uploadlog": "د پورته شويو دوتنو يادښت",
     "uploadlogpage": "د پورته شويو دوتنو يادښت",
     "uploadlogpagetext": "دا لاندې د نوو پورته شوو دوتنو لړليک دی.",
     "filename": "د دوتنې نوم",
     "filereuploadsummary": "د دوتنې بدلونونه:",
     "filestatus": "د رښتو دريځ:",
     "filesource": "سرچينه:",
-    "uploadedfiles": "پورته شوې دوتنې",
     "ignorewarning": "گواښنه بې پامه گڼل او دوتنه خوندي کول",
     "ignorewarnings": "هر ډول ګواښونه له پامه غورځول",
     "minlength1": "پکار ده چې د دوتنو نومونه لږ تر لږه يو حرف ولري.",
     "upload-warning-subj": "د پورته کولو ګواښ",
     "upload-proto-error": "ناسم پروتوکول",
     "upload-file-error": "کورنۍ ستونزه",
-    "upload-unknown-size": "ناڅرګنده کچه",
     "upload-http-error": "د HTTP يوه ستونزه رامېنځ ته شوې: $1",
     "backend-fail-notexists": "د $1 په نوم دوتنه نشته.",
     "backend-fail-delete": "د \"$1\" دوتنه ړنګه نه شوه.",
     "filehist-dimensions": "ډډې",
     "filehist-filesize": "د دوتنې کچه",
     "filehist-comment": "تبصره",
-    "filehist-missing": "دوتنه ورکه ده",
     "imagelinks": "د دوتنې کارېدنه",
     "linkstoimage": "دا {{PLURAL:$1|لاندينی مخ|$1 لانديني مخونه}} د همدې دوتنې سره تړنې لري:",
     "nolinkstoimage": "داسې هېڅ کوم مخ نه شته چې د دغې دوتنې سره تړنې ولري.",
     "usermaildisabled": "د کارن برېښليک ناچارند دی",
     "usermaildisabledtext": "په دې ويکي تاسې نورو کارنانو ته برېښليک نه شی ورلېږلی",
     "noemailtitle": "هېڅ کومه برېښليک پته نشته.",
-    "nowikiemailtitle": "د برېښليک لېږلو اجازه نشته",
     "nowikiemailtext": "دې کارن د نورو کارنانو لخوا د برېښليک د نه ترلاسه کولو چاره خوښه کړې.",
     "emailtarget": "د ترلاسه کوونکي کارن-نوم وټاپۍ",
     "emailusername": "کارن-نوم:",
     "nowatchlist": "ستاسې کتنلړ کې څه نه شته.",
     "watchlistanontext": "د خپل کتنلړ د توکو د سمولو او کتلو لپاره $1 ترسره کړۍ.",
     "watchnologin": "غونډال کې نه ياست ننوتي.",
-    "watchnologintext": "ددې لپاره چې خپل کتنلړ کې بدلون راولی نو تاسو ته پکار ده چې لومړی غونډال کې [[Special:UserLogin|ورننوځۍ]].",
     "addwatch": "کتنلړ کې ورگډول",
     "addedwatchtext": "د \"[[:$1]]\" په نوم يو مخ ستاسې [[Special:Watchlist|کتنلړ]] کې ورگډ شو.\nپه راتلونکې کې چې په دغه مخ او د دې د خبرواترو مخ کې کوم بدلونونه راځي نو هغه به ستاسې کتنلړ کې ښکاري.",
     "removewatch": "له کتنلړ نه غورځول",
     "watchlist-options": "د کتنلړ خوښنې",
     "watching": "د کتلو په حال کې...",
     "unwatching": "د نه کتلو په حال کې...",
-    "enotif_mailer": "د {{SITENAME}} خبرتيايي برېښليک",
     "enotif_reset": "ټول مخونه کتل شوي نخښه کول",
     "enotif_impersonal_salutation": "{{SITENAME}} کارن",
     "enotif_subject_deleted": "د {{SITENAME}} مخ $1 د {{gender:$2|$2}} لخوا ړنگ شوی",
     "confirm": "تاييد",
     "excontent": "د مخ مېنځپانگه دا وه: \"$1\"",
     "excontentauthor": "د مخ مېنځپانگه دا وه: \"$1\" (او يواځينی ونډه وال \"[[Special:Contributions/$2|$2]]\" وه)",
-    "exblank": "مخ تش وه",
     "delete-confirm": "\"$1\" ړنگول",
     "delete-legend": "ړنگول",
     "historywarning": "گواښنه:''' دا مخ چې تاسې يې د ړنگېدو تکل لرئ نژدې $1 {{PLURAL:$1|بڼه|بڼې}} پېښليک لري:",
     "import-upload-filename": "د دوتنې نوم:",
     "import-comment": "تبصره:",
     "import-revision-count": "$1 {{PLURAL:$1|بڼه|بڼې}}",
-    "importnotext": "تش او يا بې متنه مخ",
     "importlogpage": "د واردولو يادښت",
     "import-logentry-upload-detail": "$1 {{PLURAL:$1|بڼه|بڼې}}",
     "javascripttest": "د جاوا سکرېپټ آزمېښت",
index adb47ca..ed57c31 100644 (file)
@@ -69,7 +69,8 @@
             "Waldir",
             "Yves Marques Junqueira",
             "לערי ריינהארט",
-            "555"
+            "555",
+            "Fabsouza1"
         ]
     },
     "tog-underline": "Sublinhar links:",
     "print": "Imprimir",
     "view": "Ver",
     "edit": "Editar",
+    "edit-local": "Editar descrição local",
     "create": "Criar",
+    "create-local": "Adicionar descrição local",
     "editthispage": "Editar esta página",
     "create-this-page": "Iniciar esta página",
     "delete": "Eliminar",
     "pool-timeout": "Tempo limite de espera para o bloqueio excedido",
     "pool-queuefull": "A fila de processos está cheia",
     "pool-errorunknown": "Erro desconhecido",
+    "pool-servererror": "O servidor de contador do pool não está disponível ($1).",
     "aboutsite": "Sobre {{SITENAME}}",
     "aboutpage": "Project:Sobre",
     "copyright": "Conteúdo disponível sob $1, salvo indicação em contrário.",
     "gotaccountlink": "Autenticar-se",
     "userlogin-resetlink": "Esqueceu-se do seu nome de usuário ou da senha?",
     "userlogin-resetpassword-link": "Esqueceu sua senha?",
+    "userlogin-helplink2": "Ajuda com o login",
     "userlogin-loggedin": "Você já está conectado como {{GENDER:$1|$1}}.\nUse o formulário abaixo para iniciar sessão como outro usuário.",
     "userlogin-createanother": "Crie uma outra conta",
     "createacct-join": "Insira suas informações abaixo.",
     "accountcreatedtext": "A conta de usuário para [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|talk]]) foi criada.",
     "createaccount-title": "Criação de conta em {{SITENAME}}",
     "createaccount-text": "Alguém criou uma conta de nome $2 para o seu endereço de email no wiki {{SITENAME}} ($4), tendo como senha \"$3\".\nVocê deve se autenticar e alterar sua senha.\n\nIgnore esta mensagem caso a conta tenha sido criada por engano.",
-    "usernamehasherror": "Nome de usuário não pode conter o símbolo de cardinal (#).",
     "login-throttled": "Você recentemente tentou iniciar sessão muitas vezes.\nPor favor aguarde $1 antes de tentar novamente.",
     "login-abort-generic": "A sua autenticação não teve êxito - Abortada",
     "loginlanguagelabel": "Idioma: $1",
     "resetpass-abort-generic": "Uma extensão cancelou a alteração da senha.",
     "resetpass-expired": "Sua senha expirou. Por favor insira uma nova senha para autenticar-se.",
     "resetpass-expired-soft": "Sua senha expirou e necessita ser resetada. Por favor escolha uma nova agora, ou clique \"{{int:resetpass-submit-cancel}}\" para resetar mais tarde.",
+    "resetpass-validity-soft": "Sua senha não é válida: $1\n\nPor favor escolha uma nova senha agora, ou clique \"{{int:resetpass-submit-cancel}}\" para redefini-la mais tarde.",
     "passwordreset": "Redefinir senha",
     "passwordreset-text-one": "Complete este formulário para trocar sua senha.",
     "passwordreset-text-many": "{{PLURAL:$1|Preencha um dos campos para trocar sua senha.}}",
     "revdelete-no-file": "O arquivo especificado não existe.",
     "revdelete-show-file-confirm": "Tem a certeza de que quer visualizar uma revisão eliminada do arquivo \"<nowiki>$1</nowiki>\" de $2 em $3?",
     "revdelete-show-file-submit": "Sim",
+    "revdelete-selected-text": "'''{{PLURAL:$1|Revisão selecionada|Revisões selecionadas}} de [[:$1]]:'''",
+    "revdelete-selected-file": "{{PLURAL:$1|Versão do arquivo selecionado|Versões do arquivo selecionado}} of [[:$2]]:",
     "logdelete-selected": "{{PLURAL:$1|Evento de registro selecionado|Eventos de registro selecionados}}:",
     "revdelete-text-text": "Revisões apagadas continuarão a aparecer na página de histórico, mas parte de seus conteúdos estarão inacessíveis ao público.",
     "revdelete-text-file": "Versões dos arquivos apagados continuarão a aparecer no arquivo de histórico, mas parte de seus conteúdos estarão inacessíveis ao público.",
     "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",
     "upload-permitted": "Tipos de arquivos permitidos: $1.",
     "upload-preferred": "Tipos de arquivos preferidos: $1.",
     "upload-prohibited": "Tipos de arquivo proibidos: $1.",
-    "uploadlog": "registro de uploads",
     "uploadlogpage": "Registro de uploads",
     "uploadlogpagetext": "Segue listagem dos uploads de arquivos mais recentes.\nA [[Special:NewFiles|galeria de arquivos novos]] oferece uma listagem mais visual.",
     "filename": "Nome do arquivo",
     "filereuploadsummary": "Alterações no arquivo:",
     "filestatus": "Status dos direitos autorais:",
     "filesource": "Fonte:",
-    "uploadedfiles": "Arquivos enviados",
     "ignorewarning": "Ignorar aviso e salvar mesmo assim.",
     "ignorewarnings": "Ignorar todos os avisos",
     "minlength1": "Os nomes de arquivos precisam ter pelo menos uma letra.",
     "overwroteimage": "enviou uma nova versão de \"[[$1]]\"",
     "uploaddisabled": "Envio de arquivos desativado.",
     "copyuploaddisabled": "O upload por URL encontra-se desativado.",
-    "uploadfromurl-queued": "O seu upload foi adicionado à fila.",
     "uploaddisabledtext": "O envio de arquivos encontra-se desativado.",
     "php-uploaddisabledtext": "O envio de arquivos via PHP está desativado.\nVerifique a configuração file_uploads.",
     "uploadscripted": "Este arquivo contém HTML ou código que pode ser erroneamente interpretado por um navegador web.",
     "upload-misc-error": "Erro desconhecido ao enviar",
     "upload-misc-error-text": "Ocorreu um erro desconhecido durante o envio.\nVerifique se o endereço (URL) é válido e acessível e tente novamente.\nCaso o problema persista, procure um [[Special:ListUsers/sysop|administrador]].",
     "upload-too-many-redirects": "A URL contém redirecionamentos demais",
-    "upload-unknown-size": "Tamanho desconhecido",
     "upload-http-error": "Ocorreu um erro HTTP: $1",
     "upload-copy-upload-invalid-domain": "Não é possível realizar envios remotos neste domínio.",
     "backend-fail-stream": "Não foi possível transmitir o arquivo  $1.",
     "img-auth-streaming": "Realizando ''streaming'' de \"$1\".",
     "img-auth-public": "A img_auth.php produz arquivos a partir de um wiki privado.\nEste wiki está configurado como um wiki público.\nPara melhor segurança, o img_auth.php está desativado.",
     "img-auth-noread": "Usuário não tem acesso para ler \"$1\".",
-    "img-auth-bad-query-string": "A URL tem um texto de consulta inválido.",
     "http-invalid-url": "URL inválida: $1",
     "http-invalid-scheme": "URLs que iniciam com o prefixo \"$1\" não são aceitas.",
     "http-request-error": "A requisição HTTP falhou devido a um erro desconhecido.",
     "filehist-dimensions": "Dimensões",
     "filehist-filesize": "Tamanho do arquivo",
     "filehist-comment": "Comentário",
-    "filehist-missing": "Arquivo faltando",
     "imagelinks": "Uso do arquivo",
     "linkstoimage": "{{PLURAL:$1|A página|As $1 páginas}} a seguir tem link para este arquivo:",
     "linkstoimage-more": "Mais de $1 {{PLURAL:$1|página|páginas}} tem algum link para este arquivo.\nA lista a seguir mostra apenas {{PLURAL:$1|o primeiro link|os $1 primeiros links}} para este arquivo.\nUma [[Special:WhatLinksHere/$2|listagem completa]] está disponível.",
     "download": "download",
     "unwatchedpages": "Páginas não vigiadas",
     "listredirects": "Listar redirecionamentos",
+    "listduplicatedfiles": "Lista de arquivos com duplicatas",
+    "listduplicatedfiles-summary": "Esta é uma lista de arquivos, onde a versão mais recente do arquivo é uma duplicata da versão mais recente de algum outro arquivo. Somente os arquivos locais são considerados.",
+    "listduplicatedfiles-entry": "O arquivo [[:File:$1|$1]] tem [[$3|{{PLURAL:$2|uma duplicata|$2 duplicatas}}]].",
     "unusedtemplates": "Predefinições não utilizadas",
     "unusedtemplatestext": "Esta página lista todas as páginas no espaço nominal {{ns:template}} que não estão incluídas em uma outra página. Lembre-se de conferir se há outros links para as predefinições antes de apaga-las.",
     "unusedtemplateswlh": "outros links",
     "protectedpages-unknown-timestamp": "Desconhecido",
     "protectedpages-unknown-performer": "Usuário desconhecido",
     "protectedtitles": "Títulos protegidos",
-    "protectedtitles-summary": "Está página lista os títulos já protegidos de criação. Para ver a lista de páginas existentes que estão protegidas, consulte [[{{#special:ProtectedPages}}|{{int:protectedpages}}]].",
+    "protectedtitles-summary": "Está página lista os títulos já protegidos desde a criação. Para ver a lista de páginas existentes que estão protegidas, consulte [[{{#special:ProtectedPages}}|{{int:protectedpages}}]].",
     "protectedtitlesempty": "Neste momento, nenhum dos títulos está protegido com estes parâmetros.",
     "listusers": "Lista de usuários",
     "listusers-editsonly": "Mostrar apenas usuários com edições",
     "listgrouprights-removegroup-self": "Pode remover {{PLURAL:$2|grupo|grupos}} da própria conta: $1",
     "listgrouprights-addgroup-self-all": "Pode adicionar todos os grupos à própria conta",
     "listgrouprights-removegroup-self-all": "Pode remover todos os grupos da própria conta",
+    "trackingcategories": "Monitorando categorias",
     "mailnologin": "Nenhum endereço de envio",
     "mailnologintext": "Necessita de estar [[Special:UserLogin|autenticado]] e de possuir um endereço de e-mail válido nas suas [[Special:Preferences|preferências]] para poder enviar um e-mail a outros usuários.",
     "emailuser": "Enviar-lhe um e-mail",
     "emailuser-title-notarget": "Enviar e-mail",
     "emailpage": "Contactar usuário",
     "emailpagetext": "Você pode usar o formulário a seguir para enviar um e-mail para {{GENDER:$1|este usuário|esta usuária}}.\nO endereço de e-mail que você inseriu em [[Special:Preferences|suas preferências de usuário]] irá aparecer como o endereço do remetente da mensagem, com o destinatário podendo responder diretamente para você.",
-    "usermailererror": "Erro no email:",
     "defemailsubject": "E-mail do usuário \"$1\" da {{SITENAME}}",
     "usermaildisabled": "O e-mail do usuário foi desativado",
     "usermaildisabledtext": "Você não tem como enviar e-mails a outros usuários deste wiki.",
     "noemailtitle": "Sem endereço de e-mail",
     "noemailtext": "Este usuário não especificou um endereço de e-mail válido.",
-    "nowikiemailtitle": "E-mail não permitido",
     "nowikiemailtext": "Este usuário optou por não receber e-mail de outros usuários.",
     "emailnotarget": "O nome do destinatário não existe ou é inválido.",
     "emailtarget": "Insira o nome de usuário do destinatá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",
     "watching": "Vigiando...",
     "unwatching": "Deixando de vigiar...",
     "watcherrortext": "Ocorreu um erro ao alterar a configuração da sua lista de páginas vigiadas para \"$1\".",
-    "enotif_mailer": "{{SITENAME}} Email de Notificação",
     "enotif_reset": "Marcar todas páginas como visitadas",
     "enotif_impersonal_salutation": "Usuário do projeto \"{{SITENAME}}\"",
     "enotif_subject_deleted": "A página $1 da {{SITENAME}} foi eliminada por {{gender:$2|$2}}",
     "excontent": "o conteúdo era: '$1'",
     "excontentauthor": "o conteúdo era: \"$1\" (e o único editor era \"[[Special:Contributions/$2|$2]]\")",
     "exbeforeblank": "o conteúdo antes de esvaziar era: '$1'",
-    "exblank": "página esvaziada",
     "delete-confirm": "Eliminar \"$1\"",
     "delete-legend": "Eliminar",
     "historywarning": "'''Atenção:''' A página que você está prestes a eliminar possui um histórico com aproximadamente $1 {{PLURAL:$1|revisão|revisões}}:",
     "importunknownsource": "Tipo de fonte de importação desconhecida",
     "importcantopen": "Não foi possível abrir o arquivo de importação",
     "importbadinterwiki": "Ligação de interwiki incorreta",
-    "importnotext": "Vazio ou sem texto",
     "importsuccess": "Importação completa!",
-    "importhistoryconflict": "Existem conflitos de edições no histórico (talvez esta página já foi importada antes)",
     "importnosources": "Não foram definidas fontes de importação transwiki e o carregamento direto de históricos encontra-se desativado.",
     "importnofile": "Nenhum arquivo de importação foi carregado.",
     "importuploaderrorsize": "O envio do arquivo a ser importado falhou. O arquivo é maior do que o tamanho máximo permitido para upload.",
index 95507bd..c7849f5 100644 (file)
     "permalink": "Ligação permanente",
     "print": "Imprimir",
     "view": "Ver",
+    "view-foreign": "Ver em $1",
     "edit": "Editar",
+    "edit-local": "Editar descrição local",
     "create": "Criar",
     "editthispage": "Editar esta página",
     "create-this-page": "Criar esta página",
     "accountcreatedtext": "A conta de utilizador para [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|talk]]) foi criada.",
     "createaccount-title": "Criação de conta na {{SITENAME}}",
     "createaccount-text": "Alguém criou uma conta com o nome $2 para o seu endereço de correio eletrónico, na wiki {{SITENAME}} ($4), com a palavra-chave \"$3\".\nDeve agora autenticar-se e alterar a sua palavra-chave.\n\nSe a conta foi criada por engano, pode ignorar esta mensagem.",
-    "usernamehasherror": "O nome de utilizador não pode conter o símbolo de cardinal (#).",
     "login-throttled": "Realizou demasiadas tentativas de autenticação com esta conta.\nAguarde $1 antes de tentar novamente, por favor.",
     "login-abort-generic": "A sua autenticação não teve êxito - Cancelada",
     "loginlanguagelabel": "Língua: $1",
     "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",
     "upload-permitted": "Tipos de ficheiro permitidos: $1.",
     "upload-preferred": "Tipos de ficheiro preferidos: $1.",
     "upload-prohibited": "Tipos de ficheiro proibidos: $1.",
-    "uploadlog": "registo de carregamento",
     "uploadlogpage": "Registo de carregamento",
     "uploadlogpagetext": "Segue-se uma lista dos carregamentos mais recentes.\nConsulte a [[Special:NewFiles|galeria de novos ficheiros]] para visioná-los.",
     "filename": "Nome do ficheiro",
     "filereuploadsummary": "Alterações ao ficheiro:",
     "filestatus": "Estado dos direitos de autor:",
     "filesource": "Fonte:",
-    "uploadedfiles": "Ficheiros carregados",
     "ignorewarning": "Ignorar o aviso e gravar o ficheiro.",
     "ignorewarnings": "Ignorar todos os avisos",
     "minlength1": "Os nomes de ficheiros devem de ter pelo menos uma letra.",
     "overwroteimage": "enviou uma nova versão de \"[[$1]]\"",
     "uploaddisabled": "Carregamentos impossibilitados",
     "copyuploaddisabled": "Upload por URL impossibilitado.",
-    "uploadfromurl-queued": "O seu upload foi adicionado à fila.",
     "uploaddisabledtext": "O carregamento de ficheiros está impossibilitado.",
     "php-uploaddisabledtext": "O carregamento de ficheiros está impossibilitado no PHP.\nVerifique a configuração file_uploads, por favor.",
     "uploadscripted": "Este ficheiro contém HTML ou código que pode ser erradamente interpretado por um browser.",
     "upload-misc-error": "Erro de carregamento desconhecido",
     "upload-misc-error-text": "Ocorreu um erro desconhecido durante o envio.\nVerifique se o endereço (URL) é válido e acessível e tente novamente.\nCaso o problema persista, contacte um [[Special:ListUsers/sysop|administrador]].",
     "upload-too-many-redirects": "A URL continha demasiados redirecionamentos",
-    "upload-unknown-size": "Tamanho desconhecido",
     "upload-http-error": "Ocorreu um erro HTTP: $1",
     "upload-copy-upload-invalid-domain": "Não é possível realizar carregamentos remotos neste domínio.",
     "backend-fail-stream": "Não foi possível transmitir o ficheiro $1.",
     "img-auth-streaming": "A fazer o ''streaming'' de \"$1\".",
     "img-auth-public": "A função do img_auth.php é produzir ficheiros a partir de uma wiki privada.\nEsta wiki está configurada como uma wiki pública.\nPara optimizar a segurança, o img_auth.php está impossibilitado de executar.",
     "img-auth-noread": "O utilizador não tem acesso de leitura ao ficheiro \"$1\".",
-    "img-auth-bad-query-string": "A URL tem um texto de consulta inválido.",
     "http-invalid-url": "URL inválida: $1",
     "http-invalid-scheme": "URLs iniciadas pelo prefixo \"$1\" não são aceites.",
     "http-request-error": "O pedido HTTP falhou devido a um erro desconhecido.",
     "filehist-dimensions": "Dimensões",
     "filehist-filesize": "Tamanho do ficheiro",
     "filehist-comment": "Comentário",
-    "filehist-missing": "Ficheiro em falta",
     "imagelinks": "Uso do ficheiro",
     "linkstoimage": "{{PLURAL:$1|A seguinte página contém|As seguintes $1 páginas contêm}} links para este ficheiro:",
     "linkstoimage-more": "Mais de {{PLURAL:$1|uma página contém|$1 páginas contêm}} links para este ficheiro.\nA lista abaixo apresenta apenas {{PLURAL:$1|a primeira página|as primeiras $1 páginas}}.\nEncontra-se disponível uma [[Special:WhatLinksHere/$2|lista completa]].",
     "listgrouprights-removegroup-self": "Remover a própria conta {{PLURAL:$2|do grupo|dos grupos}}: $1",
     "listgrouprights-addgroup-self-all": "Adicionar a própria conta a todos os grupos",
     "listgrouprights-removegroup-self-all": "Remover a própria conta de todos os grupos",
+    "listgrouprights-namespaceprotection-header": "Restrições do campo nominal",
+    "listgrouprights-namespaceprotection-namespace": "Campo nominal",
+    "trackingcategories-name": "Nome da mensagem",
     "mailnologin": "Não existe endereço de envio",
     "mailnologintext": "Precisa de estar [[Special:UserLogin|autenticado]] e ter um endereço de correio válido nas suas [[Special:Preferences|preferências]], para poder enviar correio eletrónico a outros utilizadores.",
     "emailuser": "Enviar correio eletrónico a este utilizador",
     "emailuser-title-notarget": "Enviar correio eletrónico ao utilizador",
     "emailpage": "Enviar correio eletrónico ao utilizador",
     "emailpagetext": "Pode usar o formulário abaixo para enviar uma mensagem por correio eletrónico para {{GENDER:$1|este utilizador|esta utilizadora}}.\nO endereço de correio que introduziu nas [[Special:Preferences|suas preferências]] irá aparecer no campo do remetente da mensagem \"De:\", para que o destinatário lhe possa responder diretamente.",
-    "usermailererror": "O sistema de correio devolveu o erro:",
     "defemailsubject": "Correio eletrónico da {{SITENAME}}, do utilizador \"$1\"",
     "usermaildisabled": "O correio eletrónico do utilizador foi desativado",
     "usermaildisabledtext": "Não pode enviar correio eletrónico a outros utilizadores desta wiki",
     "noemailtitle": "Sem endereço de correio eletrónico",
     "noemailtext": "Este utilizador não especificou um endereço de correio eletrónico válido.",
-    "nowikiemailtitle": "Correio eletrónico não é permitido",
     "nowikiemailtext": "Este utilizador optou por não receber correio eletrónico de outros utilizadores.",
     "emailnotarget": "O nome do destinatário não existe ou é inválido.",
     "emailtarget": "Introduza o nome de utilizador do destinatário.",
     "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",
     "watching": "A vigiar...",
     "unwatching": "Deixando de vigiar...",
     "watcherrortext": "Ocorreu um erro ao alterar a configuração da sua lista de páginas vigiadas para \"$1\".",
-    "enotif_mailer": "Gerador de Notificações da {{SITENAME}}",
     "enotif_reset": "Marcar todas as páginas como visitadas",
     "enotif_impersonal_salutation": "Utilizador da \"{{SITENAME}}\"",
     "enotif_subject_deleted": "A página  $1 de {{SITENAME}} foi {{GENDER:$2|eliminada}} por $2",
     "excontent": "o conteúdo era: \"$1\"",
     "excontentauthor": "o conteúdo era: \"$1\" (e o único editor era [[Special:Contributions/$2|$2]]\")",
     "exbeforeblank": "o conteúdo antes de esvaziar era: \"$1\"",
-    "exblank": "página esvaziada",
     "delete-confirm": "Eliminar \"$1\"",
     "delete-legend": "Eliminar",
     "historywarning": "'''Aviso:''' A página que está prestes a eliminar tem um histórico com aproximadamente $1 {{PLURAL:$1|revisão|revisões}}:",
     "importunknownsource": "Tipo da fonte de importação desconhecido",
     "importcantopen": "Não foi possível abrir o ficheiro a importar",
     "importbadinterwiki": "Link interwikis incorrecto",
-    "importnotext": "Vazio ou sem texto",
     "importsuccess": "Importação completa!",
-    "importhistoryconflict": "Existem conflitos de edições no histórico (talvez esta página já tenha sido importada anteriormente)",
     "importnosources": "Não foram definidas fontes de importação transwikis e o carregamento direto de históricos encontra-se desativado.",
     "importnofile": "Nenhum ficheiro de importação foi carregado.",
     "importuploaderrorsize": "O carregamento do ficheiro importado falhou.\nO ficheiro é maior do que o tamanho máximo permitido.",
index 18fb0f3..3754086 100644 (file)
             "Žekřil71pl",
             "פוילישער",
             "គីមស៊្រុន",
-            "아라"
+            "아라",
+            "Jdforrester"
         ]
     },
     "sidebar": "{{notranslate}}",
     "category-media-header": "In category description page. Parameters:\n* $1 - category name\nSee also:\n* {{msg-mw|Category header}}",
     "category-empty": "The text displayed in category page when that category is empty",
     "hidden-categories": "Used in the categories section of pages.\n\nFollowed by a colon and a list of categories.\n\nParameters:\n* $1 - number of hidden categories\n{{Identical|Hidden category}}",
-    "hidden-category-category": "Name of the [[mw:Help:Tracking categories|tracking category]] where hidden categories will be listed.\n{{Identical|Hidden category}}",
+    "hidden-category-category": "Name of the [[mw:Special:MyLanguage/Help:Tracking categories|tracking category]] where hidden categories will be listed.\n\nSee also:\n* {{msg-mw|Hidden-category-category-desc}}\n{{Identical|Hidden category}}",
     "category-subcat-count": "This message is displayed at the top of a category page showing the number of pages in the category.\n\nParameters:\n* $1 - number of subcategories shown\n* $2 - total number of subcategories in category",
     "category-subcat-count-limited": "This message is displayed at the top of a category page showing the number of pages in the category when not all pages in a category are counted.\n\nParameters:\n* $1 - number of subcategories shown",
     "category-article-count": "This message is used on category pages. Parameters:\n* $1 – number of pages shown\n* $2 – total number of pages in category",
     "category-file-count": "This message is displayed at the top of a category page showing the number of pages in the category.\n\nParameters:\n* $1 – number of files shown\n* $2 – total number of files in category",
     "category-file-count-limited": "This message is displayed at the top of a category page showing the number of pages in the category when not all pages in a category are counted.\n\nParameters:\n* $1 - number of files shown",
     "listingcontinuesabbrev": "Shown in contiuation of each first letter group. This message follows the first letter.\n\nSee http://test.wikipedia.org/wiki/Category:Test_ko?uselang={{SUBPAGENAME}}, for example.",
-    "index-category": "Name of the [[mw:Help:Tracking categories|tracking category]] where pages with the <nowiki>__INDEX__</nowiki> behavior switch are listed. For description of this behavior switch see [[mw:Help:Magic_words#Behavior_switches|MediaWiki]].",
-    "noindex-category": "Name of the [[mw:Help:Tracking categories|tracking category]] where pages with the <nowiki>__NOINDEX__</nowiki> behavior switch are listed. For description of this behavior switch see [[mw:Help:Magic_words#Behavior_switches|MediaWiki]].",
-    "broken-file-category": "Name of [[mw:Help:Tracking categories|tracking category]] where pages that embed files that do not exist (\"broken images\") are listed.",
+    "index-category": "Name of the [[mw:Special:MyLanguage/Help:Tracking categories|tracking category]] where pages with the <nowiki>__INDEX__</nowiki> behavior switch are listed.\n\nFor description of this behavior switch see [[mw:Special:MyLanguage/Help:Magic_words#Behavior_switches|MediaWiki]].\n\nSee also:\n* {{msg-mw|Index-category-desc}}",
+    "noindex-category": "Name of the [[mw:Special:MyLanguage/Help:Tracking categories|tracking category]] where pages with the <nowiki>__NOINDEX__</nowiki> behavior switch are listed.\n\nFor description of this behavior switch see [[mw:Special:MyLanguage/Help:Magic_words#Behavior_switches|MediaWiki]].\n\nSee also:\n* {{msg-mw|Noindex-category-desc}}",
+    "broken-file-category": "Name of [[mw:Special:MyLanguage/Help:Tracking categories|tracking category]] where pages that embed files that do not exist (\"broken images\") are listed.\n\nSee also:\n* {{msg-mw|Broken-file-category-desc}}",
     "categoryviewer-pagedlinks": "{{Optional}}\nThe pagination links in category viewer. Parameters:\n* $1 - the previous link, uses {{msg-mw|Prevn}}\n* $2 - the next link, uses {{msg-mw|Nextn}}",
     "about": "{{Identical|About}}",
     "article": "A '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}}",
     "permalink": "Display name for a permanent link to the current revision of a page. When the page is edited, permalink will still link to this revision. Example: Last menu link on [[{{MediaWiki:Mainpage}}]]\n\nSee also:\n* {{msg-mw|Permalink}}\n* {{msg-mw|Accesskey-t-permalink}}\n* {{msg-mw|Tooltip-t-permalink}}\n{{Identical|Permalink}}",
     "print": "{{Identical|Print}}",
     "view": "The default text of the \"View\" or \"Read\" (Vector) views tab which represents the basic view for the page. Should be in the infinitive mood.\n\n{{Identical|View}}",
+    "view-foreign": "The text on the tab that sends people to the \"master copy\" of the file at the foreign file\nrepository (e.g. Wikimedia Commons). Should be in the infinitive mood.\n\nParameters:\n* $1 - the name of the shared repository. On Wikimedia sites, $1 is {{msg-mw|Shared-repo-name-shared}}. On wikis using [[mw:InstantCommons|InstantCommons]], $1 is {{msg-mw|Shared-repo-name-wikimediacommons}}. The default value for $1 is {{msg-mw|Shared-repo}}.",
     "edit": "The text of the tab going to the edit form. When the page is protected, you will see {{msg-mw|Viewsource}}. Should be in the infinitive mood.\n\nSee also:\n* {{msg-mw|Edit}}\n* {{msg-mw|Accesskey-ca-edit}}\n* {{msg-mw|Tooltip-ca-edit}}\n{{Identical|Edit}}",
-    "create": "The text on the tab of the edit form on unexisting pages starts editing them.\n\n{{Identical|Create}}",
+    "edit-local": "The text on the tab going to the edit form for the local description page of a file from a foreign file repository (e.g. Wikimedia Commons). Should be in the infinitive mood.\n\nSee also:\n* {{msg-mw|Edit}}\n* {{msg-mw|Create-local}}",
+    "create": "The text on the tab of the edit form on unexisting pages starts editing them. Should be in the infinitive mood.\n\n{{Identical|Create}}",
+    "create-local": "The text on the tab going to the creation form for the (not yet existing) local description page of a file from a foreign file repository (e.g. Wikimedia Commons). Should be in the infinitive mood.\n\nSee also:\n* {{msg-mw|Create}}\n* {{msg-mw|Edit-local}}",
     "editthispage": "This is the \"edit\" link as used in the Cologne Blue skin, at the bottom of the page.\n\nSee {{msg-mw|Create-this-page}} for when the page does not exist.\n{{Identical|Edit this page}}",
     "create-this-page": "In the Cologne Blue skin this is the text for the link leading to the edit form on pages that have not yet been created, at the bottom of the page. See {{msg-mw|editthispage}} for when the page already exists.\n{{Identical|Createpage}}",
     "delete": "Name of the Delete tab shown for admins. Should be in the infinitive mood.\n\nSee also:\n* {{msg-mw|Delete}}\n* {{msg-mw|Accesskey-ca-delete}}\n* {{msg-mw|Tooltip-ca-delete}}\n{{Identical|Delete}}",
     "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}}.",
+    "helppage": "{{ignored}}\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).",
     "filenotfound": "Parameters:\n* $1 - file name",
     "fileexistserror": "Parameters:\n* $1 - file name",
     "unexpected": "This message indicates the value $2 is unexpected for $1. Parameters:\n* $1 - name\n* $2 - value",
+    "formerror": "Generic error message show to a user when they try to submit information that could not be processed for any reason.",
     "badarticleerror": "Used as error message in moving page.\n\nSee also:\n* {{msg-mw|Articleexists}}\n* {{msg-mw|Bad-target-model}}",
     "cannotdelete": "Error message in deleting. Parameters:\n* $1 - page name or file name",
     "cannotdelete-title": "Title of error page when the user cannot delete a page. Parameters:\n* $1 - the page name",
     "userloginnocreate": "Since 1.22 no longer used in core, but may still be used by some extensions. A variant of {{msg-mw|Userlogin}} when the user is not allowed to create a new account. DEPRECATED\n\n{{Identical|Log in}}",
     "logout": "Used as link text in your personal toolbox (upper right side).\n\nSee also:\n* {{msg-mw|Logout}}\n* {{msg-mw|Accesskey-pt-logout}}\n* {{msg-mw|Tooltip-pt-logout}}\n{{Identical|Log out}}",
     "userlogout": "{{doc-special|UserLogout|unlisted=1}}\n{{Identical|Log out}}",
+    "userlogout-summary": "{{ignored}}",
     "notloggedin": "This message is displayed in the standard skin when not logged in. The message is placed above the login link in the top right corner of pages.\n\n{{Identical|Not logged in}}",
     "userlogin-noaccount": "In the [[Special:Userlogin]] form, this is the text prior to button inviting user to join project.\n{{Identical|Do not have an account}}",
     "userlogin-joinproject": "Text of button inviting user to create an account.\n\nSee example: [[Special:UserLogin]]",
     "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.",
     "changepassword": "Section heading on [[Special:Preferences]], tab 'User profile'.\n{{Identical|Change password}}",
+    "changepassword-summary": "{{ignored}}",
     "resetpass_announce": "Used in [[Special:UserLogin]].",
     "resetpass_text": "{{optional}}",
     "resetpass_header": "Header on box on special page [[Special:ChangePassword]].\n\n{{Identical|Reset password}}",
     "passwordreset-emailsent-capture": "Used in [[Special:PasswordReset]].\n\nSee also:\n* {{msg-mw|Passwordreset-emailsent}}\n* {{msg-mw|Passwordreset-emailerror-capture}}",
     "passwordreset-emailerror-capture": "Error message displayed in [[Special:PasswordReset]] when sending an email fails. Parameters:\n* $1 - error message\n* $2 - username, used for GENDER\nSee also:\n* {{msg-mw|Passwordreset-emailsent}}\n* {{msg-mw|Passwordreset-emailsent-capture}}",
     "changeemail": "Title of [[Special:ChangeEmail|special page]].",
+    "changeemail-summary": "{{ignored}}",
     "changeemail-header": "Header on [[Special:ChangeEmail]].",
     "changeemail-text": "Text of [[Special:ChangeEmail]].",
     "changeemail-no-info": "Error message for [[Special:ChangeEmail]].\n\nParameters:\n* $1 (unused) - a link to [[Special:UserLogin]] with {{msg-mw|loginreqlink}} as link description",
     "changeemail-cancel": "Cancel button on [[Special:ChangeEmail]]\n\n{{Identical|Cancel}}",
     "changeemail-throttled": "Error message shown at [[Special:ChangeEmail]] 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\nSee also:\n* {{msg-mw|Changepassword-throttled}}",
     "resettokens": "{{doc-special|ResetTokens}}\nIn this case \"token\" may be translated as \"key\", or similar.\n{{Identical|Reset token}}",
+    "resettokens-summary": "{{ignored}}",
     "resettokens-text": "Text on [[Special:ResetTokens]].",
     "resettokens-no-tokens": "Additional text on [[Special:ResetTokens]] if the user has no tokens.",
     "resettokens-legend": "Form legend on [[Special:ResetTokens]].\n{{Identical|Reset token}}",
     "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-head-copy-warn": "{{ignored}}Custom copyright warning in the header of an edit page.",
     "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)",
     "content-model-javascript": "Name for the JavaScript content model, used when decribing what type of content a page contains.\n\nThis message is substituted in:\n*{{msg-mw|Bad-target-model}}\n*{{msg-mw|Content-not-allowed-here}}",
     "content-model-css": "Name for the CSS content model, used when decribing what type of content a page contains.\n\nThis message is substituted in:\n*{{msg-mw|Bad-target-model}}\n*{{msg-mw|Content-not-allowed-here}}",
     "expensive-parserfunction-warning": "On some (expensive) [[MetaWikipedia:Help:ParserFunctions|parser functions]] (e.g. <code><nowiki>{{#ifexist:}}</nowiki></code>) there is a limit of how many times it may be used. This is an error message shown when the limit is exceeded.\n\nParameters:\n* $1 - the current number of parser function calls\n* $2 - the allowed number of parser function calls\nSee also [[:mw:Manual:$wgExpensiveParserFunctionLimit|$wgExpensiveParserFunctionLimit in the MediaWiki manual]].\n\nSee also:\n* {{msg-mw|Expensive-parserfunction-category}}",
-    "expensive-parserfunction-category": "This message is used as a category name for a [[mw:Help:Tracking categories|tracking category]] where pages are placed automatically if they contain too many calls to expensive parser functions.\n\nSee also:\n* {{msg-mw|Expensive-parserfunction-warning}}",
+    "expensive-parserfunction-category": "This message is used as a category name for a [[mw:Special:MyLanguage/Help:Tracking categories|tracking category]] where pages are placed automatically if they contain too many calls to expensive parser functions.\n\nSee also:\n* {{msg-mw|Expensive-parserfunction-category-desc}}\n* {{msg-mw|Expensive-parserfunction-warning}}",
     "post-expand-template-inclusion-warning": "When templates are expanded, there is a size limit for the number of bytes yielded. Usually that occurs from excessively nested templates, recursive templates, or ones having x-zillion of #if #case or similar contructs in them. When the wikicode parser detects this, it outputs a red warning message to the page.\n\n\nSee also:\n* {{msg-mw|Post-expand-template-inclusion-category}}",
-    "post-expand-template-inclusion-category": "This message is used as a category name for a [[mw:Help:Tracking categories|tracking category]] where pages are placed automatically if the expanded size of the templates they contain exceeds the limit.\nWhen templates are expanded, there is a size limit for the number of bytes yielded. Usually that occurs from excessively nested templates, recursive templates, or ones having x-zillion of #if #case or similar contructs in them. When the wikicode parser detects this, it outputs a red warning message to the page.\n\nSee also:\n* {{msg-mw|Post-expand-template-inclusion-warning}}",
+    "post-expand-template-inclusion-category": "This message is used as a category name for a [[mw:Special:MyLanguage/Help:Tracking categories|tracking category]] where pages are placed automatically if the expanded size of the templates they contain exceeds the limit.\n\nWhen templates are expanded, there is a size limit for the number of bytes yielded. Usually that occurs from excessively nested templates, recursive templates, or ones having x-zillion of #if #case or similar contructs in them. When the wikicode parser detects this, it outputs a red warning message to the page.\n\nSee also:\n* {{msg-mw|Post-expand-template-inclusion-category-desc}}\n* {{msg-mw|Post-expand-template-inclusion-warning}}",
     "post-expand-template-argument-warning": "Used as warning in parser limitation.\n\nSee also:\n* {{msg-mw|Post-expand-template-argument-category}}",
-    "post-expand-template-argument-category": "This message is used as a category name for a [[mw:Help:Tracking categories|tracking category]] where pages are placed automatically if they contain omitted template arguments.\n\nSee also:\n* {{msg-mw|Post-expand-template-argument-warning}}",
+    "post-expand-template-argument-category": "This message is used as a category name for a [[mw:Special:MyLanguage/Help:Tracking categories|tracking category]] where pages are placed automatically if they contain omitted template arguments.\n\nSee also:\n* {{msg-mw|Post-expand-template-argument-category-desc}}\n* {{msg-mw|Post-expand-template-argument-warning}}",
     "parser-template-loop-warning": "Parameters:\n* $1 - page title",
     "parser-template-recursion-depth-warning": "Parameters:\n* $1 - limit value of recursion depth",
     "language-converter-depth-warning": "Error message shown when a page uses too deeply nested language conversion syntax. Parameters:\n* $1 - the value of the depth limit",
     "diff-multi-otherusers": "This message appears in the revision history of a page when comparing two versions which aren't consecutive, and at least one of the intermediate revisions was created by a user other than the user who created the new revision.\n\nParameters:\n* $1 - the number of revisions\n* $2 - the number of distinct other users who made those revisions\n{{Related|Diff-multi}}",
     "diff-multi-manyusers": "This message appears in the revision history of a page when comparing two versions which aren't consecutive, and the intermediate revisions have been edited by more than 100 users.\n\nParameters:\n* $1 - the number of revisions, will always be 101 or more\n* $2 - the number of users that were found, which was limited at 100\n{{Related|Diff-multi}}",
     "difference-missing-revision": "Text displayed when the requested revision does not exist using a diff link.\n\nExample: [{{canonicalurl:Project:News|diff=426850&oldid=99999999}} Diff with invalid revision#]\n\nParameters:\n* $1 - the list of missing revisions IDs\n* $2 - the number of items in $1 (one or two)",
+    "search-summary": "{{doc-specialpagesummary|search}}",
     "searchresults": "This is the title of the page that contains the results of a search.\n\n{{Identical|Search results}}",
     "searchresults-title": "Appears as page title in the html header of the search result special page.\n\nParameters:\n* $1 - the search term",
     "toomanymatches": "Used as section header in [[Special:Search]], when there are too many hits.",
     "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",
+    "opensearch-desc": "{{ignored}}Link description of the [www.opensearch.org/ OpenSearch] link in the HTML head of pages.",
     "preferences": "Title of the [[Special:Preferences]] page.\n{{Identical|Preferences}}",
+    "preferences-summary": "{{doc-specialpagesummary|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-edits": "In user preferences.",
     "prefsnologintext2": "Parameters:\n* $1 - a link to [[Special:UserLogin]] with {{msg-mw|loginreqlink}} as link description",
     "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",
     "email-address-validity-valid": "Used as hint for {{msg-mw|changeemail-newemail}} field in [[Special:ChangeEmail]], when the provided E-mail address is valid.",
     "email-address-validity-invalid": "Used as warning for {{msg-mw|changeemail-newemail}} field in [[Special:ChangeEmail]], when the provided E-mail address is invalid.",
     "userrights": "Page title of [[Special:UserRights]].",
+    "userrights-summary": "{{doc-specialpagesummary|userrights}}",
     "userrights-lookup-user": "Label text when managing user rights ([[Special:UserRights]])",
     "userrights-user-editname": "Displayed on [[Special:UserRights]].",
     "editusergroup": "Button name, in page [[Special:Userrights]] (only available to administrators), in the section named {{MediaWiki:userrights-lookup-user}}.\n\n{{Identical|Edit user groups}}",
     "upload_directory_missing": "Parameters:\n* $1 - directory name",
     "upload_directory_read_only": "Parameters:\n* $1 - directory name",
     "uploaderror": "Used as section header in [[Special:Upload]].\n\nSee also:\n* {{msg-mw|upload-tryagain|Submit text}}",
+    "upload-summary": "{{doc-specialpagesummary|upload}}",
     "upload-recreate-warning": "Used as warning in [[Special:Upload]].",
     "uploadtext": "{{doc-important|<code>thumb</code> and <code>left</code> are magic words. Leave them untranslated!}}\nText displayed when uploading a file using [[Special:Upload]].",
     "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}}",
+    "upload-default-description": "{{ignored}}Custom default upload description. The contents of this message be will inserted in the field \"Summary\" on [[Special:Upload]].",
     "uploadlogpage": "{{doc-logpage}}\n\nPage title of [[Special:Log/upload]].",
     "uploadlogpagetext": "Appears on top of [[Special:Log/upload]].",
     "filename": "{{Identical|Filename}}",
     "upload-file-error-text": "See also:\n* {{msg-mw|Upload-file-error|title}}\n* {{msg-mw|Upload-file-error-text|text}}",
     "upload-misc-error": "See also:\n* {{msg-mw|Upload-misc-error|title}}\n* {{msg-mw|Upload-misc-error-text|text}}",
     "upload-misc-error-text": "See also:\n* {{msg-mw|Upload-misc-error|title}}\n* {{msg-mw|Upload-misc-error-text|text}}",
+    "upload-too-many-redirects": "Error message shown when uploading a file via URL, if the upload failed because the URL returned too many redirects.",
     "upload-http-error": "Parameters:\n* $1 - error message",
     "upload-copy-upload-invalid-domain": "Error message shown if a user is trying to upload (i.e. copy) a file from a website that is not in $wgCopyUploadsDomains (if set).\n\nSee also:\n* {{msg-mw|http-invalid-url}}\n* {{msg-mw|tmp-create-error}}\n* {{msg-mw|tmp-write-error}}",
     "backend-fail-stream": "Parameters:\n* $1 - a filename",
     "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.",
     "shared-repo-from": "This message is shown on an image description page when a duplicate of the image exists on a shared repository such as Wikimedia Commons.\n\nExample: http://test.wikipedia.org/wiki/File:Wiki.png#filelinks\n\nParameters:\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}}.",
-    "shared-repo": "This message can be used as parameter <code>$1</code> in the following messages:\n* {{msg-mw|shared-repo-from}}\n* {{msg-mw|sharedupload}}\n* {{msg-mw|sharedupload-desc-here}}\n* {{msg-mw|sharedupload-desc-there}}",
-    "shared-repo-name-wikimediacommons": "{{optional}}\n{{Identical|Wikimedia Commons}}",
+    "shared-repo": "This message can be used as parameter <code>$1</code> in the following messages:\n* {{msg-mw|view-foreign}}\n* {{msg-mw|shared-repo-from}}\n* {{msg-mw|sharedupload}}\n* {{msg-mw|sharedupload-desc-here}}\n* {{msg-mw|sharedupload-desc-there}}",
+    "shared-repo-name-wikimediacommons": "{{optional}}\n\nA specific version of {{msg-mw|shared-repo}}; see [[MediaWiki:Shared-repo/qqq]] for more information.\n\n{{Identical|Wikimedia Commons}}",
     "filepage.css": "{{Optional}}",
     "upload-disallowed-here": "This message appears on an image page in place of the normal reupload link if they cannot upload - e.g. if the image page is upload protected and they do not have the right privilege.",
     "filerevert": "Used as page title. Parameters:\n* $1 - page title\n{{Identical|Revert}}",
     "mimetype": "Used as label for input box in the MIMESearch form on [[Special:MIMESearch]].\n\nSee also:\n* {{msg-mw|Mimesearch|page title}}\n* {{msg-mw|Ilsubmit|Submit button text}}\n{{Identical|MIME type}}",
     "download": "Direct download link in each line returned by [[Special:MIMESearch]]. Points to the actual file, rather than the image description page.\n{{Identical|Download}}",
     "unwatchedpages": "{{doc-special|UnwatchedPages}}",
+    "unwatchedpages-summary": "{{doc-specialpagesummary|unwatchedpages}}",
     "listredirects": "{{doc-special|ListRedirects}}",
+    "listredirects-summary": "{{doc-specialpagesummary|listredirects}}",
     "listduplicatedfiles": "{{doc-special|ListDuplicatedFiles}}",
     "listduplicatedfiles-summary": "Summary at top of Special:ListDuplicatedFiles",
     "listduplicatedfiles-entry": "A list item on [[Special:ListDuplicatedFiles]]. Parameters:\n* $1 - the file name (no namespace prefix)\n* $2 - the number of duplicates this file has\n* $3 - the name of the duplicate search page (aka \"Special:FileDuplicateSearch/Foo.png\" or \"Spécial:Recherche_fichier_en_double/Firefox.png\")",
     "unusedtemplates": "{{doc-special|UnusedTemplates}}",
+    "unusedtemplates-summary": "{{doc-specialpagesummary|unusedtemplates}}",
     "unusedtemplatestext": "Shown on top of [[Special:Unusedtemplates]]",
     "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}}",
     "randomredirect": "{{doc-special|RandomRedirect}}",
     "randomredirect-nopages": "Parameters:\n* $1 - list of namespaces\n* $2 - (Unused) number of namespaces\nSee also:\n* {{msg-mw|Randompage-nopages}}",
     "statistics": "{{doc-special|Statistics}}\n{{Identical|Statistics}}",
+    "statistics-summary": "{{doc-specialpagesummary|statistics}}",
     "statistics-header-pages": "Used in [[Special:Statistics]]",
     "statistics-header-edits": "Used in [[Special:Statistics]]",
     "statistics-header-views": "Used in [[Special:Statistics]]",
     "statistics-mostpopular": "Used in [[Special:Statistics]]",
     "statistics-footer": "{{notranslate}}",
     "pageswithprop": "{{doc-special|PagesWithProp}}\n{{Identical|Page with page property}}",
+    "pageswithprop-summary": "{{doc-specialpagesummary|pageswithprop}}",
     "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]]",
     "pageswithprop-prop": "Label for the property name input field on [[Special:PagesWithProp]].\n{{Identical|Property name}}",
     "pageswithprop-prophidden-long": "Information shown on [[Special:PagesWithProp]] when property value is longer than 1 kilobyte.\n\nParameters:\n* $1 - size of property value in kilobytes\nSee also:\n* {{msg-mw|pageswithprop-prophidden-binary}}",
     "pageswithprop-prophidden-binary": "Information shown on [[Special:PagesWithProp]] when property value contains binary data.\n\nParameters:\n* $1 - size of property value in kilobytes\nSee also:\n* {{msg-mw|pageswithprop-prophidden-long}}",
     "doubleredirects": "{{doc-special|DoubleRedirects}}",
+    "doubleredirects-summary": "{{doc-specialpagesummary|doubleredirects}}",
     "doubleredirectstext": "Shown on top of [[Special:Doubleredirects]]",
     "double-redirect-fixed-move": "This is the message in the log when the software (under the username {{msg-mw|Double-redirect-fixer}}) updates the redirects after a page move.\n\nParameters:\n* $1 - redirect page title\n* $2 - new page title\nSee also:\n* {{msg-mw|Fix-double-redirects}}\n* {{msg-mw|Double-redirect-fixed-maintenance}}",
     "double-redirect-fixed-maintenance": "This is the message in the log when the software (under the username {{msg-mw|Double-redirect-fixer}}) updates the redirects after running maintenance/fixDoubleRedirects.php.\n\nParameters:\n* $1 - redirect page title\n* $2 - new page title\nSee also:\n* {{msg-mw|Double-redirect-fixed-move}}",
     "double-redirect-fixer": "This is the '''username''' of the user who updates the double redirects after a page move.\n\nA user is created with this username, so it is perhaps better to not change this message too often.\n\nSee also:\n* {{msg-mw|Double-redirect-fixed-move}}\n* {{msg-mw|Fix-double-redirects}}",
     "brokenredirects": "{{doc-special|BrokenRedirects}}",
+    "brokenredirects-summary": "{{doc-specialpagesummary|brokenredirects}}",
     "brokenredirectstext": "Shown on top of [[Special:BrokenRedirects]].",
     "brokenredirects-edit": "Link in [[Special:BrokenRedirects]]\n\n{{Identical|Edit}}",
     "brokenredirects-delete": "Link in [[Special:BrokenRedirects]] for admins\n\n{{Identical|Delete}}",
     "withoutinterwiki-legend": "Used on [[Special:WithoutInterwiki]] as title of fieldset.",
     "withoutinterwiki-submit": "{{Identical|Show}}",
     "fewestrevisions": "{{doc-special|FewestRevisions}}",
+    "fewestrevisions-summary": "{{doc-specialpagesummary|fewestrevisions}}",
     "nbytes": "Message used on the history page of a wiki page. Each version of a page consist of a number of bytes. $1 is the number of bytes that the page uses. Uses plural as configured for a language based on $1.",
     "ncategories": "Used in the special page '[[Special:MostCategories]]' in brackets after each entry on the list signifying how many categories a page is part of. $1 is the number of categories.",
     "ninterwikis": "Used in the special page '[[Special:MostInterwikis]]' in brackets after each entry on the list signifying how many interwikis a page is part of.\n\nParameters:\n* $1 - the number of interwiki links",
     "ntransclusions": "Used on [[Special:MostLinkedTemplates]] to indicate how often a template is in use.\n\nParameters:\n* $1 - number of pages\nSee also:\n* {{msg-mw|Nimagelinks}}",
     "specialpage-empty": "Used on a special page when there is no data. For example on [[Special:Unusedimages]] when all images are used.",
     "lonelypages": "{{doc-special|LonelyPages}}",
+    "lonelypages-summary": "{{doc-specialpagesummary|lonelypages}}",
     "lonelypagestext": "Text displayed in [[Special:LonelyPages]]",
     "uncategorizedpages": "{{doc-special|UncategorizedPages}}",
+    "uncategorizedpages-summary": "{{doc-specialpagesummary|uncategorizedpages}}",
     "uncategorizedcategories": "{{doc-special|UncategorizedCategories}}",
+    "uncategorizedcategories-summary": "{{doc-specialpagesummary|uncategorizedcategories}}",
     "uncategorizedimages": "{{doc-special|UncategorizedImages}}",
     "uncategorizedimages-summary": "{{notranslate}}\nused in [[Special:Uncategorizedimages]]. [[mw:Manual:Interface/Special pages summary|mw manual]].",
     "uncategorizedtemplates": "{{doc-special|UncategorizedTemplates}}",
+    "uncategorizedtemplates-summary": "{{doc-specialpagesummary|uncategorizedtemplates}}",
     "unusedcategories": "{{doc-special|UnusedCategories}}",
+    "unusedcategories-summary": "{{doc-specialpagesummary|unusedcategories}}",
     "unusedimages": "{{doc-special|UnusedImages}}",
+    "unusedimages-summary": "{{doc-specialpagesummary|unusedimages}}",
     "popularpages": "{{doc-special|PopularPages}}",
+    "popularpages-summary": "{{doc-specialpagesummary|popularpages}}",
     "wantedcategories": "{{doc-special|WantedCategories}}",
+    "wantedcategories-summary": "{{doc-specialpagesummary|wantedcategories}}",
     "wantedpages": "{{doc-special|WantedPages}}",
+    "wantedpages-summary": "{{doc-specialpagesummary|wantedpages}}",
     "wantedpages-badtitle": "Error message shown when [[Special:WantedPages]] is listing a page with a title that shouldn't exist.\n\nParameters:\n* $1 - a page title",
     "wantedfiles": "{{doc-special|WantedFiles}}",
+    "wantedfiles-summary": "{{doc-specialpagesummary|wantedfiles}}",
     "wantedfiletext-cat": "Message displayed at top of [[special:WantedFiles]]. $1 contains the name of the tracking category for broken files (Including Category prefix). {{msg-mw|wantedfiletext-nocat}} is used if the tracking category is disabled.",
     "wantedfiletext-nocat": "Message displayed at top of [[special:WantedFiles]] when broken file tracking category is disabled. See {{msg-mw|wantedfiletext-cat}}.",
     "wantedtemplates": "{{doc-special|WantedTemplates}}",
+    "wantedtemplates-summary": "{{doc-specialpagesummary|wantedtemplates}}",
     "mostlinked": "{{doc-special|MostLinked}}",
+    "mostlinked-summary": "{{doc-specialpagesummary|mostlinked}}",
     "mostlinkedcategories": "{{doc-special|MostLinkedCategories}}",
+    "mostlinkedcategories-summary": "{{doc-specialpagesummary|mostlinkedcategories}}",
     "mostlinkedtemplates": "{{doc-special|MostLinkedTemplates}}",
+    "mostlinkedtemplates-summary": "{{doc-specialpagesummary|mostlinkedtemplates}}",
     "mostcategories": "{{doc-special|MostCategories}}",
+    "mostcategories-summary": "{{doc-specialpagesummary|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}}",
+    "mostinterwikis-summary": "{{doc-specialpagesummary|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.",
     "protectedpages-reason": "This is a column header in the table on the page [[Special:ProtectedPages]].\n{{Identical|Reason}}",
     "protectedpages-unknown-timestamp": "This is shown, when the date and time is unknown for a protection on the page [[Special:ProtectedPages]].\n{{Identical|Unknown}}",
     "protectedpages-unknown-performer": "This is shown, when the protecting user is unknown for a protection on the page [[Special:ProtectedPages]].",
+    "protectedpages-unknown-reason": "{{ignored}}Comment used for extremely old protection log events (before there was a reason field).",
     "protectedtitles": "{{doc-special|ProtectedTitles}}",
     "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.",
     "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]].",
+    "ancientpages-summary": "{{doc-specialpagesummary|ancientpages}}",
     "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}}",
     "movethispage": "{{Identical|Move this page}}",
     "unusedimagestext": "Header message of [[Special:UnusedFiles]]",
     "suppress": "{{Identical|Oversight}}",
     "querypage-disabled": "On special pages that use expensive database queries but are not cacheable, this message is displayed when 'miser mode' is on (i.e. no expensive queries allowed).",
     "booksources": "{{doc-special|BookSources}}\n\n'''This message shouldn't be changed unless it has serious mistakes.'''\n\nIt's used as the page name of the configuration page of [[Special:BookSources]]. Changing it breaks existing sites using the default version of this message.\n\nSee also:\n* {{msg-mw|Booksources|title}}\n* {{msg-mw|Booksources-text|text}}",
+    "booksources-summary": "{{doc-specialpagesummary|booksources}}",
     "booksources-search-legend": "Box heading on [[Special:BookSources|book sources]] special page. The box is for searching for places where a particular book can be bought or viewed.",
     "booksources-isbn": "{{optional}}\nThis is a label that appears before a text input field on the Special:BookSources page.\n{{Identical|ISBN}}",
     "booksources-go": "Name of button in [[Special:BookSources]]\n\n{{Identical|Go}}",
     "log-title-wildcard": "* Appears in: [[Special:Log]]\n* Description: A check box to enable prefix search option",
     "showhideselectedlogentries": "Text of the button which brings up the [[mw:RevisionDelete|RevisionDelete]] menu on [[Special:Log]].",
     "allpages": "{{doc-special|AllPages}}\nFirst part of the navigation bar for the special page [[Special:AllPages]] and [[Special:PrefixIndex]].\nThe other parts are {{msg-mw|Prevpage}} and {{msg-mw|Nextpage}}.\n{{Identical|All pages}}",
+    "allpages-summary": "{{doc-specialpagesummary|allpages}}",
     "alphaindexline": "Used on [[Special:AllPages]] if the main namespace contains more than 960 pages. Indicates the page range displayed behind the link. \"from page $1 to page $2\". $1 is the source page name. $1 is the target page name.",
     "nextpage": "Third part of the navigation bar for the special page [[Special:AllPages]] and [[Special:PrefixIndex]]. $1 is a page title. The other parts are {{msg-mw|Allpages}} and {{msg-mw|Prevpage}}.\n\n{{Identical|Next page}}",
     "prevpage": "Second part of the navigation bar for the special page [[Special:AllPages]] and [[Special:PrefixIndex]]. $1 is a page title. The other parts are {{msg-mw|Allpages}} and {{msg-mw|Nextpage}}.\n\n{{Identical|Previous page}}",
     "cachedspecial-viewing-cached-ts": "Message notifying they are watching a cached page. This is a message displayed on special pages (contaning lists of pages with certain properties) that are served from the cache, as opposed to having been compiled run-time. This means that the displayed data may differ from the current situation.",
     "cachedspecial-refresh-now": "Link text pointing to the most recent version of the page.",
     "categories": "The page name of [[Special:Categories]].\n{{Identical|Category}}",
+    "categories-summary": "{{doc-specialpagesummary|categories}}",
     "categoriespagetext": "{{doc-important|Do not translate or change links.}}\nText displayed in [[Special:Categories]].\n\nIn order to translate \"Unused categories\" and \"wanted categories\" see {{msg-mw|Unusedcategories}} and {{msg-mw|Wantedcategories}}.\n\nParameters:\n* $1 - number of categories",
     "categoriesfrom": "Used as label for the input box in [[Special:Categories]].\n\nThis message follows the fieldset label {{msg-mw|categories}}, and is followed by the input box.",
     "special-categories-sort-count": "Commented out at this time.\n\nThis message is used on [[Special:Categories]] to sort the list by the number of members in the categories.\n\nSee also:\n* {{msg-mw|Special-categories-sort-abc}}",
     "special-categories-sort-abc": "Commented out at this time.\n\nThis message is used on [[Special:Categories]] to sort the list by the category name.\n\nSee also:\n* {{msg-mw|Special-categories-sort-count}}",
     "deletedcontributions": "The message is shown as a link on [[Special:SpecialPages]] to [[Special:DeletedContributions]].\n\n{{Identical|Deleted user contributions}}",
+    "deletedcontributions-summary": "{{doc-specialpagesummary|deletedcontributions}}",
     "deletedcontributions-title": "Title of [[Special:DeletedContributions]] (extension), a special page with a list of edits to pages which were deleted. Only viewable by sysops.\n\n{{Identical|Deleted user contributions}}",
     "sp-deletedcontributions-contribs": "Link to user's contributions on [[Special:DeletedContributions]].\n{{Identical|Contribution}}",
     "linksearch": "Title of [[Special:LinkSearch|special page]] and legend of fieldset on that page.\n\n{{Identical|External link}}",
+    "linksearch-summary": "{{doc-specialpagesummary|linksearch}}",
     "linksearch-pat": "Legend for input box on [[Special:LinkSearch]].",
     "linksearch-ns": "Legend for dropdown box on [[Special:LinkSearch|special page]].\n\n{{Identical|Namespace}}",
     "linksearch-ok": "Button label on [[Special:LinkSearch|special page]]e\n\n{{Identical|Search}}",
     "listusers-noresult": "identical with {{msg-mw|activeusers-noresult}}",
     "listusers-blocked": "Used on [[Special:ActiveUsers]] when a user has been blocked. Parameters:\n* $1 - (Optional) a user name for use with GENDER\n{{Identical|Blocked}}",
     "activeusers": "Title of [[Special:ActiveUsers]]",
+    "activeusers-summary": "{{doc-specialpagesummary|activeusers}}",
     "activeusers-intro": "Used as introduction in [[Special:ActiveUsers]]. Parameters:\n* $1 - number of days (<code>$wgActiveUserDays</code>)",
     "activeusers-count": "Used in [[Special:ActiveUsers]] to show the active user's recent action count in brackets ([]).\n* $1 is the number of recent actions\n* $2 is the user's name for use with GENDER (optional)\n* $3 is the maximum number of days of the RecentChangesList",
     "activeusers-from": "Used as label for checkbox in the form on [[Special:ActiveUsers]].\n\nidentical with {{msg-mw|listusersfrom}}\n\nSee also:\n* {{msg-mw|activeusers|legend for the form}}\n* {{msg-mw|activeusers-hidebots|label for checkbox}}\n* {{msg-mw|activeusers-hidesysops|label for checkbox}}",
     "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}}",
+    "listgrouprights-namespaceprotection-header": "Shown on [[Special:ListGroupRights]] as the header for the namespace restrictions table.",
+    "listgrouprights-namespaceprotection-namespace": "Shown on [[Special:ListGroupRights]] as the 'namespace' column header for the namespace restrictions table.",
+    "listgrouprights-namespaceprotection-restrictedto": "Shown on [[Special:ListGroupRights]] as the 'right(s) allowing user to edit' column header for the namespace restrictions table.",
     "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]]",
+    "noindex-category-desc": "No-index category-description. Shown on [[Special:TrackingCategories]].\n\nSee also:\n* {{msg-mw|Noindex-category}}",
+    "index-category-desc": "Index category-description. Shown on [[Special:TrackingCategories]].\n\nSee also:\n* {{msg-mw|Index-category}}",
+    "post-expand-template-inclusion-category-desc": "Post expand template inclusion category description. Shown on [[Special:TrackingCategories]].\n\nSee also:\n* {{msg-mw|Post-expand-template-inclusion-category}}",
+    "post-expand-template-argument-category-desc": "Post expand template argument category description. Shown on [[Special:TrackingCategories]].\n\nSee also:\n* {{msg-mw|Post-expand-template-argument-category}}",
+    "expensive-parserfunction-category-desc": "Expensive parserfunction category description. Shown on [[Special:TrackingCategories]].\n\nSee also:\n* {{msg-mw|Expensive-parserfunction-category}}",
+    "broken-file-category-desc": "Broken file category description. Shown on [[Special:TrackingCategories]].\n\nSee also:\n* {{msg-mw|Broken-file-category}}",
+    "hidden-category-category-desc": "Hidden-category category description. Shown on [[Special:TrackingCategories]].\n\nSee also:\n* {{msg-mw|Hidden-category-category}}",
     "trackingcategories-nodesc": "Tracking category description not available message",
+    "trackingcategories-disabled": "This message is used as the contents of the column \"Tracking category\" on [[Special:TrackingCategories]] when a particular tracking category has been disabled.",
     "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}}",
     "emailuser-title-target": "{{doc-special|EmailUser|unlisted=1}}\nUsed when a user was given to e-mail. Parameters:\n* $1 - a plain text username, used for GENDER.",
     "emailuser-title-notarget": "{{doc-special|EmailUser|unlisted=1}}\nUsed when no user given to e-mail yet.",
+    "emailuser-summary": "{{doc-specialpagesummary|emailuser}}",
     "emailpage": "Title of special page [[Special:EmailUser]], when it is the destination of the sidebar link {{msg-mw|Emailuser}} on a user's page.",
     "emailpagetext": "This is the text that is displayed above the email form on [[Special:EmailUser]].\n\nSpecial:EmailUser appears when you click on the link \"Email this user\" in the sidebar, but only if there is an email address in the recipient's user preferences. If there isn't then the message {{msg-mw|Noemailtext}} will appear instead of Special:EmailUser.\n\nParameters:\n* $1 - username",
     "defemailsubject": "The default subject of EmailUser emails. Parameters:\n* $1 - the username of the user sending the email and can be used for GENDER",
     "usermessage-editor": "The user name for the user that is the editor of system messages. See [{{canonicalurl:Thread:Support/Message_info_please}} discussion on Support].",
     "usermessage-template": "{{optional}}",
     "watchlist": "{{Identical|Watchlist}}",
+    "watchlist-summary": "{{doc-specialpagesummary|watchlist}}",
     "mywatchlist": "Link at the upper right corner of the screen.\n\nSee also:\n* {{msg-mw|Mywatchlist}}\n* {{msg-mw|Accesskey-pt-watchlist}}\n* {{msg-mw|Tooltip-pt-watchlist}}\n{{Identical|Watchlist}}",
     "watchlistfor2": "Subtitle on [[Special:Watchlist]].\nParameters:\n* $1 - Username of current user\n* $2 - Tool links (View relevant changes | View and edit watchlist | Edit raw watchlist)\n{{Identical|For $1}}",
     "nowatchlist": "Displayed when there is no pages in the watchlist.",
     "restriction-level-autoconfirmed": "Used on [[Special:ProtectedPages]] and [[Special:ProtectedTitles]]. An option in the drop-down box 'Restriction level', and in brackets after each page name entry. See the [[mw:Project:Protected_titles|help page on MediaWiki]] and on [[meta:Protect|Meta]] for more information.\n\nSee also:\n*{{msg-mw|Restriction-level-sysop}}\n*{{msg-mw|Restriction-level-all}}",
     "restriction-level-all": "Used on [[Special:ProtectedPages]] and [[Special:ProtectedTitles]]. An option in the drop-down box 'Restriction level'. See the [[mw:Project:Protected_titles|help page on MediaWiki]] and on [[meta:Protect|Meta]] for more information.\n\nSee also:\n*{{msg-mw|Restriction-level-sysop}}\n*{{msg-mw|Restriction-level-autoconfirmed}}",
     "undelete": "{{doc-special|Undelete}}\nSee also:\n* {{msg-mw|Undelete}}\n* {{msg-mw|Accesskey-ca-undelete}}\n* {{msg-mw|Tooltip-ca-undelete}}\n{{Identical|View deleted pages}}",
+    "undelete-summary": "{{doc-specialpagesummary|undelete}}",
     "undeletepage": "Title of special page [[Special:Undelete]]. This special page is only visible to administrators.",
     "undeletepagetitle": "Used as introduction in [[Special:Undelete]]. Parameters:\n* $1 - page title",
     "viewdeletedpage": "Title of the [[Special:Undelete]].\n\n{{Identical|View deleted pages}}",
     "tooltip-namespace_association": "Used in [[Special:Recentchanges]] as a tooltip for the associated namespace checkbox.\n\nSee also:\n* {{msg-mw|Namespace association}}",
     "blanknamespace": "Name for main namespace (blank namespace) in drop-down menus at [[Special:RecentChanges]] and other special pages.\n{{Identical|Main}}",
     "contributions": "Display name for the 'User contributions', shown in the sidebar menu of all user pages and user talk pages.\n\nAlso the page name of the target page.\n\nThe target page shows an overview of the most recent contributions by a user.\n\nParameters:\n* $1 - username\n\nSee also:\n* {{msg-mw|Contributions}}\n* {{msg-mw|Accesskey-t-contributions}}\n* {{msg-mw|Tooltip-t-contributions}}",
+    "contributions-summary": "{{doc-specialpagesummary|contributions}}",
     "contributions-title": "{{Gender}}\nThe page title in your browser bar, but not the page title.\n\nParameters:\n* $1 - the username\nSee also:\n* {{msg-mw|Contributions}}",
     "mycontris": "In the personal urls page section - right upper corner.\n\nSee also:\n* {{msg-mw|Mycontris}}\n* {{msg-mw|Accesskey-pt-mycontris}}\n* {{msg-mw|Tooltip-pt-mycontris}}\n{{Identical|Contribution}}",
     "contribsub2": "Contributions for \"user\" (links). Parameters:\n* $1 is an IP address or a username, with a link which points to the user page (if registered user).\n* $2 is list of tool links. The list contains a link which has text {{msg-mw|Sp-contributions-talk}}.\n* $3 is a plain text username used for GENDER.\n{{Identical|For $1}}",
     "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}}",
+    "sp-contributions-footer": "{{ignored}}This is the footer for users that are not anonymous or newbie on [[Special:Contributions]].",
+    "sp-contributions-footer-anon": "{{ignored}}This is the footer for anonymous users on [[Special:Contributions]].",
+    "sp-contributions-footer-newbies": "{{ignored}}This is the footer for newbie users on [[Special:Contributions]].",
     "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-summary": "{{doc-specialpagesummary|whatlinkshere}}",
     "whatlinkshere-page": "{{Identical|Page}}",
     "linkshere": "This message is the header line of the [[Special:WhatLinksHere/$1]] page generated by clicking \"What links here\" in the sidebar toolbox.\n\nIt is followed by a navigation bar built using {{msg-mw|Viewprevnext}}.\n\nParameters:\n* $1 - page title",
     "nolinkshere": "Used in [[Special:WhatLinksHere]] if empty. Parameters:\n* $1 - page title\nSee also:\n* {{msg-mw|Nolinkshere-ns}}",
     "autoblockid": "Used as name of autoblock, instead of autoblocked IPs. Parameters:\n* $1 - autoblock ID",
     "block": "{{doc-special|Block}}\n{{Identical|Block user}}",
     "unblock": "{{doc-special|Unblock}}",
+    "unblock-summary": "{{doc-specialpagesummary|unblock}}",
     "blockip": "Used as the text of a link in the sidebar toolbox. Clicking this link takes you to [[Special:Block]], with a relevant username or IP address (e.g. \"Username\" on [[User talk:Username]], [[Special:Contributions/Username]], etc.) already filled in.\n\n{{Identical|Block user}}",
     "blockip-legend": "Legend/Header for the fieldset around the input form of [[Special:Block]].\n\n{{Identical|Block user}}",
     "blockiptext": "Used in the {{msg-mw|Blockip}} form in [[Special:Block]].\n\nRefers to {{msg-mw|Policy-url}}.\n\nThis message may follow the message {{msg-mw|Ipb-otherblocks-header}} and other block messages.\n\nSee also:\n* {{msg-mw|Unblockiptext}}",
     "blockipsuccesstext": "Used in [[Special:Block]].\nThe title (subject) for this message is {{msg-mw|Blockipsuccesssub}}.\n\nParameters:\n* $1 - username, can be used for GENDER",
     "ipb-blockingself": "Used as confirmation message in [[Special:Block]].\n\nSee also:\n* {{msg-mw|Ipb-confirmhideuser}}",
     "ipb-confirmhideuser": "Used as confirmation message in [[Special:Block]].\n\nSee also:\n* {{msg-mw|Ipb-blockingself}}",
+    "ipb-confirmaction": "Confirmation message displayed to users asking them to think again before really blocking someone.",
     "ipb-edit-dropdown": "Shown beneath the user block form on the right side. It is a link to {{msg-mw|Ipbreason-dropdown|notext=1}}.\n\nSee also:\n* {{msg-mw|Delete-edit-reasonlist}}\n* {{msg-mw|Protect-edit-reasonlist}}",
     "ipb-unblock-addr": "Used as page title in [[Special:Block]], if the target user is specified.\n\nParameters:\n* $1 - target username\n\nSee also:\n* {{msg-mw|Ipb-unblock}}",
     "ipb-unblock": "Used as page title in [[Special:Block]], if the target user is not specified.\n\nSee also:\n* {{msg-mw|Ipb-unblock-addr}}",
     "blocklist-by": "This is a column header in the table on the page [[Special:BlockList]].",
     "blocklist-params": "This is a column header in the table on the page [[Special:BlockList]].",
     "blocklist-reason": "This is a column header in the table on the page [[Special:BlockList]].\n\n{{Identical|Reason}}",
+    "blocklist-summary": "{{doc-specialpagesummary|blocklist}}",
     "ipblocklist-submit": "Used as Submit button text in the form on [[Special:BlockList]].\n\nSee also:\n* {{msg-mw|Ipblocklist-legend}}\n* {{msg-mw|Ipblocklist-submit}}\n{{Identical|Search}}",
     "ipblocklist-localblock": "[[File:Special IPBlockList new.png|thumb|Example]]\nUsed on [[Special:IPBlockList]] as header when global blocks exists too.",
     "ipblocklist-otherblocks": "[[File:Special IPBlockList new.png|thumb|Example]]\nUsed on [[Special:IPBlockList]] as header for other blocks, i.e. from GlobalBlocking or TorBlocks.\n\nParameters:\n* $1 - number of blocks\nSee also:\n* {{msg-mw|Ipb-otherblocks-header}}",
     "cant-see-hidden-user": "Used as (red) error message on [[Special:Block]] when you try to change (as sysop without the hideuser right) the block of a hidden user.",
     "ipbblocked": "Error message shown when a user tries to alter block settings when they are themselves blocked.",
     "ipbnounblockself": "Error message shown when a user without the <code>unblockself</code> right tries to unblock themself.",
+    "ipb-default-expiry": "{{ignored}}The default block expiry on the block form on [[Special:Block]].",
     "lockdb": "The title of the special page [[Special:LockDB]].\n\nAlso used as the title of the error message {{msg-mw|Databasenotlocked}} in [[Special:UnlockDB]].\n\nSee also:\n* {{msg-mw|Lockdb}}\n* {{msg-mw|Unlockdb}}\n* {{msg-mw|Lockfilenotwritable|error in Special:LockDB}}\n* {{msg-mw|Databasenotlocked|error in Special:UnlockDB}}\n{{Identical|Lock database}}",
     "unlockdb": "The title of the special page [[Special:UnlockDB]].\n\n{{Identical|Unlock database}}",
     "lockdbtext": "Used in the Lock form on [[Special:LockDB]].\n\nSee also:\n* {{msg-mw|Lockbtn}}\n* {{msg-mw|Unlockbtn}}\n* {{msg-mw|Lockdbtext}}\n* {{msg-mw|Unlockdbtext}}",
     "databasenotlocked": "Used as error message in [[Special:UnlockDB]].\nThe title of this error message is {{msg-mw|Lockdb}}.\n\nSee also:\n* {{msg-mw|Lockdb|title}}\n* {{msg-mw|Databasenotlocked|message}}",
     "lockedbyandtime": "Used as part of the message when a database is locked through [[Special:LockDB]]. Parameters:\n* $1 is the user that locked the database.\n* $2 is the date on which the lock was made\n* $3 is the time at which the lock was made",
     "move-page": "Used as page title of [[Special:MovePage]] to move pages.\n\nSee example: [[Special:MovePage/Portal:En]].\n\nParameters:\n* $1 - the name of the page to be moved (without link)",
+    "movepage-summary": "{{doc-specialpagesummary|movepage}}",
     "move-page-legend": "Legend of the fieldset around the input form of [[Special:MovePage/testpage]].\n\nSee also:\n* {{msg-mw|movearticle|label for old title}}\n* {{msg-mw|newtitle|label for new title}}\n* {{msg-mw|movereason|label for textarea}}\n* {{msg-mw|movetalk|label for checkbox}}\n* {{msg-mw|move-leave-redirect|label for checkbox}}\n* {{msg-mw|fix-double-redirects|label for checkbox}}\n* {{msg-mw|move-subpages|label for checkbox}}\n* {{msg-mw|move-talk-subpages|label for checkbox}}\n* {{msg-mw|move-watch|label for checkbox}}\n{{Identical|Move page}}",
     "movepagetext": "Introduction shown when moving a page ([[Special:MovePage]]).\n\nSpecial pages mentioned: {{msg-mw|Doubleredirects}}, {{msg-mw|Brokenredirects}}\n\nSee also:\n* {{msg-mw|Movepagetext-noredirectfixer}}",
     "movepagetext-noredirectfixer": "A variant of the following message ''Movepagetext'' displayed when the automatic redirect fixer is not enabled.\n\nSpecial pages mentioned: {{msg-mw|Doubleredirects}}, {{msg-mw|Brokenredirects}}\n\nSee also:\n* {{msg-mw|Movepagetext}}",
     "movesubpagetext": "Used in [[Special:MovePage]]. Parameters:\n* $1 - number of subpages\nSee also:\n* {{msg-mw|movesubpage|section header}}\n* {{msg-mw|movenosubpage|without subpage}}",
     "movenosubpage": "See also:\n* {{msg-mw|movesubpage|section header}}\n* {{msg-mw|movenosubpage|without subpage}}\n* {{msg-mw|movesubpagetext|with subpages}}",
     "movereason": "Used in [[Special:MovePage]]. The text for the inputbox to give a reason for the page move.\n\nSee also:\n* {{msg-mw|Move-page-legend|legend for the form}}\n* {{msg-mw|Movearticle|label for old title}}\n* {{msg-mw|Newtitle|label for new title}}\n* {{msg-mw|Movetalk|label for checkbox}}\n* {{msg-mw|Move-leave-redirect|label for checkbox}}\n* {{msg-mw|Fix-double-redirects|label for checkbox}}\n* {{msg-mw|Move-subpages|label for checkbox}}\n* {{msg-mw|Move-talk-subpages|label for checkbox}}\n* {{msg-mw|Move-watch|label for checkbox}}\n{{Identical|Reason}}",
+    "move-redirect-text": "{{ignored}}The text that's added to a redirected page when that redirect is created.",
     "revertmove": "{{Identical|Revert}}",
     "delete_and_move": "Button text on the move page when the target page already exists.",
     "delete_and_move_text": "Used when moving a page, but the destination page already exists and needs deletion.\n\nThis message is to confirm that you really want to delete the page.\n\nParameters:\n* $1 - the destination page title\n\nSee also:\n* {{msg-mw|Delete and move confirm}}",
     "move-over-sharedrepo": "Notice when a file with that filename already exists on a shared repository, such as Wikimedia Commons.\n\nParameters:\n* $1 - the destination page title",
     "file-exists-sharedrepo": "Used in [[Special:MovePage]].",
     "export": "Page title of [[Special:Export]], a page where a user can export pages from a wiki to a file.",
+    "export-summary": "{{doc-specialpagesummary|export}}",
     "exporttext": "{{doc-important|Leave the line <code><nowiki>[[{{#Special:Export}}/{{MediaWiki:Mainpage}}]]</nowiki></code> exactly as it is!}}\nMain text on [[Special:Export]].\n\nRefers to {{msg-mw|Mainpage}}.",
     "exportall": "A label of checkbox option in [[Special:Export]]",
     "exportcuronly": "A label of checkbox option in [[Special:Export]]",
     "thumbnail_image-missing": "This is the parameter 1 of the message {{msg-mw|thumbnail error}}.\n*$1 is the path incl. filename of the missing image",
     "thumbnail_image-failure-limit": "Used as <code>$1</code> in {{msg-mw|Thumbnail error}}.\n\nParameters:\n* $1 - the maximum allowed number of failed attempts",
     "import": "The title of the special page [[Special:Import]];",
+    "import-summary": "{{doc-specialpagesummary|import}}",
     "importinterwiki": "Used as legend for the Import form in [[Special:Import]].",
     "import-interwiki-text": "Used as summary for the Import form in [[Special:Import]].",
     "import-interwiki-source": "Used as label for input box in [[Special:Import]].",
     "importuploaderrorsize": "Used as error message when importing from file.\n\nSee also:\n* {{msg-mw|importnofile}}\n* {{msg-mw|importuploaderrorpartial}}\n* {{msg-mw|importuploaderrortemp}}",
     "importuploaderrorpartial": "Used as error message when importing from file.\n\nSee also:\n* {{msg-mw|importnofile}}\n* {{msg-mw|importuploaderrorsize}}\n* {{msg-mw|importuploaderrortemp}}",
     "importuploaderrortemp": "Used as error message when importing from file.\n\nSee also:\n* {{msg-mw|importnofile}}\n* {{msg-mw|importuploaderrorsize}}\n* {{msg-mw|importuploaderrorpartial}}",
+    "import-parse-failure": "Error message shown when importing one or more pages to the wiki via an XML file, if the import failed because the XML in the file could not be parsed.",
     "import-noarticle": "Used as error message when importing from interwiki.\n\nSee also:\n* {{msg-mw|Import-noarticle}}\n* {{msg-mw|Importbadinterwiki}}",
     "import-nonewrevisions": "Used in [[Special:Import]].",
     "xml-error-string": "Parameters:\n* $1 - Some kind of message, perhaps name of the error?\n* $2 - line number\n* $3 - column number\n* $4 - ?? $this->mByte . $this->mContext\n* $5 - error description\nExample:\n* Import failed: XML import parse failure at line 1, col 1 (byte 3; \"- <mediawiki xml\"): Empty document",
     "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-anonuserpage": "Tooltip for a link to the user page of the current anonymous user.",
     "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}}",
     "tooltip-pt-preferences": "Tooltip shown when hovering over the {{msg-mw|Mypreferences}} link in your personal toolbox (upper right side).\n\nSee also:\n* {{msg-mw|Mypreferences}}\n* {{msg-mw|Accesskey-pt-preferences}}\n* {{msg-mw|Tooltip-pt-preferences}}\n{{Identical|Preferences}}",
     "tooltip-preferences-save": "Used as tooltip for Save button.\n\nSee also:\n* {{msg-mw|Saveprefs}}\n* {{msg-mw|Accesskey-preferences-save}}\n* {{msg-mw|Tooltip-preferences-save}}",
     "tooltip-summary": "Used as tooltip for Summary input box in Editor page.\n\nSee also:\n* {{msg-mw|Summary}}\n* {{msg-mw|Accesskey-summary}}\n* {{msg-mw|Tooltip-summary}}",
     "interlanguage-link-title": "{{Optional}}\nFormat of a sidebar interwiki link tooltip. Parameters:\n* $1 - page name in the target wiki\n* $2 - target wiki language autonym",
+    "interlanguage-link-title-langonly": "{{ignored}}Interlanguage link title. Parameters: $1 replaced with a language name.",
     "common.css": "{{optional}}\nCSS applied to all users.",
     "cologneblue.css": "{{optional}}",
     "monobook.css": "{{optional}}\nCSS applied to users using Monobook skin.",
     "spam_blanking": "Edit summary for spam cleanup script.\n\nUsed when a page is blanked (made to have no content, but still exist) because the script could not find an appropriate revision to set the page to.\n\nParameters:\n* $1 - a spammed domain name",
     "spam_deleting": "Edit summary for spam cleanup script.\n\nUsed when a page is deleted because all revisions contained a particular link.\n\nParameters:\n* $1 - a spammed domain name",
     "simpleantispam-label": "Used as label for the input box in \"Edit\" page.\n\nThe label and the input box are always hidden.",
+    "pageinfo-header": "{{ignored}}Custom text for the top of the info page (action=info).",
     "pageinfo-title": "Page title for action=info. Parameters:\n* $1 is the page name",
     "pageinfo-not-current": "Error message displayed when information for an old revision is requested. Example: [{{fullurl:Project:News|oldid=4266597&action=info}}]",
     "pageinfo-header-basic": "Table section header in action=info. See [{{canonicalurl:MediaWiki:Pageinfo-header-basic/en|action=info}} example].\n{{Identical|Basic information}}",
     "pageinfo-hidden-categories": "The list of hidden categories on the page. Parameters:\n* $1 - the number of hidden categories on the page\n{{Identical|Hidden category}}",
     "pageinfo-templates": "The list of templates transcluded within the page. Parameters:\n* $1 is the number of templates transcluded within the current page.\nSee also:\n* {{msg-mw|Pageinfo-transclusions}}",
     "pageinfo-transclusions": "The list of pages on which this page is transcluded. Parameters:\n* $1 is the number of pages the current page is transcluded on.\nSee also:\n* {{msg-mw|Pageinfo-templates}}",
+    "pageinfo-footer": "{{ignored}}Custom text for the bottom of the info page (action=info).",
     "pageinfo-toolboxlink": "Information link for the page (like 'What links here', but to action=info for the current page instead)",
     "pageinfo-redirectsto": "Key for the row shown if this page is a redirect. Verb. See [{{canonicalurl:w:Main_page|action=info}} example].",
     "pageinfo-redirectsto-info": "Text to put in parentheses for the link to the action=info of the redirect target.\n{{Identical|Info}}",
     "exif-contrast": "{{Related|Exif-contrast}}",
     "exif-saturation": "{{Related|Exif-saturation}}",
     "exif-sharpness": "{{Related|Exif-sharpness}}",
+    "exif-devicesettingdescription": "The section header shown above device settings extracted from a file's EXIF data on the file's page.",
     "exif-subjectdistancerange": "{{Related|Exif-subjectdistancerange}}",
     "exif-imageuniqueid": "A unique identifier for the image in the form of a 128-bit hexadecimal string. See http://www.exif.org/Exif2-2.PDF for details on exif properties.",
     "exif-gpsversionid": "Version of the GPS IFD used to store location information. This is usually 2.2.0.0",
     "exif-gpsaltituderef": "No longer used except for when using foreign image repository with old version of mediawiki. 0 for above sea level, 1 for below sea level.",
     "exif-gpsaltitude": "Altitude in meters that the image was taken at.",
     "exif-gpstimestamp": "Time (does not include date) that GPS measurement was taken, in UTC. Since often this is at the same time as photo was taken, this is sometimes more reliable than {{msg-mw|exif-datetimeoriginal}}.",
+    "exif-gpssatellites": "Label for EXIF information. Indicates the GPS satellites used for measurements.",
     "exif-gpsstatus": "See also:\n* {{msg-mw|Exif-gpsstatus-a}}\n* {{msg-mw|Exif-gpsstatus-v}}",
     "exif-gpsmeasuremode": "Is the measurement 2D (latitude and longitude) or 3D (latitude, longitude, and altitude).\n\nSee also:\n* {{msg-mw|Exif-gpsmeasuremode-2}}\n* {{msg-mw|Exif-gpsmeasuremode-3}}",
     "exif-gpsdop": "How accurate the GPS information is. See http://en.wikipedia.org/wiki/Dilution_of_precision_(GPS)\n{{Related|Exif-gpsdop}}",
     "exif-gpstrack": "See also:\n* {{msg-mw|Exif-gpstrackref}}\n* {{msg-mw|Exif-gpsimgdirection}}\n* {{msg-mw|Exif-gpsimgdirectionref}}\n* {{msg-mw|Exif-gpsdestbearing}}\n* {{msg-mw|Exif-gpsdestbearingref}}",
     "exif-gpsimgdirectionref": "See also:\n* {{msg-mw|Exif-gpstrack}}\n* {{msg-mw|Exif-gpstrackref}}\n* {{msg-mw|Exif-gpsimgdirection}}\n* {{msg-mw|Exif-gpsdestbearing}}\n* {{msg-mw|Exif-gpsdestbearingref}}",
     "exif-gpsimgdirection": "See also:\n* {{msg-mw|Exif-gpstrack}}\n* {{msg-mw|Exif-gpstrackref}}\n* {{msg-mw|Exif-gpsimgdirectionref}}\n* {{msg-mw|Exif-gpsdestbearing}}\n* {{msg-mw|Exif-gpsdestbearingref}}",
+    "exif-gpsmapdatum": "Label for EXIF information. Indicates the geodetic survey data used by the GPS receiver.",
     "exif-gpsdestlatituderef": "{{Related|Exif-gpslatitude}}",
     "exif-gpsdestlatitude": "The latitude of the location shown in the picture, if it is different from latitude of the camera location. See {{msg-mw|exif-gpslatitude}}.\n{{Related|Exif-gpslatitude}}\n{{Identical|Latitude}}",
     "exif-gpsdestlongituderef": "{{Related|Exif-gpslatitude}}",
     "exif-gpsdestbearing": "See also:\n* {{msg-mw|Exif-gpstrack}}\n* {{msg-mw|Exif-gpstrackref}}\n* {{msg-mw|Exif-gpsimgdirection}}\n* {{msg-mw|Exif-gpsimgdirectionref}}\n* {{msg-mw|Exif-gpsdestbearingref}}",
     "exif-gpsdestdistanceref": "I think \"reference\" stands for \"unit\". See {{msg-mw|Exif-gpsspeedref}}\n{{Related|Exif-gpsdestdistance}}",
     "exif-gpsdestdistance": "{{Related|Exif-gpsdestdistance}}",
+    "exif-gpsprocessingmethod": "Label for EXIF information. A character string recording the name of the method used for location finding.",
+    "exif-gpsareainformation": "Label for EXIF information. Contains a character string recording the name of the GPS area.",
     "exif-gpsdatestamp": "Date (does not generally include time unless recorded in XMP) that GPS measurement was taken, in UTC. Since often this is at the same date as photo was taken, this is sometimes more reliable than {{msg-mw|exif-datetimeoriginal}}.",
+    "exif-gpsdifferential": "Label for EXIF information. Indicates whether differential correction is applied to the GPS receiver.",
     "exif-coordinate-format": "{{optional}}\nFor formatting GPS latitude coordinates. Parameters:\n* $1 - degrees\n* $2 - minutes\n* $3 - seconds (up to two decimal places)\n* $4 - direction (N, S, W, or E)\n* $5 - (Unused) coordinate as a single positive or negative real number",
     "exif-jpegfilecomment": "This is not a true exif tag, but the contents of the JPEG COM segment. This often contains a file source, but can potentially contain any comment about the file. This is similar to {{msg-mw|exif-usercomment}}, {{msg-mw|exif-pngfilecomment}}, and {{msg-mw|exif-giffilecomment}}.",
     "exif-keywords": "List of keywords for the photograph (or other media).\n\nThis can come from IPTC-iim 2:25 keyword field, or XMP's dc:subject field.",
     "livepreview-error": "Used as error message. Parameters:\n* $1 - ...\n* $2 - ...\nSee also:\n* {{msg-mw|Livepreview-failed}}\n* {{msg-mw|Livepreview-error}}",
     "lag-warn-normal": "Used as warning about slave lag. Parameters:\n* $1 - number of seconds\nSee also:\n* {{msg-mw|Lag-warn-high}}",
     "lag-warn-high": "Used as warning about slave lag. Parameters:\n* $1 - number of seconds\nSee also:\n* {{msg-mw|Lag-warn-normal}}",
+    "editwatchlist-summary": "{{doc-specialpagesummary|editwatchlist}}",
     "watchlistedit-numitems": "Message on [[Special:EditWatchlist]]. This is paired with the message {{Msg-mw|Watchlistedit-noitems}} which appears instead of this message when $1 is 0.",
     "watchlistedit-noitems": "Message on [[Special:EditWatchlist]], which only appears when a user's watchlist is empty.",
     "watchlistedit-normal-title": "Title of [[Special:Watchlist/edit|special page]].",
     "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": "{{doc-special|Version}}\n{{Identical|Version}}",
+    "version-summary": "{{doc-specialpagesummary|version}}",
     "version-extensions": "Header on [[Special:Version]].",
     "version-specialpages": "Part of [[Special:Version]].\n{{Identical|Special page}}",
     "version-parserhooks": "This message is a heading at [[Special:Version]] for extensions that modifies the parser of wikitext.",
     "version-software": "Message shown on [[Special:Version]].\nThis message is followed by the list of installed software (MediaWiki, PHP and MySQL).",
     "version-software-product": "Shown in [[Special:Version]].\n{{Identical|Product}}",
     "version-software-version": "{{Identical|Version}}",
+    "version-db-mysql-url": "{{ignored}}URL to the website of MySQL",
+    "version-db-mariadb-url": "{{ignored}}URL to the website of MariaDB",
+    "version-db-percona-url": "{{ignored}}URL to the website of Percona",
+    "version-db-postgres-url": "{{ignored}}URL to the website of PostgreSQL",
+    "version-db-oracle-url": "{{ignored}}URL to the website of Oracle",
+    "version-db-sqlite-url": "{{ignored}}URL to the website of SQLite",
+    "version-db-mssql-url": "{{ignored}}URL to the website of Microsoft SQL Server",
     "version-entrypoints": "Header on [[Special:Version]] above a table that lists the URLs of various entry points in this MediaWiki installation. Entry points are the \"places\" where the wiki's content and information can be accessed in various ways, for instance the standard index.php which shows normal pages, histories etc.",
     "version-entrypoints-header-entrypoint": "Header for the first column in the entry points table on [[Special:Version]].\nSee also {{msg-mw|Version-entrypoints}}",
     "version-entrypoints-header-url": "Header for the second column in the entry points table on [[Special:Version]].\n{{Identical|URL}}",
     "fileduplicatesearch-result-n": "Result line after the list of files of [[Special:FileDuplicateSearch]]\n\n* $1 is the name of the requested file.\n* $2 is the number of identical duplicates of the requested file",
     "fileduplicatesearch-noresults": "Parameters:\n* $1 - file name",
     "specialpages": "{{doc-special|SpecialPages|unlisted=1}}\nDisplay name of link to [[Special:SpecialPages]] shown on all pages in the toolbox.\n\nSee also:\n* {{msg-mw|Specialpages}}\n* {{msg-mw|Accesskey-t-specialpages}}\n* {{msg-mw|Tooltip-t-specialpages}}\n{{Identical|Special page}}",
+    "specialpages-summary": "{{doc-specialpagesummary|specialpages}}",
     "specialpages-note-top": "Heading for {{msg-mw|specialpages-note}}.\n{{Identical|Legend}}",
     "specialpages-note": "Footer note for the [[Special:SpecialPages]] page",
     "specialpages-group-maintenance": "{{doc-special-group|like=[[Special:DoubleRedirects]], [[Special:LonelyPages]] and [[Special:WantedPages]]}}",
     "intentionallyblankpage": "Text displayed in [[Special:BlankPage]].\n\nSee also:\n* {{msg-mw|Intentionallyblankpage|page title}}",
     "external_image_whitelist": "As usual please leave all the wiki markup, including the spaces, as they are. You can translate the text, including 'Leave this line exactly as it is'. The first line of this messages has one (1) leading space.\n\nSee definition of [[w:Regular_expression|regular expression]] on Wikipedia.",
     "tags": "Shown on [[Special:Specialpages]] for page listing the tags that the software may mark an edit with, and their meaning. For more information on tags see [[mw:Manual:Tags|MediaWiki]].\n\nIt appears that the word 'valid' describes 'tags', not 'change'. It also appears that you could use the term 'defined' instead of 'valid', or perhaps use a phrase meaning 'The change tags that are in use'.",
+    "tags-summary": "{{doc-specialpagesummary|tags}}",
     "tag-filter": "Caption of a filter shown on lists of changes (e.g. [[Special:Log]], [[Special:Contributions]], [[Special:Newpages]], [[Special:Recentchanges]], [[Special:Recentchangeslinked]], page histories)",
     "tag-filter-submit": "Caption of the submit button displayed next to the tag filter on lists of changes (e.g. [[Special:Log]], [[Special:Contributions]], [[Special:Newpages]], [[Special:Recentchanges]], [[Special:Recentchangeslinked]], page histories)\n\n{{Identical|Filter}}",
     "tag-list-wrapper": "Wrapper for the list of tags shown on recent changes, watchlists, history pages and diffs.\n\nParameters:\n* $1 - number of distinct tags for given edit\n* $2 - comma-separated list of tags for given edit",
     "tags-edit": "Used on [[Special:Tags]]. Verb. Used as display text on a link to create/edit a description.\n{{Identical|Edit}}",
     "tags-hitcount": "Shown in the \"{{msg-mw|Tags-hitcount-header}}\" column in [[Special:Tags]]. For more information on tags see [[mw:Manual:Tags|MediaWiki]].\n\nParameters:\n* $1 - the number of changes marked with the tag",
     "comparepages": "The title of [[Special:ComparePages]]",
+    "comparepages-summary": "{{doc-specialpagesummary|comparepages}}",
     "compare-page1": "Label for the field of the 1st page in the comparison for [[Special:ComparePages]]\n{{Identical|Page}}",
     "compare-page2": "Label for the field of the 2nd page in the comparison for [[Special:ComparePages]]\n{{Identical|Page}}",
     "compare-rev1": "Label for the field of the 1st revision in the comparison for [[Special:ComparePages]]\n{{Identical|Revision}}",
     "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}}",
+    "move-redirect-suppressed": "{{ignored}}Message unused?",
     "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.",
index e8359d3..3ab68a2 100644 (file)
     "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",
index 0f55f36..14289ec 100644 (file)
     "disclaimers": "Infurmaziòn legêli",
     "disclaimerpage": "Project: Avìs generèl",
     "edithelp": "Livar dal spiegaziòn",
-    "helppage": "Help:Tòt j argumént",
     "mainpage": "Prèma Pagina",
     "privacy": "Léz sora agli infurmaziòn persunèli",
     "privacypage": "Project: Léz sora agli infurmaziòn persunèli",
index 93712c6..b91e233 100644 (file)
     "disclaimers": "Ismigilen",
     "disclaimerpage": "Project:Asmigel amatu",
     "edithelp": "Tallalt deg uẓareg",
-    "helppage": "Help:Tira d yiwlafen",
     "mainpage": "Tasna Tamezwarut",
     "mainpage-description": "Tasna Tamezwarut",
     "portal": "Tawwart n timetti",
index 16d6d00..ae06c72 100644 (file)
@@ -7,7 +7,8 @@
             "Kazu89",
             "Shirayuki",
             "Urhixidur",
-            "לערי ריינהארט"
+            "לערי ריינהארט",
+            "Davent"
         ]
     },
     "tog-underline": "Suttastritgar colliaziuns:",
@@ -72,7 +73,7 @@
     "january": "schaner",
     "february": "favrer",
     "march": "mars",
-    "april": "avril",
+    "april": "avrigl",
     "may_long": "matg",
     "june": "zercladur",
     "july": "fanadur",
@@ -84,7 +85,7 @@
     "january-gen": "schaner",
     "february-gen": "favrer",
     "march-gen": "mars",
-    "april-gen": "avril",
+    "april-gen": "avrigl",
     "may-gen": "matg",
     "june-gen": "zercladur",
     "july-gen": "fanadur",
     "accountcreatedtext": "Il conto d'utilisader [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|talk]]) è vegnì creà.",
     "createaccount-title": "Crear in conto per {{SITENAME}}",
     "createaccount-text": "Insatgi ha creà in conto d'utilisader per tia adressa dad e-mail sin {{SITENAME}} ($4). Il pled-clav generà automaticamain per l'utilisader «$2» è «$3». Ti ta duessas t'annunzar uss e midar tes pled-clav. \n\nSche ti na levas betg crear quest conto d'utilisader pos ti ignorar quest e-mail.",
-    "usernamehasherror": "Il num d'utilisader na po betg cuntegnair il segn da rauta (#)",
     "login-throttled": "Ti has empruvà memia savens da t'annunziar.\nSpetga $1 avant ch'empruvar anc ina giada.",
     "login-abort-generic": "Annunzia senza success - Annullà",
     "loginlanguagelabel": "Lingua: $1",
     "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",
     "upload-permitted": "Tips da datotecas lubids: $1.",
     "upload-preferred": "Tips da datotecas preferids: $1.",
     "upload-prohibited": "Tips da datotecas betg lubids: $1.",
-    "uploadlog": "protocol da datotecas chargiadas si",
     "uploadlogpage": "Protocol da datotecas chargiadas si",
     "uploadlogpagetext": "Quai è ina glista da las datotecas ch'èn vegnidas chargiadas si sco ultimas.\nGuarda era la [[Special:NewFiles|galleria da novas datotecas]] per ina survista pli visuala.",
     "filename": "Num da datoteca",
     "filereuploadsummary": "Midadas da la datoteca:",
     "filestatus": "Status dals dretgs d'autur:",
     "filesource": "Funtauna:",
-    "uploadedfiles": "Datotecas chargiadas si",
     "ignorewarning": "Ignorar l'avertiment e memorisar la datoteca",
     "ignorewarnings": "Ignorar tut ils avertiments (Warnung)",
     "minlength1": "Nums da datotecas ston esser almain in bustab lung.",
     "overwroteimage": "ha chargià si ina nova versiun da \"[[$1]]\"",
     "uploaddisabled": "Chargiar si è deactivà.",
     "copyuploaddisabled": "Il transferir per URL è deactivà.",
-    "uploadfromurl-queued": "Tia datoteca per transferir è vegnida agiuntada a la colonna da spetga.",
     "uploaddisabledtext": "La funcziun da chargiar si datotecas è deactivada.",
     "php-uploaddisabledtext": "La funcziun da chargiar si datotecas è deactivada en PHP. \nControllescha per plaschair l'opziun <code>file_uploads</code>.",
     "uploadscripted": "Questa datoteca cuntegna HTML u code da scripts che pudess vegnir exequì per sbagl dal navigatur.",
     "upload-misc-error": "Errur da transferir nunenconuschenta",
     "upload-misc-error-text": "Ina errur nunenconuschenta è capitada durant transferir. \nControllescha per plaschair che l'URL è valida ed accessibla ed emprova anc ina giada.\nSch'il problem exista anc adina, contactescha in [[Special:ListUsers/sysop|administratur]].",
     "upload-too-many-redirects": "La URL ha cuntegnì memia blers renviaments",
-    "upload-unknown-size": "Grondezza nunenconuschenta",
     "upload-http-error": "In sbagl da HTTP è capità: $1",
     "upload-copy-upload-invalid-domain": "Transferir copias n'è betg pussaivel sin questa domain.",
     "backend-fail-stream": "Impussibel da leger la datoteca $1.",
     "img-auth-streaming": "Stream da \"$1\".",
     "img-auth-public": "La funcziun da img_auth.php è da returnar datotecas d'in vichi privat.\nQuest vichi è configurà sco public.\nPer cuntanscher segirezza opgimala è img_auth.php deactivà.",
     "img-auth-noread": "L'utilisader n'ha betg access da leger \"$1\".",
-    "img-auth-bad-query-string": "L'URL ha in string da query nunvalid.",
     "http-invalid-url": "URL nunvalida: $1",
     "http-invalid-scheme": "URLs dal schema \"$1\" na vegnan betg sustegnidas.",
     "http-request-error": "La damonda HTTP n'è betg reussida causa ina errur nunenconuschenta.",
     "filehist-dimensions": "dimensiuns",
     "filehist-filesize": "grondezza da datoteca",
     "filehist-comment": "commentari",
-    "filehist-missing": "Datoteca manca",
     "imagelinks": "Utilisaziun da la datoteca",
     "linkstoimage": "{{PLURAL:$1|La suandanta pagina è colliada|Las suandantas $1 paginas èn colliadas}} cun questa datoteca:",
     "linkstoimage-more": "Dapli che {{PLURAL:$1|ina pagina è colliada|$1 paginas èn colliadas}} a questa datoteca.\nLa suandanta glista mussa be {{PLURAL:$1|l'emprima colliaziun|las emprimas $1 colliaziuns}} a questa pagina.\nIna [[Special:WhatLinksHere/$2|glista cumpletta]] è disponibla",
     "emailuser-title-notarget": "Trametter in e-mail a l'utilisader",
     "emailpage": "Trametter in e-mail a l'utilisader",
     "emailpagetext": "Ti pos utilisar il formular sutvart per trametter in'e-mail a {{GENDER:$1|quest utilisader|questa utilisadra}}.\nL'adressa dad e-mail che ti has endatà en [[Special:Preferences|tias preferenzas]] vegn inditgada sco speditur da l'e-mail, uschia {{GENDER:$1|ch'il retschavider|che la retschavidra}} po rispunder directamain a tai.",
-    "usermailererror": "La funcziun dad e-mail ha returnà ina errur:",
     "defemailsubject": "{{SITENAME}} e-mail da l'utilisader \"$1\"",
     "usermaildisabled": "Trametter e-mails è deactivà",
     "usermaildisabledtext": "Ti na pos betg trametter e-mails ad auters utilisaders sin questa wiki",
     "noemailtitle": "Nagina adressa dad e-mail",
     "noemailtext": "Quest utilisader n'ha betg inditgà ina adressa dad e-mail valida.",
-    "nowikiemailtitle": "Betg lubì da termetter e-mail",
     "nowikiemailtext": "Quest utilisader ha tschernì ch'el na vul betg reschaiver e-mails dad auters utilisaders.",
     "emailnotarget": "Num d'utilisader nunexistent u nunvalid sco desinatur.",
     "emailtarget": "Endatescha il num d'utilisader dal destinatur",
     "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",
     "watching": "observ...",
     "unwatching": "observ betg pli...",
     "watcherrortext": "Ina errur è capitada durant midar tia configuraziun da tia glista d'observaziun per \"$1\".",
-    "enotif_mailer": "Servetsch d'infurmaziun per e-mail da {{SITENAME}}",
     "enotif_reset": "Marcar tut las paginas sco visitadas.",
     "enotif_impersonal_salutation": "Utilisader da {{SITENAME}}",
     "enotif_subject_deleted": "La pagina $1 da {{SITENAME}} è vegnida stizzada da {{GENDER:$2|$2}}",
     "excontent": "il cuntegn era: \"$1\"",
     "excontentauthor": "il cuntegn era: \"$1\" (ed il sulet contribuent era \"[[Special:Contributions/$2|$2]]\")",
     "exbeforeblank": "il cuntegn avant svidar la pagina era: \"$1\"",
-    "exblank": "la pagina era vida",
     "delete-confirm": "Stizzar \"$1\"",
     "delete-legend": "Stizzar",
     "historywarning": "'''Attenziun:''' L'artitgel che ti vuls stizzar ha ina cronologia cun circa {{PLURAL:$1|ina versiun|$1 versiuns}}:",
     "importunknownsource": "Funtauna d'import nunenconuschenta",
     "importcantopen": "Betg pussaivel dad avrir la datoteca d'import",
     "importbadinterwiki": "Colliaziun interwiki nunvalida",
-    "importnotext": "Vid u nagin text",
     "importsuccess": "Terminà l'import!",
-    "importhistoryconflict": "La cronologia cuntegna versiuns che stattan en conflict (eventualmain è questa pagina gia vegnida importada ina giada)",
     "importnosources": "Naginas funtaunas per l'import transwiki èn vegnidas definidas e la funcziun da chargiar si directamain la coronologia è deactivada.",
     "importnofile": "Nagina datoteca d'import è vegnida chargiada si.",
     "importuploaderrorsize": "Betg reussì da chargiar si la datoteca d'import.\nLa datoteca è pli gronda che la grondezza maximala per chargiar si.",
index 4844455..48873b6 100644 (file)
@@ -91,7 +91,6 @@
     "disclaimers": "Termenurya",
     "disclaimerpage": "Project:Termenurya",
     "edithelp": "Editisaripnasko zhutipen",
-    "helppage": "Help:Zhutipen",
     "mainpage": "Sherutni patrin",
     "mainpage-description": "Sherutni patrin",
     "portal": "Maladipnasko than",
index 4fd7545..6ebacee 100644 (file)
     "permalink": "Legătură permanentă",
     "print": "Tipărire",
     "view": "Lectură",
+    "view-foreign": "Vizualizare la $1",
     "edit": "Modificare",
+    "edit-local": "Modifică descrierea locală",
     "create": "Creare",
+    "create-local": "Adaugă descriere locală",
     "editthispage": "Modificați pagina",
     "create-this-page": "Creați această pagină",
     "delete": "Ștergere",
     "accountcreatedtext": "Contul utilizatorului pentru [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|discuție]]) a fost creat.",
     "createaccount-title": "Creare de cont la {{SITENAME}}",
     "createaccount-text": "Cineva a creat un cont asociat adresei dumneavoastră de e-mail pe {{SITENAME}} ($4) numit „$2” și având parola „$3”.\nEste de dorit să vă autentificați și să schimbați parola cât mai repede.\n\nIgnorați acest mesaj dacă crearea contului s-a produs în urma unei greșeli.",
-    "usernamehasherror": "Numele de utilizator nu poate conține caractere diez (#)",
     "login-throttled": "Ați avut prea multe încercări recente de a vă autentifica.\nVă rugăm să așteptați $1 până să reîncercați.",
     "login-abort-generic": "Procesul de autentificare a eșuat și a fost abandonat",
     "loginlanguagelabel": "Limba: $1",
     "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",
     "right-protect": "Schimbă nivelurile de protejare și modifică pagini protejate în cascadă",
     "right-editprotected": "Modifică pagini protejate ca „{{int:protect-level-sysop}}”",
     "right-editsemiprotected": "Modifică pagini protejate ca „{{int:protect-level-autoconfirmed}}”",
-    "right-editinterface": "Modificare interfața cu utilizatorul",
+    "right-editinterface": "Modifică interfața cu utilizatorul",
     "right-editusercssjs": "Modifică fișierele CSS și JS ale altor utilizatori",
     "right-editusercss": "Modifică fișierele CSS ale altor utilizatori",
     "right-edituserjs": "Modifică fișierele JS ale altor utilizatori",
     "upload-permitted": "Tipuri de fișiere permise: $1.",
     "upload-preferred": "Tipuri de fișiere preferate: $1.",
     "upload-prohibited": "Tipuri de fișiere interzise: $1.",
-    "uploadlog": "jurnal fișiere trimise",
     "uploadlogpage": "Jurnal fișiere trimise",
     "uploadlogpagetext": "Mai jos este afișată lista ultimelor fișiere trimise.\nVezi [[Special:NewFiles|galeria fișierelor noi]] pentru o mai bună vizualizare.",
     "filename": "Nume fișier",
     "filereuploadsummary": "Modificări ale fișierului:",
     "filestatus": "Statutul drepturilor de autor:",
     "filesource": "Sursă:",
-    "uploadedfiles": "Fișiere trimise",
     "ignorewarning": "Ignoră avertismentul și salvează fișierul",
     "ignorewarnings": "Ignoră orice avertismente",
     "minlength1": "Numele fișierelor trebuie să fie cel puțin o literă.",
     "overwroteimage": "încărcat o versiune nouă a fișierului \"[[$1]]\"",
     "uploaddisabled": "Ne pare rău, trimiterea de imagini este dezactivată.",
     "copyuploaddisabled": "Trimiterea prin URL este dezactivată.",
-    "uploadfromurl-queued": "Fișierul a fost pus în șirul de așteptare.",
     "uploaddisabledtext": "Încărcările de fișiere sunt dezactivate.",
     "php-uploaddisabledtext": "Încărcarea de fișiere este dezactivată în PHP.\nVă rugăm să verificați setările din file_uploads.",
     "uploadscripted": "Fișierul conține HTML sau cod script care poate fi interpretat în mod eronat de un browser.",
     "upload-misc-error": "Eroare de încărcare necunoscută",
     "upload-misc-error-text": "A apărut o eroare necunoscută în timpul încărcării.\nVă rugăm să verificați dacă adresa URL este validă și accesibilă și încercați din nou.\nDacă problema persistă, contactați un [[Special:ListUsers/sysop|administrator]].",
     "upload-too-many-redirects": "URL-ul conținea prea multe redirecționări",
-    "upload-unknown-size": "Mărime necunoscută",
     "upload-http-error": "A avut loc o eroare HTTP: $1",
     "upload-copy-upload-invalid-domain": "Încărcarea copiilor nu este disponibilă pentru acest domeniu.",
     "backend-fail-stream": "Imposibil de citit fișierul $1.",
     "img-auth-streaming": "Derularea continuă a \"$1\".",
     "img-auth-public": "Funcția img_auth.php este pentru a exporta fișiere de pe un wiki privat.\nAcest wiki este configurat ca unul public.\nPentru securitate optimă, img_auth.php este dezactivat.",
     "img-auth-noread": "Acest utilizator nu are acces să citească \"$1\".",
-    "img-auth-bad-query-string": "Adresa URL are un șir de interogare invalid.",
     "http-invalid-url": "URL invalid: $1",
     "http-invalid-scheme": "Adresele URL cu schema „$1” nu sunt acceptate.",
     "http-request-error": "Cererea HTTP a eșuat din cauza unei erori necunoscute.",
     "filehist-dimensions": "Dimensiuni",
     "filehist-filesize": "Mărimea fișierului",
     "filehist-comment": "Comentariu",
-    "filehist-missing": "Fișier lipsă",
     "imagelinks": "Utilizarea fișierului",
     "linkstoimage": "{{PLURAL:$1|Următoarea pagină trimite spre|Următoarele $1 pagini trimit spre|Următoarele $1 de pagini trimit spre}} această imagine:",
     "linkstoimage-more": "Mai mult de $1 {{PLURAL:$1|pagină este legată|pagini sunt legate}} de acest fișier.\nUrmătoarea listă arată {{PLURAL:$1|prima legătură|primele $1 legături}} către acest fișier.\nO [[Special:WhatLinksHere/$2|listă completă]] este disponibilă.",
     "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",
+    "listgrouprights-namespaceprotection-header": "Restricții de spațiu de nume",
+    "listgrouprights-namespaceprotection-namespace": "Spațiu de nume",
+    "listgrouprights-namespaceprotection-restrictedto": "Drept(uri) care permit(e) utilizatorului modificări",
     "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.",
+    "noindex-category-desc": "Pagina conține cuvântul magic <code><nowiki>__NOINDEX__</nowiki></code> (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 <code><nowiki>__INDEX__</nowiki></code> (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 <code>$wgMaxArticleSize</code>, 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 <code>{{{Foo}}})</code>, pagina a depășit <code>$wgMaxArticleSize</code>.",
     "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.",
+    "hidden-category-category-desc": "Această categorie conține <code><nowiki>__HIDDENCAT__</nowiki></code>, 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",
     "emailuser-title-notarget": "E-mail către utilizator",
     "emailpage": "E-mail către utilizator",
     "emailpagetext": "Puteți folosi formularul de mai jos pentru a trimite un e-mail {{GENDER:$1|acestui utilizator|acestei utilizatoare}}.\nAdresa de e-mail specificată de dumneavoastră în [[Special:Preferences|preferințele de utilizator]] va apărea ca adresa expeditorului e-mailului; astfel, destinatarul va putea să vă răspundă direct.",
-    "usermailererror": "Obiectul de mail a dat eroare:",
     "defemailsubject": "E-mail {{SITENAME}} de la utilizatorul „$1”",
     "usermaildisabled": "E-mail dezactivat",
     "usermaildisabledtext": "Nu puteți trimite e-mail altor utilizatori ai acestui wiki.",
     "noemailtitle": "Fără adresă de e-mail",
     "noemailtext": "Utilizatorul nu a specificat o adresă validă de e-mail.",
-    "nowikiemailtitle": "Nu este permis e-mail-ul",
     "nowikiemailtext": "Acest utilizator a ales să nu primească e-mail-uri de la alți utilizatori.",
     "emailnotarget": "Destinatarul este un nume de utilizator inexistent sau invalid.",
     "emailtarget": "Introduceți numele de utilizator al destinatarului",
     "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",
     "watching": "Se urmărește...",
     "unwatching": "Așteptați...",
     "watcherrortext": "A apărut o eroare în timp ce se modificau setările listei de pagini urmărite pentru „$1”.",
-    "enotif_mailer": "Sistemul de notificare {{SITENAME}}",
     "enotif_reset": "Marchează toate paginile vizitate",
     "enotif_impersonal_salutation": "Utilizator {{SITENAME}}",
     "enotif_subject_deleted": "Pagina $1 de la {{SITENAME}} a fost ștearsă de către {{gender:$2|$2}}",
     "excontent": "conținutul era: '$1'",
     "excontentauthor": "conținutul era: „$1” (unicul contribuitor: [[Special:Contributions/$2|$2]])",
     "exbeforeblank": "conținutul înainte de golire era: '$1'",
-    "exblank": "pagina era goală",
     "delete-confirm": "Şterge \"$1\"",
     "delete-legend": "Şterge",
     "historywarning": "'''Atenție:''' istoricul paginii pe care o ștergeți conține aproximativ $1 {{PLURAL:$1|versiune|versiuni|de versiuni}}:",
     "importunknownsource": "Tipul sursei de import este necunoscut",
     "importcantopen": "Fișierul importat nu a putut fi deschis",
     "importbadinterwiki": "Legătură interwiki greșită",
-    "importnotext": "Gol sau fără text",
     "importsuccess": "Import reușit!",
-    "importhistoryconflict": "Există istorii contradictorii (se poate să fi importat această pagină înainte)",
     "importnosources": "Nici o sursă de import transwiki a fost definită și încărcările directe ale istoricului sunt oprite.",
     "importnofile": "Nici un fișier pentru import nu a fost încărcat.",
     "importuploaderrorsize": "Încărcarea fișierului a eșuat.\nFișierul are o mărime mai mare decât limita de încărcare permisă.",
index b118a8b..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",
index 297874d..c43fc38 100644 (file)
     "permalink": "Постоянная ссылка",
     "print": "Печать",
     "view": "Просмотр",
+    "view-foreign": "Посмотреть на сайте $1",
     "edit": "Править",
+    "edit-local": "Редактировать локальное описание",
     "create": "Создать",
+    "create-local": "Добавить локальное описание",
     "editthispage": "Править эту страницу",
     "create-this-page": "Создать эту страницу",
     "delete": "Удалить",
     "accountcreatedtext": "Создана учётная запись участника [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|обс.]]).",
     "createaccount-title": "{{SITENAME}}: создание учётной записи",
     "createaccount-text": "Кто-то создал учётную запись «$2» на сервере проекта {{SITENAME}} ($4), указав ваш адрес электронной почты. \n\nПароль учётной записи — «$3». Вам следует авторизоваться на сайте и изменить пароль.\n\nПроигнорируйте данное сообщение, если учётная запись была создана по ошибке.",
-    "usernamehasherror": "Имя участника не может содержать символ «решётки»",
     "login-throttled": "Вы сделали слишком много попыток представиться системе.\nПожалуйста, подождите $1 перед тем, как попробовать снова.",
     "login-abort-generic": "Неудачная попытка представиться системе",
     "loginlanguagelabel": "Язык: $1",
     "prefs-skin": "Тема оформления",
     "skin-preview": "Предпросмотр",
     "datedefault": "По умолчанию",
-    "prefs-beta": "Бета-возможности",
     "prefs-datetime": "Дата и время",
     "prefs-labs": "Экспериментальные возможности",
     "prefs-user-pages": "Страницы участника",
     "upload-permitted": "Разрешённые типы файлов: $1.",
     "upload-preferred": "Предпочтительные типы файлов: $1.",
     "upload-prohibited": "Запрещённые типы файлов: $1.",
-    "uploadlog": "журнал загрузок",
     "uploadlogpage": "Журнал загрузок",
     "uploadlogpagetext": "Ниже представлен список последних загрузок файлов.\nСм. также [[Special:NewFiles|галерею новых файлов]], где сведения о новых загрузках представлены в более наглядном виде.",
     "filename": "Имя файла",
     "filereuploadsummary": "Изменения в файле:",
     "filestatus": "Условия распространения:",
     "filesource": "Источник:",
-    "uploadedfiles": "Загруженные файлы",
     "ignorewarning": "Игнорировать предупреждения и сохранить файл",
     "ignorewarnings": "Игнорировать предупреждения",
     "minlength1": "Название файла должно содержать хотя бы одну букву.",
     "overwroteimage": "загружена новая версия «[[$1]]»",
     "uploaddisabled": "Загрузка запрещена",
     "copyuploaddisabled": "Загрузка по URL отключена.",
-    "uploadfromurl-queued": "Ваша загрузка поставлена в очередь.",
     "uploaddisabledtext": "Загрузка файлов отключена.",
     "php-uploaddisabledtext": "Загрузка файлов отключена в настройках PHP. Пожалуйста, проверьте значение свойства file_uploads.",
     "uploadscripted": "Файл содержит HTML-код или скрипт, который может быть ошибочно обработан браузером.",
     "upload-misc-error": "Неизвестная ошибка загрузки",
     "upload-misc-error-text": "Неизвестная ошибка загрузки. Пожалуйста, проверьте, что адрес верен, и повторите попытку. Если проблема остаётся, обратитесь к [[Special:ListUsers/sysop|администратору]].",
     "upload-too-many-redirects": "URL содержит слишком много перенаправлений",
-    "upload-unknown-size": "Неизвестный размер",
     "upload-http-error": "Произошла ошибка HTTP: $1",
     "upload-copy-upload-invalid-domain": "Копирование загрузок не доступно в этом домене.",
     "backend-fail-stream": "Не удалось транслировать файл $1.",
     "img-auth-streaming": "Потоковая передача «$1».",
     "img-auth-public": "Назначением img_auth.php является вывод файлов из закрытой вики.\nЭта вики настроена как общедоступная.\nДля оптимизации безопасности img_auth.php отключена.",
     "img-auth-noread": "Участник не имеет доступа на чтение «$1».",
-    "img-auth-bad-query-string": "URL-адрес содержит неправильную строку запроса.",
     "http-invalid-url": "Ошибочный URL: $1",
     "http-invalid-scheme": "Не поддерживаются адреса со схемой «$1»",
     "http-request-error": "Сбой HTTP-запроса из-за неизвестной ошибки.",
     "filehist-dimensions": "Размеры",
     "filehist-filesize": "Размер файла",
     "filehist-comment": "Примечание",
-    "filehist-missing": "Файл отсутствует",
     "imagelinks": "Использование файла",
     "linkstoimage": "{{PLURAL:$1|Следующая $1 страница ссылается|Следующие $1 страниц ссылаются|Следующие $1 страницы ссылаются}} на данный файл:",
     "linkstoimage-more": "Более $1 {{PLURAL:$1|страницы|страниц}} ссылаются на этот файл.\nВ данном списке {{PLURAL:$1|представлена только $1 ссылка|представлены только $1 ссылок|представлены только $1 ссылки}} на этот файл.\nДоступен также [[Special:WhatLinksHere/$2|полный список]].",
     "listgrouprights-removegroup-self": "может удалять свою учётную запись из {{PLURAL:$2|1=группы|групп}}: $1",
     "listgrouprights-addgroup-self-all": "Может добавлять все группы к своей учётной записи",
     "listgrouprights-removegroup-self-all": "может удалять все группы со своей учётной записи",
+    "listgrouprights-namespaceprotection-header": "Ограничения пространства имён",
+    "listgrouprights-namespaceprotection-namespace": "Пространство имён",
+    "listgrouprights-namespaceprotection-restrictedto": "Права, позволяющие участнику редактировать",
     "trackingcategories": "Отслеживающие категории",
     "trackingcategories-summary": "На этой странице перечислены отслеживающие категории, которые автоматически заполняются программным обеспечением MediaWiki. Их можно переименовать, изменив соответствующие системные сообщения в пространстве имён {{ns:8}}.",
     "trackingcategories-msg": "Отслеживающая категория",
     "trackingcategories-name": "Имя сообщения",
     "trackingcategories-desc": "Критерий включения в категорию",
-    "noindex-category-desc": "Ð\9dа Ñ\81Ñ\82Ñ\80аниÑ\86е Ð¸Ð¼ÐµÐµÑ\82Ñ\81Ñ\8f Â«Ð²Ð¾Ð»Ñ\88ебное Ñ\81лово» <nowiki>__NOINDEX__</nowiki> (и Ñ\81Ñ\82Ñ\80аниÑ\86а Ð½Ð°Ñ\85одиÑ\82Ñ\81Ñ\8f Ð² Ð¿Ñ\80оÑ\81Ñ\82Ñ\80анÑ\81Ñ\82ве Ð¸Ð¼Ñ\91н, Ð³Ð´Ðµ Ñ\80азÑ\80еÑ\88Ñ\91н Ñ\8dÑ\82оÑ\82 Ñ\84лаг), Ð¿Ð¾Ñ\8dÑ\82омÑ\83 Ð¾Ð½Ð° Ð½Ðµ Ð¸Ð½Ð´ÐµÐºÑ\81иÑ\80Ñ\83Ñ\8eÑ\82Ñ\81Ñ\8f Ð¿Ð¾Ð¸Ñ\81ковÑ\8bми Ñ\80обоÑ\82ами.",
+    "noindex-category-desc": "СÑ\82Ñ\80аниÑ\86а Ð½Ðµ Ð¸Ð½Ð´ÐµÐºÑ\81иÑ\80Ñ\83Ñ\8eÑ\82Ñ\81Ñ\8f Ð¿Ð¾Ð¸Ñ\81ковÑ\8bми Ñ\80обоÑ\82ами, Ð¿Ð¾Ñ\82омÑ\83 Ñ\87Ñ\82о Ð½Ð° Ð½ÐµÐ¹ Ð¸Ð¼ÐµÐµÑ\82Ñ\81Ñ\8f Â«Ð²Ð¾Ð»Ñ\88ебное Ñ\81лово» <code><nowiki>__NOINDEX__</nowiki></code>, Ð¸ Ð¾Ð½Ð° Ð½Ð°Ñ\85одиÑ\82Ñ\81Ñ\8f Ð² Ð¿Ñ\80оÑ\81Ñ\82Ñ\80анÑ\81Ñ\82ве Ð¸Ð¼Ñ\91н, Ð³Ð´Ðµ Ñ\80азÑ\80еÑ\88Ñ\91н Ñ\8dÑ\82оÑ\82 Ñ\84лаг).",
     "index-category-desc": "На странице имеется «волшебное слово» __INDEX__ (и страница находится в пространстве имён, где разрешён этот флаг), поэтому она индексируются поисковыми роботами в тех случаях, когда этого обычно не происходит.",
-    "post-expand-template-inclusion-category-desc": "После показа всех шаблонов размер страницы станет больше, чем $wgMaxArticleSize, поэтому некоторые шаблоны не были показаны полностью.",
-    "post-expand-template-argument-category-desc": "После раскрытия аргумента шаблона (что-нибудь в тройных фигурных скобках, например, {{{Foo}}}), страница станет больше, чем $wgMaxArticleSize.",
+    "post-expand-template-inclusion-category-desc": "После показа всех шаблонов размер страницы станет больше, чем <code>$wgMaxArticleSize</code>, поэтому некоторые шаблоны не были показаны полностью.",
+    "post-expand-template-argument-category-desc": "После раскрытия аргумента шаблона (что-нибудь в тройных фигурных скобках, например, <code>{{{Foo}}})</code>, страница станет больше, чем <code>$wgMaxArticleSize</code>.",
     "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> в ней, что по умолчанию предотвращает её отображение на страницах в разделе категорий.",
+    "hidden-category-category-desc": "Это категория с добавленной меткой <code><nowiki>__HIDDENCAT__</nowiki></code> в ней, что по умолчанию предотвращает её отображение на страницах в разделе категорий.",
     "trackingcategories-nodesc": "Описание отсутствует.",
     "trackingcategories-disabled": "Категория отключена",
     "mailnologin": "Адрес для отправки отсутствует",
     "emailuser-title-notarget": "Написание электронного письма участнику",
     "emailpage": "Письмо участнику",
     "emailpagetext": "С помощью данной формы можно отправить сообщение на адрес электронной почты {{GENDER:$1|этого участника|этой участницы}}.\nВ качестве обратного адреса будет указан тот адрес, который вы указали в [[Special:Preferences|своих настройках]], таким образом получатель будет иметь возможность ответить непосредственно вам.",
-    "usermailererror": "При отправке сообщения электронной почты произошла ошибка:",
     "defemailsubject": "{{SITENAME}} — Письмо от $1",
     "usermaildisabled": "Электронная почта участника отключена",
     "usermaildisabledtext": "Вы не можете отправлять электронные письма другим участникам этой вики",
     "noemailtitle": "Адрес электронной почты отсутствует",
     "noemailtext": "Этот участник не указал действительный адрес электронной почты.",
-    "nowikiemailtitle": "Нет разрешения отправлять письма",
     "nowikiemailtext": "Этот участник указал, что не желает получать письма от других участников.",
     "emailnotarget": "Несуществующее или ошибочное имя участника-получателя.",
     "emailtarget": "Введите имя участника-получателя",
     "nowatchlist": "Ваш список наблюдения пуст.",
     "watchlistanontext": "Вы должны $1, чтобы просмотреть или отредактировать список наблюдения.",
     "watchnologin": "Нужно представиться системе",
-    "watchnologintext": "Вы должны [[Special:UserLogin|представиться системе]], чтобы иметь возможность изменять свой список наблюдения",
     "addwatch": "Добавить в список наблюдения",
     "addedwatchtext": "Страница «[[:$1]]» была добавлена в ваш [[Special:Watchlist|список наблюдения]].\nТам будут отмечаться последующие изменения этой страницы, а также связанной с ней страницы обсуждения.",
     "removewatch": "Удалить из списка наблюдения",
     "watching": "Добавление в список наблюдения…",
     "unwatching": "Удаление из списка наблюдения…",
     "watcherrortext": "Произошла ошибка при изменении настройки наблюдения для «$1».",
-    "enotif_mailer": "{{SITENAME}} Служба извещений по почте",
     "enotif_reset": "Отметить все страницы как просмотренные",
     "enotif_impersonal_salutation": "Участник {{grammar:genitive|{{SITENAME}}}}",
     "enotif_subject_deleted": "Страница проекта «{{SITENAME}}» с именем «$1» была удалена {{gender:$2|участником|участницей}} $2",
     "excontent": "содержимое: «$1»",
     "excontentauthor": "содержимое: «$1» (единственным автором был [[Special:Contributions/$2|$2]])",
     "exbeforeblank": "содержимое до очистки: «$1»",
-    "exblank": "страница была пуста",
     "delete-confirm": "$1 — удаление",
     "delete-legend": "Удаление",
     "historywarning": "'''Внимание:''' эта страница имеет историю изменений приблизительно из $1 {{PLURAL:$1|версии|версий}}:",
     "importunknownsource": "Неизвестный тип импортируемой страницы",
     "importcantopen": "Невозможно открыть импортируемый файл",
     "importbadinterwiki": "Неправильная интервики-ссылка",
-    "importnotext": "Текст отсутствует",
     "importsuccess": "Импортирование выполнено!",
-    "importhistoryconflict": "Конфликт существующих версий (возможно, эта страница уже была импортирована)",
     "importnosources": "Не был выбран источник межвики-импорта, прямая загрузка истории изменений отключена.",
     "importnofile": "Файл для импорта не был загружен.",
     "importuploaderrorsize": "Не удалось загрузить или импортировать файл. Размер файла превышает установленный предел.",
index f2d90d7..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": "Вымазати зо списку слїдованых сторінок",
index f3a1d59..37206aa 100644 (file)
@@ -96,7 +96,6 @@
     "currentevents": "Evenimente di tora",
     "disclaimers": "Nipricunuschire",
     "edithelp": "Agiutor ti alãxire",
-    "helppage": "Help:Conținut",
     "mainpage": "Prota frânḑâ",
     "mainpage-description": "Prota frânḑâ",
     "portal": "Portalu a comunitatiľei",
index 7652498..4972df2 100644 (file)
@@ -88,7 +88,6 @@
     "disclaimers": "Тајменулс",
     "disclaimerpage": "Project:тајменул",
     "edithelp": "Ајутор пентре едитаере",
-    "helppage": "Help:Ајутор",
     "mainpage": "Пажу принципу",
     "mainpage-description": "Пажу принципу",
     "privacy": "Политикмус де лижитул",
index f1c808c..d3275f3 100644 (file)
@@ -88,7 +88,6 @@
     "disclaimers": "tǎmenuls",
     "disclaimerpage": "Project:tǎmenul",
     "edithelp": "Ajutor pentru editaere",
-    "helppage": "Help:Ajutor",
     "mainpage": "Pažu principu",
     "mainpage-description": "Pažu principu",
     "privacy": "Politikmus de ližitul",
index 3abeeaa..6ef319a 100644 (file)
     "permalink": "स्थायिपरिसन्धिः",
     "print": "मुद्र्यताम्",
     "view": "दृश्यताम्",
+    "view-foreign": "$1 अत्र दृश्यताम्",
     "edit": "सम्पाद्यताम्",
+    "edit-local": "स्थानीयवर्णनं सम्पाद्यताम्",
     "create": "सृज्यताम्",
+    "create-local": "स्थानीयवर्णनं योज्यताम्",
     "editthispage": "इदं पृष्ठं सम्पाद्यताम्",
     "create-this-page": "इदं पृष्ठं सृज्यताम्",
     "delete": "अपाक्रियताम्",
     "accountcreated": "सदस्यता प्राप्ता",
     "accountcreatedtext": "[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|talk]]) कृते \"योजसम्भाषणम्\" इति पृष्ठं रचितम् ।",
     "createaccount-title": "{{SITENAME}} कृते सदस्यता प्राप्यताम्",
-    "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": "भवतः प्रवेशप्रयासः विफलीभूतः - परित्यक्तः",
+    "createaccount-text": "{{SITENAME}} ($4) इत्यत्र, \"$2\" नाम्ना, \"$3\" कूटशब्देन, च कोऽपि भवतः/भवत्याः ई-पत्रसङ्केतस्य उपयोगं कृत्वा सदस्यतां प्रापत् ।\nअधुना भवान्/भवती प्रवेशं कृत्वा गुप्तसङ्ख्यां परिवर्तयितं शक्नोति ।\nएषा सदस्यताप्राप्तिः क्षत्या अभवत् चेत्, एनं सन्देशम् अवगणोतु ।",
+    "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": "परमाणुपत्रसङ्गेत:",
-    "passwordreset-emailtitle": "{{SITENAME}} इत्यत्र लेखा-विवरणम्",
-    "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",
-    "passwordreset-emailsent": "एकः स्मारकः विद्युत्सन्देशः प्रेषितोऽस्ति।",
-    "passwordreset-emailsent-capture": "अधो दर्शितस्य विद्युन्मानसङ्केतस्य अनुस्मारकं प्रेषितम् ।",
-    "passwordreset-emailerror-capture": "अधो निर्दिष्टानुस्मारकः विद्युन्मानसन्देशः रचितः । किन्तुः योजकसम्प्रेषणं विपन्नम् ।$1",
-    "changeemail": "विद्युन्मानपत्रादेशं परिवर्तयतु",
-    "changeemail-header": "उपयोजकसंज्ञायाः विद्युन्मानपत्रसङ्केतं परिवर्तयतु ।",
-    "changeemail-text": "स्वस्य विद्युन्मानपत्रसङ्केतं परिवर्तयितुम् एतत् प्रपत्रं पूरयतु । दृढीकरणार्थं निकुञ्चः निवेशनीयः ।",
-    "changeemail-no-info": "अस्य पुटस्य उपसञ्चारार्थं नामाभिलेखनम् अनिवार्यम् ।",
-    "changeemail-oldemail": "प्रचलितः विद्युन्मानपत्रसङ्केतः ।",
-    "changeemail-newemail": "नूतनः विद्युन्मानसङ्केतः ।",
-    "changeemail-none": "असत्",
-    "changeemail-password": "भवतः {{SITENAME}} कूटशब्दः:",
-    "changeemail-submit": "विद्युन्मानपत्रसङ्केतं परिवर्तयतु ।",
-    "changeemail-cancel": "निवर्तयते",
+    "passwordreset-email": "ई-पत्रसङ्केतः",
+    "passwordreset-emailtitle": "{{SITENAME}} इत्यत्र योजकविषये",
+    "passwordreset-emailtext-ip": "कोऽपि (कदाचित् भवान्/भवती, $1 अन्तर्जालसंविदः (from IP)) {{SITENAME}}($4) जालस्थानस्य  कृते कूटशब्दपरिवर्तनस्य विनतिम् अकरोत् । निम्न{{PLURAL:$3|योजकः|योजकाः}} अनेन ई-पत्रेण सह सल्लग्नः अस्ति/सल्लग्नाः सन्ति ।\n\n$2\n\n{{PLURAL:$3|एषः अल्पकालीनकूटशब्दः|एते अल्पकालीनकूटशब्दाः}} {{PLURAL:$5|चतुर्विंशतिघण्टासु|$5 दिनेषु}} निरस्तः भविष्यति/निरस्ताः भविष्यन्ति ।\nअधुना प्रवेशं सम्प्राप्य कूटशब्दः परिवर्तनीयः एव । \n\nनिम्नकारणानि यदि सन्ति, तर्हि एनं सन्देशम् अवगण्यताम् ।\n\n१ कोऽपि अन्यः अत्र विनतिम् अकरोत् । \n२ पूरातनः कूटशब्दः भवतः/भवत्याः स्मरणे अस्ति ।\n३ भवान्/भवती कूटशब्दं परिवर्तयितुं नेच्छिति ।",
+    "passwordreset-emailtext-user": "$1 योजकः {{SITENAME}}($4) जालस्थानस्य  कृते कूटशब्दपरिवर्तनस्य विनतिम् अकरोत् । निम्न{{PLURAL:$3|योजकः|योजकाः}} अनेन ई-पत्रेण सह सल्लग्नः अस्ति/सल्लग्नाः सन्ति ।\n\n$2\n\n{{PLURAL:$3|एषः अल्पकालीनकूटशब्दः|एते अल्पकालीनकूटशब्दाः}} {{PLURAL:$5|चतुर्विंशतिघण्टासु|$5 दिनेषु}} निरस्तः भविष्यति/निरस्ताः भविष्यन्ति ।\nअधुना प्रवेशं सम्प्राप्य कूटशब्दः परिवर्तनीयः एव । \n\nनिम्नकारणानि यदि सन्ति, तर्हि एनं सन्देशम् अवगण्यताम् ।\n\n१ कोऽपि अन्यः अत्र विनतिम् अकरोत् । \n२ पूरातनः कूटशब्दः भवतः/भवत्याः स्मरणे अस्ति ।\n३ भवान्/भवती कूटशब्दं परिवर्तयितुं नेच्छिति ।",
+    "passwordreset-emailelement": "प्रयोक्तृनाम : $1\nअल्पकालीनकूटशब्दः : $2",
+    "passwordreset-emailsent": "परिवर्तितकूटशब्दस्य ई-पत्रं प्रेषितम् अस्ति ।",
+    "passwordreset-emailsent-capture": "परिवर्तितकूटशब्दस्य ई-पत्रं प्रेषितम् अस्ति । तत् अधः द्रष्टुं शक्यते ।",
+    "passwordreset-emailerror-capture": "परिवर्तितकूटशब्दस्य ई-पत्रं निर्मितम् अस्ति । तत् अधः द्रष्टुं शक्यते । परन्तु {{GENDER:$2|योजकाय}} प्रेषणकाले तत् निरस्तम् अभवत् : $1",
+    "changeemail": "ई-पत्रसङ्केतः परिवर्त्यताम्",
+    "changeemail-header": "प्रयोक्तृनाम्नः ई-पत्रसङ्केतः परिवर्त्यताम्",
+    "changeemail-text": "स्वस्य ई-पत्रसङ्केतं परिवर्तयितुम् अधः दत्तं प्रपत्रं पूरयतु । एतस्यै प्रक्रियायै कूटशब्दः आवश्यकः ।",
+    "changeemail-no-info": "एतत् पृष्ठं सम्पादयितुं प्रवेशः अनिवार्यः ।",
+    "changeemail-oldemail": "वर्तमानः ई-पत्रसङ्केतः",
+    "changeemail-newemail": "नूतनः ई-पत्रसङ्केतः :",
+    "changeemail-none": "(न कोऽपि)",
+    "changeemail-password": "भवतः/भवत्याः {{SITENAME}} कूटशब्दः:",
+    "changeemail-submit": "ई-पत्रं परिवर्त्यताम्",
+    "changeemail-cancel": "निरस्यताम्",
+    "changeemail-throttled": "भवता/भवत्या अत्यधिकाः प्रवेशप्रयासाः कृताः । \nकृपया $1 कालं यावत् प्रतिक्षां करोतु ।",
+    "resettokens": "चिह्नानि (tokens) परिवर्त्यताम्",
+    "resettokens-text": "भवतः/भवत्याः सदस्यतया सह सल्लग्नानि चिह्नानि () उपयोक्तुं शक्यन्ते । येन अनया सदस्यतया सह सल्लग्नाः काश्चन गुप्तसूचनाः ज्ञातुं शक्यन्ते ।",
+    "resettokens-no-tokens": "परिवर्तनार्थं न किमपि चिह्नं तत्र विद्यते ।",
+    "resettokens-legend": "चिह्नानि (tokens) परिवर्त्यताम्",
+    "resettokens-tokens": "चिह्नानि :",
+    "resettokens-token-label": "$1 (वर्तमानमूल्यम् : $2)",
+    "resettokens-watchlist-token": "[[Special:Watchlist|भवतः/भवत्याः ध्यानसूच्याः परिवर्तनस्य]] जालपूर्तेः (Atom/RSS) चिह्नं",
+    "resettokens-done": "चिह्नं परिवर्त्यताम्",
+    "resettokens-resetbutton": "अङ्कितं चिह्नं परिवर्त्यताम्",
     "bold_sample": "स्थूलाक्षराणि",
     "bold_tip": "स्थूलाक्षराणि",
     "italic_sample": "तिर्यक् अक्षरम्",
     "link_sample": "परिसन्धेः शीर्षकम्",
     "link_tip": "आन्तरिकसम्पर्कतन्तुः",
     "extlink_sample": "http://www.example.com परिसन्धेः शीर्षकम्",
-    "extlink_tip": "बाहà¥\8dयानà¥\81बनà¥\8dधà¤\83 (http:// à¤\87ति à¤ªà¥\82रà¥\8dवनà¥\8dयासमà¥\8d अग्रे योजनीयम् इति स्मरतु)",
+    "extlink_tip": "बाहà¥\8dयानà¥\81बनà¥\8dधà¤\83 (http:// à¤ªà¥\82रà¥\8dवनà¥\8dयाससà¥\8dय अग्रे योजनीयम् इति स्मरतु)",
     "headline_sample": "शीर्षकम्",
     "headline_tip": "द्वितीयस्तरीयं शीर्षकम्",
     "nowiki_sample": "अप्रारूपितं पाठम् अत्र निवेश्यताम्",
     "media_sample": "उदाहरणम्.ogg",
     "media_tip": "सञ्चिकासम्बन्धः",
     "sig_tip": "समयोल्लेखेन सह भवतः/भवत्याः हस्ताक्षरम्",
-    "hr_tip": "à¤\95à¥\8dषà¥\88तिà¤\9c-रà¥\87à¤\96ा (नà¥\8dयà¥\82नतया प्रयोक्तव्या)",
-    "summary": "सारांशः:",
+    "hr_tip": "तिरà¥\8dयà¤\95à¥\8d-रà¥\87à¤\96ा (भिनà¥\8dनतया प्रयोक्तव्या)",
+    "summary": "सारांशः :",
     "subject": "विषयः/शीर्षकम् :",
     "minoredit": "इदं लघु सम्पादनम्",
     "watchthis": "इदं पृष्ठं निरीक्षताम्",
     "showlivepreview": "प्रत्यक्षं प्राग्दृश्यम्",
     "showdiff": "परिवर्तनानि दृश्यन्ताम्",
     "anoneditwarning": "'''पूर्वसूचना''' भवता/भवत्या प्रवेशः न कृतः !\nअत्र सम्पादनं कर्तुं प्रवेशः अनिवार्यः । अन्यथा अस्य पृष्ठस्य इतिहासे भवतः/भवत्याः अन्तर्जालसंविदः (IP) सङ्ख्या अङ्किता भवति ।",
-    "anonpreviewwarning": "''भवानà¥\8d à¤ªà¥\8dरवà¥\87शितà¤\83 à¤¨ à¤\85सà¥\8dति। à¤°à¤\95à¥\8dषणà¥\87न à¤ªà¥\83षà¥\8dठसà¥\8dय à¤¸à¤®à¥\8dपादनà¥\87तिहासà¥\87 à¤­à¤µà¤¤à¤\83 à¤\86à¤\87पà¥\80सà¤\82à¤\95à¥\87तà¤\83 à¤\85à¤\82à¤\95ितà¤\83 à¤­à¤µà¤¿à¤·à¥\8dयति।''",
-    "missingsummary": "'''à¤\85नà¥\81सà¥\8dमारà¤\95मà¥\8d:''' à¤­à¤µà¤¤à¤¾ à¤¸à¤®à¥\8dपादनसà¥\8dय à¤¸à¤¾à¤°à¤\83 à¤¨ à¤ªà¥\8dरदतà¥\8dतà¤\83।\nà¤\9aà¥\87दà¥\8dभवानà¥\8d \"{{int:savearticle}}\" à¤\87तà¥\8dयà¥\87तदà¥\8d à¤ªà¥\81नà¤\83 à¤\95à¥\8dलिà¤\95à¥\8dà¤\95रà¥\8bति, à¤­à¤µà¤¤à¤\83 à¤¸à¤®à¥\8dपादनानि à¤¸à¤¾à¤°à¤¾à¤¦à¥\8d à¤\8bतà¥\87 à¤°à¤\95à¥\8dषितà¥\80भविषà¥\8dयनà¥\8dति।",
-    "missingcommenttext": "à¤\95à¥\83पया à¤\85धसà¥\8dतातà¥\8d à¤\8fà¤\95ा à¤\9fिपà¥\8dपणà¥\80 à¤¦à¤¾à¤¤à¤µà¥\8dया।",
-    "missingcommentheader": "'''à¤\85नà¥\81सà¥\8dमारà¤\95मà¥\8d:''' à¤­à¤µà¤¤à¤¾ à¤\85सà¥\8dयाà¤\83 à¤\9fिपà¥\8dपणà¥\8dयाà¤\83 à¤µà¤¿à¤·à¤¯à¤\83 à¤¶à¥\80रà¥\8dषà¤\95à¤\82 à¤µà¤¾ à¤¨ à¤ªà¥\8dरदतà¥\8dतà¤\83।\nà¤\9aà¥\87दà¥\8dभवानà¥\8d \"{{int:savearticle}}\" à¤\87तà¥\8dयà¥\87तदà¥\8d à¤ªà¥\81नà¤\83 à¤\95à¥\8dलिà¤\95à¥\8dà¤\95रà¥\8bति, à¤­à¤µà¤¤à¤\83 à¤¸à¤®à¥\8dपादनानि à¤µà¤¿à¤·à¤¯à¤¾à¤¤à¥\8d à¤¶à¥\80रà¥\8dषà¤\95ादà¥\8d à¤µà¤¾ à¤\8bतà¥\87 à¤°à¤\95à¥\8dषितà¥\80भविषà¥\8dयनà¥\8dति।",
+    "anonpreviewwarning": "''भवता/भवतà¥\8dया à¤ªà¥\8dरवà¥\87शà¤\83 à¤¨ à¤¸à¥\8dवà¥\80à¤\95à¥\83तà¤\83 à¥¤ à¤\85सà¥\8dय à¤ªà¥\83षà¥\8dठसà¥\8dय à¤ªà¤°à¤¿à¤µà¤°à¥\8dतनसà¥\8dय à¤\87तिहासà¥\87 à¤­à¤µà¤¤à¤\83/भवतà¥\8dयाà¤\83 à¤\85नà¥\8dतरà¥\8dà¤\9cालसà¤\82विदà¤\83 (IP) à¤\89लà¥\8dलà¥\87à¤\96à¥\8b à¤­à¤µà¤¿à¤·à¥\8dयति ।''",
+    "missingsummary": "'''सà¥\8dमरतà¥\81''' à¤­à¤µà¤¤à¤¾/भवतà¥\8dया à¤¸à¤®à¥\8dपादनसà¥\8dय à¤¸à¤¾à¤°à¤¾à¤\82शà¤\83 à¤¨ à¤ªà¥\8dरदतà¥\8dतà¤\83 à¥¤\n\"{{int:savearticle}}\" à¤\85तà¥\8dर à¤¯à¤¦à¤¿ à¤­à¤µà¤¾à¤¨à¥\8d/भवतà¥\80 à¤¦à¥\8dवितà¥\80यवारà¤\82 à¤¨à¥\81दिषà¥\8dयति, à¤¤à¤°à¥\8dहि à¤­à¤µà¤¤à¤\83/भवतà¥\8dयाà¤\83 à¤¸à¤®à¥\8dपादनसाराà¤\82शातà¥\8d à¤\8bतà¥\87 à¤ªà¤°à¤¿à¤µà¤°à¥\8dतनà¤\82 à¤°à¤\95à¥\8dषितà¤\82 à¤­à¤µà¤¿à¤·à¥\8dयति ।",
+    "missingcommenttext": "à¤\95à¥\83पया à¤\85धà¤\83 à¤\9fिपà¥\8dपणà¥\80à¤\82 à¤²à¤¿à¤\96तà¥\81 ।",
+    "missingcommentheader": "'''सà¥\8dमरतà¥\81''' à¤­à¤µà¤¤à¤¾/भवतà¥\8dया à¤\85सà¥\8dयà¥\88 à¤\9fिपà¥\8dपणà¥\8dयà¥\88 à¤µà¤¿à¤·à¤¯à¤\83/शà¥\80रà¥\8dषà¤\95à¤\82 à¤¨ à¤ªà¥\8dरदतà¥\8dतमà¥\8d à¥¤\n\"{{int:savearticle}}\" à¤\85तà¥\8dर à¤¯à¤¦à¤¿ à¤­à¤µà¤¾à¤¨à¥\8d/भवतà¥\80 à¤¦à¥\8dवितà¥\80यवारà¤\82 à¤¨à¥\81दिषà¥\8dयति, à¤¤à¤°à¥\8dहि à¤­à¤µà¤¤à¤\83/भवतà¥\8dयाà¤\83 à¤¸à¤®à¥\8dपादनसाराà¤\82शातà¥\8d à¤\8bतà¥\87 à¤\8fततà¥\8d à¤°à¤\95à¥\8dषितà¤\82 à¤­à¤µà¤¿à¤·à¥\8dयति ।",
     "summary-preview": "सारांशस्य प्राग्दृश्यम् :",
     "subject-preview": "विषयस्य/शीर्षकस्य प्राग्दृश्यम्:",
     "blockedtitle": "प्रयोक्ता अवरुद्धः वर्तते",
-    "blockedtext": "भवतः आइपिसङ्केतः स्वचालितविधिना अवरुद्धोऽस्ति, यस्मादयं भिन्नेनैकेन सदस्येन प्रयुक्त आसीत्, यो हि $1 इत्यनेन अवरुद्धः आसीत्।\nप्रदत्तं कारणमेतदस्ति:\n:''$2''\n* अवरोधनस्यारम्भः: $8\n* अवरोधनस्य समाप्तिः: $6\n* अभिप्रेतः अवरोध्यः: $7\n\nभवान् अवरोधार्थं सम्भाषणं कर्तुं  $1 इत्येतं अथवा अन्यान् [[{{MediaWiki:Grouppage-sysop}}|प्रबन्धकान्]] सम्पर्कं कर्त्तुं शक्नोति।\nमनसि धारयतु यद् भवान् \"e-mail this user\"(विद्युत्सन्देशः)  इति सुविधायाः प्रयोगः तावत् कर्त्तुं न शक्नोति यावत् भवानेकं  विधिमान्यं विद्युत्सन्देश-सङ्केतं [[Special:Preferences|user preferences]] इत्यत्र न पञ्जीकृतवानस्ति अपि च भवान् तस्य प्रयोगात् न निवारितोऽस्ति।\n\nभवतः वर्तमानः आइपीसङ्केतः $3 इति अस्ति। अपि च अवरोधनस्य परिचयचिह्नम्  (आइडी) #$5 इत्यस्ति।\nकृपया भवान् स्वकीयेषु सर्वेष्वपि प्रश्नेषु सर्वमेतत् वर्णनं ददातु।",
-    "autoblockedtext": "भवतः आइपिसङ्केतः स्वचालितविधिना अवरुद्धोऽस्ति, यस्मादयं भिन्नेनैकेन सदस्येन प्रयुक्त आसीत्, यो हि $1 इत्यनेन अवरुद्धः आसीत्।\nप्रदत्तं कारणमेतदस्ति:\n:''$2''\n* अवरोधनस्यारम्भः: $8\n* अवरोधनस्य समाप्तिः: $6\n* अभिप्रेतः अवरोध्यः: $7\n\nभवान् अवरोधार्थं सम्भाषणं कर्तुं  $1 इत्येतं अथवा अन्यान् [[{{MediaWiki:Grouppage-sysop}}|प्रबन्धकान्]] सम्पर्कं कर्त्तुं शक्नोति।\nमनसि धारयतु यद् भवान् \"e-mail this user\"(विद्युत्सन्देशः)  इति सुविधायाः प्रयोगः तावत् कर्त्तुं न शक्नोति यावत् भवानेकं  विधिमान्यं विद्युत्सन्देश-सङ्केतं [[Special:Preferences|user preferences]] इत्यत्र न पञ्जीकृतवानस्ति अपि च भवान् तस्य प्रयोगात् न निवारितोऽस्ति।\n\nभवतः वर्तमानः आइपीसङ्केतः $3 इति अस्ति। अपि च अवरोधनस्य परिचयचिह्नम्  (आइडी) #$5 इत्यस्ति।\nकृपया भवान् स्वकीयेषु सर्वेष्वपि प्रश्नेषु सर्वमेतत् वर्णनं ददातु।",
-    "blockednoreason": "न किमपि कारणम् दत्तम्",
-    "whitelistedittext": "पà¥\83षà¥\8dठाणाà¤\82 à¤¸à¤®à¥\8dपादनारà¥\8dथà¤\82 $1 à¤\87ति à¤\95ारà¥\8dयमà¥\8d à¤\86वशà¥\8dयà¤\95मà¥\8d।",
-    "confirmedittext": "समà¥\8dपादनातà¥\8d à¤ªà¥\82रà¥\8dवà¤\82 à¤­à¤µà¤¤à¤¾ à¤¸à¥\8dवà¤\95à¥\80यà¤\82 à¤µà¤¿à¤¦à¥\8dयà¥\81तà¥\8dसनà¥\8dदà¥\87शसà¤\82à¤\95à¥\87तà¤\83 à¤ªà¤°à¤¿à¤ªà¥\81षà¥\8dà¤\9fà¥\80à¤\95रणà¥\80यà¤\83।\nà¤\95à¥\83पया à¤¸à¥\8dवà¤\95à¥\80यà¤\83 à¤µà¤¿à¤¦à¥\8dयà¥\81तà¥\8dसनà¥\8dदà¥\87शसà¤\82à¤\95à¥\87तà¤\83 [[Special:Preferences|पà¥\8dरयà¥\8bà¤\95à¥\8dतà¥\83-वरà¥\80याà¤\82सि]] à¤\87तà¥\8dयà¥\87तदà¥\8dदà¥\8dवारा à¤ªà¥\8dरददातà¥\81 à¤¤à¤¥à¤¾ à¤\9a à¤ªà¥\8dरमाणà¥\80à¤\95रà¥\8bतà¥\81।",
-    "nosuchsectiontitle": "à¤\8fतादà¥\83शà¤\83 à¤\95à¥\8bपà¥\8dयनà¥\81भाà¤\97à¤\83 à¤¨ à¤²à¤¬à¥\8dधः",
-    "nosuchsectiontext": "भवता à¤\8fतादà¥\83श à¤\8fà¤\95à¥\8bऽनà¥\81भाà¤\97à¤\83 à¤¸à¤®à¥\8dपादितà¥\81à¤\82 à¤\9aà¥\87षà¥\8dà¤\9fितà¤\82, à¤¯à¤¨à¥\8dन à¤¹à¤¿ à¤µà¤¿à¤¦à¥\8dयतà¥\87।\nततà¥\8dतà¥\81 à¤ªà¤¶à¥\8dयति à¤­à¤µà¤¤à¤¿ à¤\8fव à¤ªà¥\8dरà¤\9aालितमà¥\8d à¤\85थवा à¤\85पाà¤\95à¥\83तà¤\82 à¤¸à¥\8dयातà¥\8d।",
+    "blockedtext": "<strong>भवतः/भवत्याः सदस्यता अन्तर्जालसंविद् वा प्रतिबन्धिता वर्तते ।</strong>\n\nप्रतिबन्धः $1 द्वारा अभवत् ।\nकारणं दत्तं यत्, <em>$2</em>.\n\n* प्रतिबन्धस्य प्रारम्भः : $8\n* प्रतिबन्धस्य समाप्तिः : $6\n* अभिप्रेतः अवरोध्यः : $7\n\n$1 अस्य सम्पर्कं कर्तुं शक्नोति । अथवा अन्य[[{{MediaWiki:Grouppage-sysop}}|प्रबन्धकेन]] सह प्रतिबन्धविषयकचर्चां कर्तुं शक्नोति ।\nभवान्/भवती \"ई-पत्रं प्रेष्यताम्\" विकल्पस्य उपयोगं कर्तुं न शक्नोति । भवतः/भवत्याः [[Special:Preferences|इष्टतमानि]] विकल्पे कोऽपि ई-पत्रसङ्केतः अस्ति, तस्य उपयोगाय च प्रतिबन्धः नास्ति चेत्, तस्य ई-पत्रस्य उपयोगं कर्तुं शक्नोति ।\n\nभवतः/भवत्याः वर्तमाना अन्तर्जालसंविद् $3, प्रतिबन्धितसदस्यता #$5 च अस्ति । \n\nयत्र कुत्रापि प्रबन्धसम्बद्धां चर्चां करोति, तत्र उक्तसूचनायाः  उपयोगम् अवश्यं करोतु ।",
+    "autoblockedtext": "<strong>भवतः/भवत्याः अन्तर्जालसंविद् प्रतिबन्धिता वर्तते ।</strong>\n\nप्रतिबन्धः $1 द्वारा अभवत् ।\nकारणं दत्तं यत्, <em>$2</em>.\n\n* प्रतिबन्धस्य प्रारम्भः : $8\n* प्रतिबन्धस्य समाप्तिः : $6\n* अभिप्रेतः अवरोध्यः : $7\n\n$1 अस्य सम्पर्कं कर्तुं शक्नोति । अथवा अन्य[[{{MediaWiki:Grouppage-sysop}}|प्रबन्धकेन]] सह प्रतिबन्धविषयकचर्चां कर्तुं शक्नोति ।\nभवान्/भवती \"ई-पत्रं प्रेष्यताम्\" विकल्पस्य उपयोगं कर्तुं न शक्नोति । भवतः/भवत्याः [[Special:Preferences|इष्टतमानि]] विकल्पे कोऽपि ई-पत्रसङ्केतः अस्ति, तस्य उपयोगाय च प्रतिबन्धः नास्ति चेत्, तस्य ई-पत्रस्य उपयोगं कर्तुं शक्नोति ।\n\nभवतः/भवत्याः वर्तमाना अन्तर्जालसंविद् $3, प्रतिबन्धितसदस्यता #$5 च अस्ति । \n\nयत्र कुत्रापि प्रबन्धसम्बद्धां चर्चां करोति, तत्र उक्तसूचनायाः  उपयोगम् अवश्यं करोतु ।",
+    "blockednoreason": "न किमपि कारणम् दत्तम्",
+    "whitelistedittext": "समà¥\8dपादनà¤\82 à¤\95रà¥\8dतà¥\81à¤\82 $1 à¤\86वशà¥\8dयà¤\95मà¥\8d ।",
+    "confirmedittext": "समà¥\8dपादनातà¥\8d à¤ªà¥\82रà¥\8dवà¤\82 à¤¸à¥\8dवसà¥\8dय à¤\88-पतà¥\8dरसà¤\99à¥\8dà¤\95à¥\87तà¤\82 à¤ªà¥\81षà¥\8dà¤\9fà¤\82 à¤\95रà¥\8bतà¥\81 à¥¤\n[[Special:Preferences|user preferences]] à¤\87तà¥\8dयतà¥\8dर à¤¸à¥\8dवसà¥\8dय à¤¯à¥\8bà¤\97à¥\8dयमà¥\8d à¤\88-पतà¥\8dरसà¤\99à¥\8dà¤\95à¥\87तà¤\82 à¤²à¤¿à¤\96तà¥\81 ।",
+    "nosuchsectiontitle": "à¤\8fतादà¥\83शà¤\83 à¤¨ à¤\95à¥\8bऽपि à¤µà¤¿à¤­à¤¾à¤\97à¤\83 à¤ªà¥\8dरापà¥\8dतः",
+    "nosuchsectiontext": "यà¤\83 à¤µà¤¿à¤­à¤¾à¤\97à¤\83 à¤\8fव à¤¨à¤¾à¤¸à¥\8dति, à¤¤à¤¾à¤¦à¥\83शसà¥\8dय à¤µà¤¿à¤­à¤¾à¤\97सà¥\8dय à¤¸à¤®à¥\8dपादनसà¥\8dय à¤¨à¤¿à¤¶à¥\8dà¤\9aयà¤\83 à¤\95à¥\83तà¤\83 à¤­à¤µà¤¤à¤¾/भवतà¥\8dया à¥¤\nà¤\8fषà¤\83 à¤µà¤¿à¤­à¤¾à¤\97à¤\83 à¤\9aालितà¤\83 à¤\85पाà¤\95à¥\83तà¤\83 à¤µà¤¾ à¤¸à¥\8dयातà¥\8d ।",
     "loginreqtitle": "प्रवेशः अपेक्षितः",
     "loginreqlink": "प्रविश्यताम्",
-    "loginreqpagetext": "अन्यानि पृष्ठानि द्रष्टुं भवता $1 इत्येतत् अवश्यमेव कर्त्तव्यम्।",
-    "accmailtitle": "à¤\95à¥\82à¤\9fसà¤\99à¥\8dà¤\95à¥\87तः प्रेषितः",
-    "accmailtext": "[[User talk:$1|$1]] à¤\87तà¥\8dयà¥\87तदरà¥\8dथà¤\82 à¤\8fà¤\95à¤\83 à¤¯à¤¾à¤¦à¥\83à¤\9aà¥\8dà¤\9bिà¤\95तया à¤\89तà¥\8dपादितà¤\83 à¤\95à¥\82à¤\9fशबà¥\8dदà¤\83 $2 à¤\87तà¥\8dयà¥\87ततà¥\8d à¤ªà¥\8dरति à¤ªà¥\8dरà¥\87षितà¥\8bऽसà¥\8dति।\nसतà¥\8dरारमà¥\8dभपशà¥\8dà¤\9aातà¥\8d à¤¨à¥\82तनायाà¤\83 à¤\85सà¥\8dयाà¤\83 à¤²à¥\87à¤\96ायाà¤\83 à¤\95à¥\82à¤\9fशबà¥\8dदà¤\83  '''[[Special:ChangePassword|à¤\95à¥\82à¤\9fशबà¥\8dदà¤\82 à¤ªà¤°à¤¿à¤µà¤°à¥\8dततामà¥\8d]]'' à¤\87ति à¤ªà¥\83षà¥\8dठà¥\87 à¤ªà¤°à¤¿à¤µà¤°à¥\8dतितà¥\81à¤\82 à¤¶à¤\95à¥\8dयतà¥\87।",
+    "loginreqpagetext": "अन्यानि पृष्ठानि द्रष्टुं $1 आवश्यकम् ।",
+    "accmailtitle": "à¤\95à¥\82à¤\9fशबà¥\8dदः प्रेषितः",
+    "accmailtext": "[[User talk:$1|$1]] à¤\95à¥\83तà¥\87 à¤\85शà¥\83à¤\99à¥\8dà¤\96लितरà¥\80तà¥\8dया (randomly) à¤\89तà¥\8dपादितà¤\83 à¤\95à¥\82à¤\9fशबà¥\8dदà¤\83 $2 à¤\88-पतà¥\8dरसà¤\99à¥\8dà¤\95à¥\87तà¤\82 à¤ªà¥\8dरति à¤ªà¥\8dरषितà¤\83 à¤\85सà¥\8dति à¥¤ <em>[[Special:ChangePassword|à¤\95à¥\82à¤\9fशबà¥\8dदà¤\83 à¤ªà¤°à¤¿à¤µà¤°à¥\8dतà¥\8dयतामà¥\8d]]</em> à¤\85तà¥\8dर à¤¤à¤¤à¥\8d à¤ªà¤°à¤¿à¤°à¥\8dतयितà¥\81à¤\82 à¤¶à¤\95à¥\8dयतà¥\87 ।",
     "newarticle": "(नूतनम्)",
     "newarticletext": "भवान्/भवती अनिर्मिते पृष्ठे अस्ति । \nपृष्ठं स्रष्टुम् अधः प्रदत्तायां पेटिकायां टङ्कनं प्रारभतु (साहाय्यार्थं [$1 अत्र]) नुदतु ।\nभवान्/भवती यदि क्षतिकारणात् एतत् पृष्ठं प्रति आगच्छत्, तर्हि अस्य गवेषकस्य (browser) Back नुदतु ।",
-    "anontalkpagetext": "तस्य अनामकयोजकस्य, अथवा अनुपयोजकस्य च परिचर्चापुटम् येन एतावति काले स्वस्थनं  न निर्मितम् । \nअतः तस्य अभिज्ञानार्थं ऐ.पि.सङ्गेतसङ्ख्या प्रयोजनीया । \nसा समाना सङ्ख्याः अन्ययोजकैः अपि विभक्ता । यदि भवान् अनामकयोजकः, भवता असम्बद्धटीकाः श्रुताः, कृपया स्वस्थनं निर्मीय नामाभिलेखं करोतु ।  [[Special:UserLogin/signup|create an account]], [[Special:UserLogin|log in]] अन्यानामकयोजकैः सह सम्भूयमनभ्रमैः विमुक्तः भवतु ।",
+    "anontalkpagetext": "----\n<em>एतत् सम्भाषणपृष्ठम् अनामकयोजकेभ्यः अस्ति । एतत् तेभ्यः अनामकयोजकेभ्यः रचितमस्ति, यैः सदस्यता न प्राप्ता अस्ति तथा च अस्य पृष्ठस्य उपयोगं न कुर्वन्तः सन्ति ।</em>\nतेषां व्यक्तिगतसूचनां प्राप्तुमेव वयं तस्य/तस्याः अन्तर्जालसंविदः उपयोगं कुर्मः । केचन योजकाः स्वस्य अन्तर्जालसंविदम् अन्यान् योजकान् कथयन्ति । \nयद्यपि अनामकयोजकः अहं नास्मि, तथापि अयोग्यसूचनाः मम पार्श्वे आगच्छन्त्यः सन्ति इति यदि भवान्/भवती अनुवति, तर्हि एतत् [[Special:UserLogin/signup|create an account]] एतत् [[Special:UserLogin|log in]] वा कृत्वा भविष्यस्य अनामकयोजकनां सन्देशेभ्यः स्वस्य रक्षणं करोतु ।",
     "noarticletext": "अस्मिन् पृष्ठे अधुना किमपि न विद्यते । [[Special:Search/{{PAGENAME}}|एषः शब्दः]] येषु पृष्ठेषु अन्तर्भवति, तानि पृष्ठानि अन्वेष्टुं शक्यन्ते । \n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}}  सम्बद्धेषु पृष्ठेषु अन्वेषणं]\n[{{fullurl:{{FULLPAGENAME}}|action=edit}} अस्य पृष्ठस्य सम्पादनं] वा  शक्यम्</span>.",
     "noarticletext-nopermission": "अस्मिन् पृष्ठे अधुना किमपि न विद्यते । [[Special:Search/{{PAGENAME}}|एषः शब्दः]] येषु पृष्ठेषु अन्तर्भवति, तानि पृष्ठानि अन्वेष्टुं शक्यन्ते । \n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}}  सम्बद्धेषु पृष्ठेषु अन्वेषणं]\n[{{fullurl:{{FULLPAGENAME}}|action=edit}} अस्य पृष्ठस्य सम्पादनं] वा  शक्यम्</span>.",
-    "missing-revision": "{{FULLPAGENAME}} इति नामाङ्कितपुटस्य #$1 इति पुनरावृत्तिः अत्र नाश्ति । \nपुटेन सह कालातीतानुबन्धकारणेन एतत् अभवत् ।\nविवरणम् अत्र दृश्यते ।[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log].",
-    "userpage-userdoesnotexist": "\"$1\" à¤\87ति à¤ªà¥\8dरयà¥\8bà¤\95à¥\8dतà¥\83लà¥\87à¤\96ा à¤ªà¤\9eà¥\8dà¤\9cà¥\80à¤\95à¥\83ता à¤¨à¤¾à¤¸à¥\8dति।\nà¤\9aà¥\87दà¥\8dभवानà¥\8d à¤\8fततà¥\8dपà¥\83षà¥\8dठà¤\82 à¤¸à¥\8dरषà¥\8dà¤\9fà¥\81मिà¤\9aà¥\8dà¤\9bति à¤¸à¤®à¥\8dपादयितà¥\81मिà¤\9aà¥\8dà¤\9bति à¤µà¤¾ à¤¤à¤¦à¤¾ à¤\95à¥\83पया à¤ªà¥\81नरà¥\80à¤\95à¥\8dषतामà¥\8d।",
-    "userpage-userdoesnotexist-view": "\"$1\" à¤\87ति à¤ªà¥\8dरयà¥\8bà¤\95à¥\8dतà¥\83लà¥\87à¤\96ा à¤ªà¤\9eà¥\8dà¤\9cà¥\80à¤\95à¥\83ता à¤¨à¤¾à¤¸à¥\8dति।",
+    "missing-revision": "\"{{FULLPAGENAME}}\" पृष्ठस्य संस्करणं #$1 नोपलभ्यत् ।\nयस्य पृष्ठस्य इतिहासे परिसन्धयः कालातीतान्यः सन्ति, तेषु पृष्ठेषु एवं भवति ।\nअधिकसूटनाः अत्र प्राप्तुं शक्यते [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} अपाकृतानाम् आवलिः].",
+    "userpage-userdoesnotexist": "\"$1\" à¤\87ति à¤ªà¥\8dरयà¥\8bà¤\95à¥\8dतà¥\83नाम à¤ªà¤\9eà¥\8dà¤\9cिà¤\95à¥\83तà¤\82 à¤¨ à¤µà¤¿à¤¦à¥\8dयतà¥\87 à¥¤ à¤\85सà¥\8dय\nनवरà¤\9aनायà¥\88/समà¥\8dपादनाय à¤¤à¤¤à¥\8d à¤ªà¤¶à¥\8dयतà¥\81 ।",
+    "userpage-userdoesnotexist-view": "\"$1\" à¤\87ति à¤ªà¥\8dरयà¥\8bà¤\95à¥\8dतà¥\83नाम à¤ªà¤\9eà¥\8dà¤\9cिà¤\95à¥\83तà¤\82 à¤¨ à¤µà¤¿à¤¦à¥\8dयतà¥\87 ।",
     "blocked-notice-logextract": "अयं प्रयोक्ता सम्प्रति अवरुद्धः वर्तते।\nनूतनतमा अवरोधाभिलेख-प्रविष्टिः सन्दर्भार्थम् अधस्तात् प्रदत्ताऽस्ति:",
-    "clearyourcache": "'''सूचनाः:''' संरक्षणानन्तरं परिवर्तनानां दर्शनाय जालगवेशकस्य पुनर्चालनम् अवश्यं भवेत् ।\n* '''Firefox / Safari:''' गृह्यताम् ''Shift'' नोदनावसरे ''Reload'', अथवा एतयोः अन्यतरं नुद्यताम् ''Ctrl-F5'' अथवा ''Ctrl-R'' (''⌘-R'' on a Mac)\n* '''Google Chrome:''' नुद्यताम् ''Ctrl-Shift-R'' (''⌘-Shift-R'' on a Mac)\n* '''Internet Explorer:''' गृह्यताम् ''Ctrl'' नोदनावसरे ''Refresh'', अथवा नुद्यताम् ''Ctrl-F5''\n* '''Opera:''' पुनर्चाल्यताम् ''Tools → Preferences''",
-    "usercssyoucanpreview": "'''सूचना :''' रक्षणात्पूर्वं स्वकीयं जावास्क्रिप्ट् इति लिपिं परीक्षितुं \"{{int:showpreview}}\" इति गण्डं प्रयोजयतु।",
-    "userjsyoucanpreview": "'''सूचना :''' रक्षणात्पूर्वं स्वकीयं जावास्क्रिप्ट् इति लिपिं परीक्षितुं \"{{int:showpreview}}\" इति गण्डं प्रयोजयतु।",
-    "usercsspreview": "'''मनसि धारयतु यद्भवान् केवलं प्राग्दृश्यं पश्यति स्वकीयस्य प्रयोक्तृ-सीएसएस् इत्येतस्य'''\n'''इदं अधुनावधि यावत् रक्षितं नास्ति!'''",
-    "userjspreview": "'''मनसि धारयतु यद्भवान् केवलं स्वकीयस्य जावास्क्रिप्ट्लिपेः परीक्षणं प्राग्दर्शनं वा करोति।'''\n'''इदं अधुनावधि यावत् रक्षितं नास्ति!'''",
-    "sitecsspreview": "'''मनसि धारयतु यद्भवान् स्वकीयस्य सीएस्एस्-इत्येतस्य केवलं प्राग्दृश्यं पश्यति।'''\n'''इदं अधुनावधि यावत् रक्षितं नास्ति!'''",
-    "sitejspreview": "'''मनसि धारयतु यद्भवान् स्वकीयस्य जावास्क्रिप्ट्कूटस्य केवलं प्राग्दृश्यं पश्यति।'''\n'''इदं अधुनावधि यावत् रक्षितं नास्ति!'''",
-    "userinvalidcssjstitle": "'''पà¥\82रà¥\8dवसà¥\82à¤\9aना:'''  \"$1\" à¤\87ति à¤¤à¥\8dवà¤\95à¥\8d à¤¨ à¤µà¤¿à¤¦à¥\8dयतà¥\87।\nमनसि à¤§à¤¾à¤°à¤¯à¤¤à¥\81 à¤¯à¤¤à¥\8d à¤¸à¥\8dवà¥\87à¤\9aà¥\8dà¤\9bया à¤ªà¤°à¤¿à¤µà¤°à¥\8dतिताà¤\83 .css, .js à¤\9aà¥\87ति à¤ªà¥\83षà¥\8dठाà¤\83 à¤²à¤\98à¥\82नà¤\95à¥\8dषरानà¥\8d à¤ªà¥\8dरयà¥\8bà¤\9cयनà¥\8dति, à¤¯à¤¥à¤¾  {{ns:user}}:Foo/Vector.css à¤\87तà¥\8dयà¥\87तसà¥\8dय à¤¸à¥\8dथानà¥\87  {{ns:user}}:Foo/vector.css à¤\87तà¥\8dयà¥\87ततà¥\8d।",
-    "updated": "(à¤\85दà¥\8dयतनà¥\80à¤\95à¥\83तà¤\83)",
+    "clearyourcache": "<strong>सूचना :</strong> भवता/भवत्या कृतानि सम्पादनानि संरक्ष्य तानि परिवर्तनेषु द्रष्टुं गवेषकस्य पृष्ठस्य पुनरारोपणम् (reload) आवश्यकं भवति ।\n* <strong>Firefox / Safari:</strong> <em>Shift</em>कुड्मलेन सह <em>Reload</em>कुड्मलं नुदतु । \n* <strong>Google Chrome:</strong> <em>Ctrl-Shift-R</em> नोदनेन पुनरारोपणं भवति । (<em>⌘-R</em> इति Mac तन्त्रांशप्रयोक्तॄभ्यः)\n* <strong>Internet Explorer:</strong> <em>Ctrl</em>कुड्मलेन सह <em>Refresh</em>कुड्मलं नुदतु, <em>Ctrl-F5</em> नुदतु वा ।\n* <strong>Opera:</strong> <em>Tools → Preferences</em> इत्यत्र गत्वा कर्तुं शक्नोति ।",
+    "usercssyoucanpreview": "'''सूचना :''' CSS नवीनलिप्याः संरक्षणं करणात् प्राक् एतत् \"{{int:showpreview}}\" नुद्य प्रयोगं करोतु ।",
+    "userjsyoucanpreview": "'''सूचना :''' JavaScript नवीनलिप्याः संरक्षणं करणात् प्राक् एतत् \"{{int:showpreview}}\" नुद्य प्रयोगं करोतु ।",
+    "usercsspreview": "<strong>एतत् केवलं योजकस्य CSS इत्यस्य प्राग्दृश्यं वर्तते इति स्मरतु । भवता/भवत्या कृतानि परिवर्तनानि एतवता न रक्षितानि !</strong>",
+    "userjspreview": "<strong>एतत् केवलं योजकस्य JabaScript इत्यस्य प्राग्दृश्यं वर्तते इति स्मरतु । भवता/भवत्या कृतानि परिवर्तनानि एतवता न रक्षितानि !</strong>",
+    "sitecsspreview": "<strong>एतत् केवलं CSS इत्यस्य प्राग्दृश्यं वर्तते इति स्मरतु । भवता/भवत्या कृतानि परिवर्तनानि एतवता न रक्षितानि !</strong>",
+    "sitejspreview": "<strong>एतत् केवलं JavaScript इत्यस्य प्राग्दृश्यं वर्तते इति स्मरतु । भवता/भवत्या कृतानि परिवर्तनानि एतवता न रक्षितानि !</strong>",
+    "userinvalidcssjstitle": "'''पà¥\82रà¥\8dवसà¥\82à¤\9aना:'''  \"$1\" à¤\87ति à¤¤à¥\8dवà¤\95à¥\8d à¤¨ à¤µà¤¿à¤¦à¥\8dयतà¥\87।\nयà¥\8bà¤\9cà¤\95परिवरà¥\8dतितà¥\87 .css, .js à¤¸à¤\9eà¥\8dà¤\9aिà¤\95à¥\87 à¤²à¤\98à¥\81-à¤\86à¤\99à¥\8dà¤\97ावरà¥\8dणमालायाà¤\83 à¤µà¤°à¥\8dणà¥\88à¤\83 à¤²à¤¿à¤\96à¥\8dयà¥\87तà¥\87 à¥¤ à¤\89दा. {{ns:user}}:Foo/Vector.css à¤\8fवà¤\82 à¤¨ à¤²à¥\87à¤\96नà¥\80यमà¥\8d à¥¤ à¤²à¤\98à¥\81वरà¥\8dणà¥\88à¤\83 {{ns:user}}:Foo/vector.css à¤\8fवà¤\82 à¤²à¥\87à¤\96नà¥\80यमà¥\8d ।",
+    "updated": "(नवà¥\80à¤\95à¥\83तमà¥\8d (updated))",
     "note": "'''सूचना:'''",
-    "previewnote": "'''एतत् केवलं प्राग्दृश्यं वर्तते इति स्मरतु'''\nभवता/भवत्या कृतानि परिवर्तनानि एतवता न रक्षितानि ।",
-    "continue-editing": "समà¥\8dपादनमà¥\8d à¤\85नà¥\81वरà¥\8dतताम्",
-    "previewconflict": "à¤\85सà¥\8dमिनà¥\8d à¤ªà¥\8dराà¤\97à¥\8dदà¥\83शà¥\8dयà¥\87 à¤¦à¤°à¥\8dशितमसà¥\8dति à¤¯à¤¤à¥\8d à¤\89परिवरà¥\8dति à¤ªà¤¾à¤  à¤\95à¥\8dषà¥\87तà¥\8dरसà¥\8dय à¤ªà¤¾à¤ à¤\83 à¤°à¤\95à¥\8dषणपशà¥\8dà¤\9aातà¥\8d à¤\95à¥\80दà¥\83शà¤\83 à¤¦à¥\83षà¥\8dà¤\9fिà¤\97à¥\8bà¤\9aरà¤\83 à¤­à¤µà¤¿à¤·à¥\8dयति।",
-    "session_fail_preview": "'''क्षम्यताम्! अस्माभिः भवतः सम्पादनस्य संसाधनं न कर्तुं शक्तम् यस्माद्धि सत्रस्य सूचनाः लुप्ताः।'''\nकृपया पुनः चेष्टताम्।\nचेदेतत् अधुनाऽपि न कार्यशीलं स्यात्, [[Special:UserLogout|सत्राद्बहिः गत्वा]] पुनः प्रवेशं करोतु।",
-    "session_fail_preview_html": "लेखभागाभावात् ते परिचर्यां समापयितुं न शक्यते ।[[Special:UserLogout|logging out]]",
-    "token_suffix_mismatch": "'''तà¥\87 à¤¸à¤®à¥\8dपादनà¤\82 à¤¤à¤¿à¤°à¥\8dसà¥\8dà¤\95à¥\83तमà¥\8d à¥¤ à¤¯à¤¤à¤\83 à¤¤à¥\87 à¤\97à¥\8dराहà¤\95à¤\83 à¤¸à¤®à¥\8dपादनपà¥\8dरतà¥\80à¤\95à¥\87 à¤²à¥\87à¤\96ानà¤\9aिहà¥\8dनानि à¤\95à¥\8dषतविà¤\95à¥\8dषतानि à¤\85à¤\95रà¥\8bतà¥\8d। '''\nपाठà¥\8dयपà¥\81à¤\9fसà¥\8dय à¤¸à¤\82रà¤\95à¥\8dषणारà¥\8dथà¤\82 à¤¸à¤®à¥\8dपादनावà¤\95ाशà¤\83 à¤ªà¤¿à¤¹à¤¿à¤¤à¤\83 à¥¤ à¤\85नामिà¤\95ानामà¥\8d à¤\89पयà¥\8bà¤\97à¤\95ालà¥\87 à¤\95दाà¤\9aितà¥\8d à¤\8fवà¤\82 à¤¸à¤®à¥\8dभवति ।",
-    "edit_form_incomplete": "'''समà¥\8dपादनसà¥\8dय à¤\95तिà¤\9aनाà¤\82शाà¤\83 à¤µà¤¿à¤¤à¤¾à¤°à¤\95à¤\82 à¤¨ à¤ªà¥\8dरापà¥\8dताà¤\83 ; à¤¸à¤®à¥\8dपादनà¤\82  à¤¦à¥\8dविवरà¤\82 à¤ªà¤°à¤¿à¤¶à¥\80लयतà¥\81 à¥¤ à¤¤à¥\87 à¤¸à¤®à¥\8dपादनानि à¤\85नाहतानि, à¤ªà¥\81नà¤\83 à¤¯à¤¤à¤¤à¤¾à¤®à¥\8d  '''",
+    "previewnote": "<strong>एतत् केवलं प्राग्दृश्यं वर्तते इति स्मरतु । भवता/भवत्या कृतानि परिवर्तनानि एतवता न रक्षितानि !</strong>",
+    "continue-editing": "समà¥\8dपादनविभाà¤\97à¤\82 à¤\97मà¥\8dयताम्",
+    "previewconflict": "à¤\8fततà¥\8d à¤ªà¥\83षà¥\8dठà¤\82 à¤¯à¤¦à¤¿ à¤­à¤µà¤¾à¤¨à¥\8d/भवतà¥\80 à¤°à¤\95à¥\8dषिषà¥\8dयति, à¤¤à¤°à¥\8dहि à¤\85तà¥\8dर à¤ªà¥\8dराà¤\97à¥\8dदà¥\83शà¥\8dयà¥\87 à¤¯à¤¥à¤¾ à¤¦à¥\83शà¥\8dयतà¥\87, à¤¤à¤¥à¥\88व à¤°à¤\95à¥\8dषितà¤\82 à¤­à¤µà¤¿à¤·à¥\8dयति ।",
+    "session_fail_preview": "'''क्षम्यताम् ! प्रवेशसूचनायाः लोपत्वात् भवता/भवत्या कृतानि परिवर्तनानि रक्षितुं वयं न अशक्नुम ।\nअधुनापि यदि सा एव समस्या अस्ति, तर्हि [[Special:UserLogout|निर्गमनं कृत्वा]] पुनः प्रविश्यताम् ।",
+    "session_fail_preview_html": "'''क्षम्यताम् ! प्रवेशसूचनायाः लोपत्वात् भवता/भवत्या कृतानि परिवर्तनानि रक्षितुं वयं न अशक्नुम ।\n\n<em>कारणं {{SITENAME}} इत्यत्र मूल-HTML-समर्थितं भवति । अतः JavaScript इत्यस्मात् रक्षितुं प्राग्दृश्यं निगूढं भवति ।</em>\n\n<strong>भवता/भवत्या कृतं सम्पादनं यदि उचितमस्ति, तर्हि पुनः प्रयासं करोतु ।</strong>\n\nअधुनापि यदि सा एव समस्या अस्ति, तर्हि [[Special:UserLogout|निर्गमनं कृत्वा]] पुनः प्रविश्यताम् ।",
+    "token_suffix_mismatch": "'''भवता/भवतà¥\8dया à¤\95à¥\83तानि à¤ªà¤°à¤¿à¤µà¤°à¥\8dतनानि à¤¨à¤¿à¤°à¤¸à¥\8dतानि à¤\95à¥\83तानि à¥¤ à¤\95राणà¤\82 à¤­à¤µà¤¤à¤\83/भवतà¥\8dयाà¤\83 à¤\97वà¥\87षà¤\95à¥\87न (browser) à¤¸à¤®à¥\8dपादनà¥\87 à¤\95ानिà¤\9aन à¤µà¤¿à¤°à¤¾à¤®à¤\9aिहà¥\8dनानि à¤\85सà¥\8dतवà¥\8dयसà¥\8dतà¤\95à¥\83तानि à¥¤'''\nलà¥\87à¤\96सà¥\8dय à¤ªà¤¾à¤ à¤\83 à¤\85सà¤\82सà¥\8dà¤\95à¥\83तà¤\83 à¤¨ à¤¸à¥\8dयातà¥\8d, à¤\85तà¤\83 à¤­à¤µà¤¤à¤\83/भवतà¥\8dयाà¤\83 à¤ªà¤°à¤¿à¤µà¤°à¥\8dतनानि à¤¨à¤¿à¤°à¤¸à¥\8dतà¥\80à¤\95à¥\83तानि à¥¤\nà¤\85यà¥\8bà¤\97à¥\8dयपà¥\8dरतिनिधà¥\87à¤\83 (proxy server) à¤\89पयà¥\8bà¤\97à¥\87नापि à¤\95à¥\81तà¥\8dरà¤\9aितà¥\8d à¤\8fतादà¥\83शà¤\82 भवति ।",
+    "edit_form_incomplete": "'''समà¥\8dपादनसà¥\8dय à¤\95तिà¤\9aनाà¤\82शाà¤\83 à¤µà¤¿à¤¤à¤°à¤\95à¥\87 (server) à¤¨ à¤°à¤\95à¥\8dषिताà¤\83 à¥¤ à¤­à¤µà¤¤à¤¾/भवतà¥\8dया à¤\95à¥\83तानि à¤¸à¤®à¥\8dपादनानि à¤¯à¥\8bà¤\97à¥\8dयानि à¤\9aà¥\87तà¥\8d à¤ªà¥\81नà¤\83 à¤ªà¥\8dरयततामà¥\8d à¥¤'''",
     "editing": "$1 सम्पाद्यते",
-    "creating": "$1 à¤¸à¤°à¥\8dà¤\9cनमà¥\8d",
-    "editingsection": "$1 (विभाà¤\97सà¥\8dय) à¤¸à¤®à¥\8dपादनà¤\82 à¤\95à¥\81रà¥\8dवनà¥\8d à¤\85सà¥\8dति",
-    "editingcomment": "$1 संपादनम् (विभागः)",
-    "editconflict": "सम्पादनयोः/सम्पादनानाम् अन्तर्विरोधः : $1",
-    "explainconflict": "तà¥\87 à¤¸à¤®à¥\8dपादनावसरà¥\87 à¤\95à¥\8bपि à¤\85नà¥\8dयà¤\83 à¤ªà¤°à¤¿à¤µà¤°à¥\8dतितवानà¥\8d à¥¤ à¤\89परितनलà¥\87à¤\96सà¥\8dय à¤\95à¥\8dषà¥\87तà¥\8dरà¤\82 à¤¸à¤¦à¥\8dयà¤\83 à¤µà¤¿à¤¦à¥\8dयमानपà¥\81à¤\9fयà¥\81à¤\95à¥\8dतमसà¥\8dति à¥¤ à¤¤à¥\87 à¤ªà¤°à¤¿à¤µà¤°à¥\8dतनमà¥\8d à¤\85धà¤\83 à¤²à¥\87à¤\96à¤\95à¥\8dषà¥\87तà¥\8dरà¥\87 à¤¦à¥\83शà¥\8dयतà¥\87 à¥¤ à¤µà¤¿à¤¦à¥\8dयमानलà¥\87à¤\96à¥\88à¤\83 à¤¸à¤¹ à¤¤à¥\87 à¤ªà¤°à¤¿à¤µà¤°à¥\8dताननि à¤µà¤¿à¤²à¥\80नयतà¥\81 à¥¤ à¤¯à¤¦à¤¾ à¤¸à¤\82रà¤\95à¥\8dषणपà¥\8dरयतà¥\8dनà¤\83 à¤\95à¥\8dरियतà¥\87 à¤¤à¤¦à¤¾ à¤\95à¥\87वलमà¥\8d à¤\89परिपठà¥\8dयभाà¤\97à¤\83 à¤\8fव à¤¸à¥\81रà¤\95à¥\8dषितà¤\82 à¤­à¤µति ।",
-    "yourtext": "भवतः पाठः",
-    "storedversion": "रà¤\95à¥\8dषिता à¤\86वà¥\83तà¥\8dतिà¤\83",
-    "nonunicodebrowser": "'''पूर्वसूचना: भवतः विचरकं यूनीकोड्-अनुकूलम् नास्ति।'''\nभवान् सुरक्षिततया सम्पादनं करोतु इत्येतदर्थं एका युक्तिः कृताऽस्ति: आस्की-इतराणि अक्षराणि सम्पादनपिटके षौडशिक(hexadecimal) कूटेषु द्रक्ष्यन्ते।",
-    "editingold": "''' पूर्वसूचना : कालातीतपुटस्य सम्पादनं करोति  ''' यदि एतत् रक्षितुं यतते परिवर्तनं नैव रक्ष्यते ।",
+    "creating": "$1 à¤¸à¥\83à¤\9cà¥\8dयतà¥\87",
+    "editingsection": "$1 (विभाà¤\97à¤\83) à¤¸à¤®à¥\8dपादà¥\8dयतà¥\87",
+    "editingcomment": "$1 (नवीनविभागः) सम्पाद्यते",
+    "editconflict": "सम्पादनयोः अन्तर्विरोधः : $1",
+    "explainconflict": "भवता/भवतà¥\8dया à¤¯à¤¦à¤¾ à¤¸à¤®à¥\8dपादनà¤\82 à¤ªà¥\8dरारबà¥\8dधà¤\82, à¤¤à¤¦à¤¾à¤°à¤­à¥\8dय à¤\85नà¥\8dयà¤\9cनà¤\83 à¤\85पि à¤\85तà¥\8dर à¤¸à¤®à¥\8dपादनà¤\82 à¤\95à¥\81रà¥\8dवनà¥\8d à¤\86सà¥\80तà¥\8d à¥¤\nà¤\85धà¥\81ना à¤¯à¤¥à¤¾ à¤¸à¥\8dथितिà¤\83 à¤\85सà¥\8dति, à¤¤à¤¥à¤¾ à¤\89परि à¤ªà¥\87à¤\9fिà¤\95ायाà¤\82 à¤¦à¥\8dरषà¥\8dà¤\9fà¥\81à¤\82 à¤¶à¤\95à¥\8dयतà¥\87 à¥¤\nà¤\85धà¤\83 à¤ªà¥\87à¤\9fिà¤\95ायाà¤\82 à¤­à¤µà¤¤à¤¾/भवतà¥\8dया à¤\95à¥\83तानि à¤ªà¤°à¤¿à¤µà¤°à¥\8dतनानि à¤ªà¥\8dरदरà¥\8dशितानि à¤¸à¤¨à¥\8dति à¥¤ \nà¤\85धà¥\81ना à¤ªà¥\83षà¥\8dठà¥\87 à¤¯à¤¤à¥\8d à¤²à¤¿à¤\96ितà¤\82 à¤µà¤°à¥\8dततà¥\87, à¤¤à¥\87न à¤¸à¤¹ à¤¸à¥\8dवसà¥\8dय à¤ªà¤°à¤¿à¤µà¤°à¥\8dतनानि à¤¯à¥\8bà¤\9cनà¥\80यानि à¤­à¤µà¤¿à¤·à¥\8dयति à¥¤ \nभवानà¥\8d/भवतà¥\80 à¤¯à¤¦à¤¾ \" à¤\8fततà¥\8d {{int:savearticle}}\" à¤¨à¥\81दति, à¤¤à¤¦à¤¾\n<strong>à¤\95à¥\87वलà¤\82</strong> à¤\89परिसà¥\8dतनपà¥\87à¤\9fिà¤\95ायाà¤\82 à¤¯à¤¤à¥\8d à¤²à¤¿à¤\96ितमà¥\8d à¤\85सà¥\8dति, à¤¤à¤¤à¥\8d à¤°à¤\95à¥\8dषितà¤\82 à¤­à¤µà¤¿à¤·à¥\8dयति ।",
+    "yourtext": "भवतः/भवत्याः पाठः",
+    "storedversion": "रà¤\95à¥\8dषितसà¤\82सà¥\8dà¤\95रणमà¥\8d",
+    "nonunicodebrowser": "<strong>पूर्वसूचना : भवतः/भवत्याः गवेषकं (browser) Unicode न समर्थयति ।</strong>\nअत्र भवान्/भवती योग्यरीत्या सम्पादनं कर्तुं शक्ष्यति :\nये वर्णाः ASCII कूटे न भविष्यन्ति, ते hexadecimal वर्णत्वेन प्रदर्शयन्ते ।",
+    "editingold": "<strong>पूर्वसूचना : भवता/भवत्या अस्य पृष्ठस्य कालातीत-आवृत्तिं समाद्यते । </strong>\nएतत् पृष्ठं यदि भवान्/भवती रक्षिष्यति, तर्हि सद्यः आवृत्ति-तः पुरा यानि परिवर्तनानि आसन्, तानि नशिष्यन्ति ।",
     "yourdiff": "भेदाः",
-    "copyrightwarning": "à¤\95à¥\83पया à¤¸à¤\82सà¥\8dमरà¥\8dतवà¥\8dयà¤\82 à¤¯à¤¤à¥\8d {{SITENAME}} à¤\87तà¥\8dयà¥\87तदà¥\8d à¤ªà¥\8dरति à¤\95à¥\83तानि à¤¸à¤°à¥\8dवाणि à¤¯à¥\8bà¤\97दानानि $2 à¤\87तà¥\8dयसà¥\8dय à¤ªà¥\8dरतिबà¤\82धाà¤\82तरà¥\8dà¤\97तानि à¤¸à¤¨à¥\8dति (à¤\85धिà¤\95ाय à¤\9cà¥\8dà¤\9eानाय $1 à¤\87तà¥\8dयà¥\87तदà¥\8d à¤ªà¤¶à¥\8dयतà¥\81)।\n\nयदि à¤­à¤µà¤¾à¤¨à¥\8d à¤¸à¥\8dवà¤\95à¥\80यानि à¤²à¤¿à¤\96ितानि à¤ªà¤°à¤¿à¤µà¤°à¥\8dतमनà¥\8dतशà¥\8dà¤\9a, à¤ªà¥\81नà¤\83 à¤µà¤¿à¤¤à¤°à¥\8dयमनà¥\8dतशà¥\8dà¤\9a à¤¨ à¤¦à¥\8dरषà¥\8dà¤\9fà¥\81मिà¤\9aà¥\8dà¤\9bति à¤¤à¤¦à¤¾ à¤®à¤¾ à¤\95à¥\83पया à¤®à¤¾à¤½à¤¤à¥\8dर à¤¯à¥\8bà¤\97दानà¤\82 à¤\95रà¥\8bतà¥\81। <br />\n\nभवानà¥\8d à¤\8fतदपि à¤ªà¥\8dरमाणà¥\80à¤\95रà¥\8bति à¤¯à¤¤à¥\8d à¤\8fतदà¥\8d à¤­à¤µà¤¤à¤¾ à¤¸à¥\8dवतà¤\83 à¤²à¤¿à¤\96ितमसà¥\8dति à¤\85थवा à¤\95सà¥\8dमाà¤\9aà¥\8dà¤\9aतà¥\8d à¤\9cनारà¥\8dपितातà¥\8d à¤µà¤¾ à¤®à¥\81à¤\95à¥\8dतातà¥\8d à¤µà¤¾ à¤¸à¥\8dरà¥\8bतसà¤\83 à¤ªà¥\8dरतिलिपà¥\80à¤\95à¥\83तमसà¥\8dति।\n\n'''पà¥\8dरतिलिपà¥\8dयधिà¤\95ारयà¥\81तानà¥\8d à¤²à¥\87à¤\96ानà¥\8d, à¤\85नà¥\81à¤\9cà¥\8dà¤\9eाà¤\82 à¤µà¤¿à¤¨à¤¾, à¤®à¤¾à¤½à¤¤à¥\8dर à¤ªà¥\8dरददातà¥\81!'''",
-    "copyrightwarning2": "à¤\95à¥\83पया à¤¸à¤\82सà¥\8dमरà¥\8dतवà¥\8dयà¤\82 à¤¯à¤¤à¥\8d {{SITENAME}} à¤\87तà¥\8dयà¥\87तदà¥\8d à¤ªà¥\8dरति à¤\95à¥\83तानि à¤¸à¤°à¥\8dवाणि à¤¯à¥\8bà¤\97दानानि  à¤\87तà¥\8dयसà¥\8dय à¤ªà¥\8dरतिबà¤\82धाà¤\82तरà¥\8dà¤\97तानि à¤¸à¤¨à¥\8dति (à¤\85धिà¤\95ाय à¤\9cà¥\8dà¤\9eानाय $1 à¤\87तà¥\8dयà¥\87तदà¥\8d à¤ªà¤¶à¥\8dयतà¥\81)।\n\nयदि à¤­à¤µà¤¾à¤¨à¥\8d à¤¸à¥\8dवà¤\95à¥\80यानि à¤²à¤¿à¤\96ितानि à¤ªà¤°à¤¿à¤µà¤°à¥\8dतमनà¥\8dतशà¥\8dà¤\9a, à¤ªà¥\81नà¤\83 à¤µà¤¿à¤¤à¤°à¥\8dयमनà¥\8dतशà¥\8dà¤\9a à¤¨ à¤¦à¥\8dरषà¥\8dà¤\9fà¥\81मिà¤\9aà¥\8dà¤\9bति à¤¤à¤¦à¤¾ à¤®à¤¾ à¤\95à¥\83पया à¤®à¤¾à¤½à¤¤à¥\8dर à¤¯à¥\8bà¤\97दानà¤\82 à¤\95रà¥\8bतà¥\81। <br />\n\nभवानà¥\8d à¤\8fतदपि à¤ªà¥\8dरमाणà¥\80à¤\95रà¥\8bति à¤¯à¤¤à¥\8d à¤\8fतदà¥\8d à¤­à¤µà¤¤à¤¾ à¤¸à¥\8dवतà¤\83 à¤²à¤¿à¤\96ितमसà¥\8dति à¤\85थवा à¤\95सà¥\8dमाà¤\9aà¥\8dà¤\9aतà¥\8d à¤\9cनारà¥\8dपितातà¥\8d à¤µà¤¾ à¤®à¥\81à¤\95à¥\8dतातà¥\8d à¤µà¤¾ à¤¸à¥\8dरà¥\8bतसà¤\83 à¤ªà¥\8dरतिलिपà¥\80à¤\95à¥\83तमसà¥\8dति।\n\n'''पà¥\8dरतिलिपà¥\8dयधिà¤\95ारयà¥\81तानà¥\8d à¤²à¥\87à¤\96ानà¥\8d, à¤\85नà¥\81à¤\9cà¥\8dà¤\9eाà¤\82 à¤µà¤¿à¤¨à¤¾, à¤®à¤¾à¤½à¤¤à¥\8dर à¤ªà¥\8dरददातà¥\81!'''",
-    "longpageerror": "रुटिः: भवता प्रदत्तः पाठः {{PLURAL:}} $1 किलोबैटमितः दीर्घः, अतः एषः अधिकतमानुज्ञातात् $2 मितात् दीर्घतरः अस्ति। एषः रक्षितुं न शक्यते।'''",
-    "readonlywarning": "पूर्वसूचना ''' निर्वहणार्थं पाठः पिहितः । अधुना भवान् सम्पादनं रक्षितुं नैव शक्नोति । पाठसञ्चिकायां संश्लेष्य कार्यफलं रक्षतु । एतद्विवरणं प्रतिबन्धकः प्रशासकः विरतरि ।$1",
-    "protectedpagewarning": "'''पूर्वसूचना ''' प्रशासकपदयुक्ताः योजकाः एव सम्पादनं कर्तुमर्हन्ति । अतः एतत्पुटं सुरक्षितम् । निदेशार्थम् अधः जघन्यप्रवेशः सूचितः ।",
-    "semiprotectedpagewarning": "'''सà¥\82à¤\9aना ''' à¤ªà¤\9eà¥\8dà¤\9cà¥\80à¤\95à¥\83तयà¥\8bà¤\9cà¤\95ानाà¤\82  à¤\89पयà¥\8bà¤\97ारà¥\8dथ à¤\95à¥\87वलमà¥\8d à¤\8fततà¥\8dपà¥\81à¤\9fमà¥\8d à¤\85भिरà¤\95à¥\8dषितमà¥\8d à¥¤ à¤\9cà¤\98नà¥\8dयपà¥\8dरवà¥\87शसà¥\8dय à¤¸à¥\82à¤\9aना à¤\86नà¥\81à¤\95à¥\82लà¥\8dयारà¥\8dथमà¥\8d à¤\85धà¥\8bनिदà¥\87शिता à¥¤",
-    "cascadeprotectedwarning": "'''पूर्वसूचना ''' प्रशासकसौकर्ययुक्तानां योजकानाम् सम्पादनार्थम् एतत् पुटम् अभिरक्षितमस्ति । यतः अधोनिदेशितनिर्झरे एतदन्तर्गतम् । {{PLURAL:$1|page|pages}}:",
-    "titleprotectedwarning": "'''पूर्वसूचना  [[Special:ListGroupRights|specific rights]] जनानां सर्जनार्थम् एतत्पुटम् अभिरक्षितम् । '''",
+    "copyrightwarning": "à¤\95à¥\83पया à¤§à¥\8dयानà¤\82 à¤¦à¤¦à¤¾à¤¤à¥\81 à¤¯à¤¤à¥\8d, {{SITENAME}} à¤\87तà¥\8dयतà¥\8dर à¤\95à¥\83तानि à¤¸à¤°à¥\8dवाणि à¤¯à¥\8bà¤\97दानानि $2 à¤\87तà¥\8dयसà¥\8dय à¤¨à¤¿à¤¯à¤¨à¤¾à¤¨à¥\81सारà¤\82 à¤­à¤µà¤¿à¤·à¥\8dयनà¥\8dति à¥¤ (विसà¥\8dतारà¥\87ण à¤\9cà¥\8dà¤\9eातà¥\81à¤\82 $1 à¤\85तà¥\8dर à¤¨à¥\81दतà¥\81)\nभवानà¥\8d/भवतà¥\80 à¤¸à¥\8dवसà¥\8dय à¤¯à¥\8bà¤\97दानà¥\87षà¥\81 à¤ªà¤°à¤¿à¤µà¤°à¥\8dतन-पà¥\81नरà¥\8dनिरà¥\8dदà¥\87शन-à¤\86दिनि à¤ªà¤°à¤¿à¤µà¤°à¥\8dतनानि à¤¦à¥\8dरषà¥\8dà¤\9fà¥\81à¤\82 à¤¨ à¤¶à¤\95à¥\8dनà¥\8bति à¤\9aà¥\87तà¥\8d, à¤\85तà¥\8dर à¤¯à¥\8bà¤\97दानà¤\82 à¤®à¤¾ à¤\95रà¥\8bतà¥\81 à¥¤ (à¤\85तà¥\8dर à¤¤à¥\81 à¤²à¤¿à¤\96ितà¥\87 à¤¨à¤¿à¤°à¤¨à¥\8dतरà¤\82 à¤ªà¤¿à¤°à¤µà¤°à¥\8dतनà¤\82 à¤­à¤µà¤¤à¥\8dयà¥\87व à¤\87ति à¤­à¤¾à¤µà¤\83)\n<br />\n\nà¤\85सà¥\8dमभà¥\8dयà¤\82 à¤­à¤µà¤¤à¤¾/भवतà¥\8dया à¤ªà¥\8dरतिà¤\9cà¥\8dà¤\9eा à¤\95रà¥\8dतवà¥\8dया à¤¯à¤¤à¥\8d, \"à¤\85तà¥\8dर à¤¯à¤¤à¥\8dà¤\95िमपि à¤­à¤µà¤¾à¤¨à¥\8d/भवतà¥\80 à¤²à¥\87à¤\96िषà¥\8dयति, à¤¤à¤¤à¥\8d à¤¸à¤°à¥\8dवà¤\82 à¤¸à¥\8dवरà¤\9aितà¤\82, à¤¸à¤¾à¤°à¥\8dवà¤\9cनà¥\80à¤\95à¤\82 à¤\9a à¤­à¤µà¤¿à¤·à¥\8dयति à¥¤ à¤\95à¥\81तसà¥\8dमातà¥\8d à¤¸à¥\8dथानातà¥\8d à¤ªà¥\8dरतिलिपिà¤\95à¥\83तमà¥\8d à¤\85पि à¤¸à¤¾à¤°à¥\8dवà¤\9cनà¥\80à¤\95मà¥\87व à¤¸à¥\8dयातà¥\8d\" à¤\87ति à¥¤ \n<strong>à¤\85नà¥\8dयसà¥\8dय à¤¸à¤°à¥\8dवाधिà¤\95ारानà¥\8dतरà¥\8dà¤\97तà¤\82 (copyright) à¤¯à¤¤à¥\8d à¤­à¤µà¤¤à¤¿, à¤¤à¤¤à¥\8d à¤µà¤¿à¤¨à¤¾ à¤\85नà¥\81मतà¥\8dया à¤\85तà¥\8dर à¤²à¤¿à¤\96तà¥\81à¤\82 à¤¨ à¤¶à¤\95à¥\8dयतà¥\87 à¥¤</strong>",
+    "copyrightwarning2": "à¤\95à¥\83पया à¤§à¥\8dयानà¤\82 à¤¦à¤¦à¤¾à¤¤à¥\81 à¤¯à¤¤à¥\8d, {{SITENAME}} à¤\87तà¥\8dयतà¥\8dर à¤\95à¥\83तानि à¤¸à¤°à¥\8dवाणि à¤¯à¥\8bà¤\97दानानि à¤\85नà¥\8dययà¥\8bà¤\9cà¤\95à¥\88à¤\83 à¤¸à¤®à¥\8dपादयितà¥\81à¤\82, à¤ªà¤°à¤¿à¤°à¥\8dवतितà¥\81à¤\82, à¤¨à¤¿à¤·à¥\8dà¤\95ाशयितà¥\81à¤\82 à¤\9a à¤¶à¤\95à¥\8dयनà¥\8dतà¥\87 à¥¤ \nभवानà¥\8d/भवतà¥\80 à¤¸à¥\8dवसà¥\8dय à¤¯à¥\8bà¤\97दानà¥\87षà¥\81 à¤ªà¤°à¤¿à¤µà¤°à¥\8dतन-पà¥\81नरà¥\8dनिरà¥\8dदà¥\87शन-à¤\86दिनि à¤ªà¤°à¤¿à¤µà¤°à¥\8dतनानि à¤¦à¥\8dरषà¥\8dà¤\9fà¥\81à¤\82 à¤¨ à¤¶à¤\95à¥\8dनà¥\8bति à¤\9aà¥\87तà¥\8d, à¤\85तà¥\8dर à¤¯à¥\8bà¤\97दानà¤\82 à¤®à¤¾ à¤\95रà¥\8bतà¥\81 à¥¤ (à¤\85तà¥\8dर à¤¤à¥\81 à¤²à¤¿à¤\96ितà¥\87 à¤¨à¤¿à¤°à¤¨à¥\8dतरà¤\82 à¤ªà¤¿à¤°à¤µà¤°à¥\8dतनà¤\82 à¤­à¤µà¤¤à¥\8dयà¥\87व à¤\87ति à¤­à¤¾à¤µà¤\83)\n<br />\n\nà¤\85सà¥\8dमभà¥\8dयà¤\82 à¤­à¤µà¤¤à¤¾/भवतà¥\8dया à¤ªà¥\8dरतिà¤\9cà¥\8dà¤\9eा à¤\95रà¥\8dतवà¥\8dया à¤¯à¤¤à¥\8d, \"à¤\85तà¥\8dर à¤¯à¤¤à¥\8dà¤\95िमपि à¤­à¤µà¤¾à¤¨à¥\8d/भवतà¥\80 à¤²à¥\87à¤\96िषà¥\8dयति, à¤¤à¤¤à¥\8d à¤¸à¤°à¥\8dवà¤\82 à¤¸à¥\8dवरà¤\9aितà¤\82, à¤¸à¤¾à¤°à¥\8dवà¤\9cनà¥\80à¤\95à¤\82 à¤\9a à¤­à¤µà¤¿à¤·à¥\8dयति à¥¤ à¤\95à¥\81तसà¥\8dमातà¥\8d à¤¸à¥\8dथानातà¥\8d à¤ªà¥\8dरतिलिपिà¤\95à¥\83तमà¥\8d à¤\85पि à¤¸à¤¾à¤°à¥\8dवà¤\9cनà¥\80à¤\95मà¥\87व à¤¸à¥\8dयातà¥\8d\" à¤\87ति à¥¤ \n<strong>à¤\85नà¥\8dयसà¥\8dय à¤¸à¤°à¥\8dवाधिà¤\95ारानà¥\8dतरà¥\8dà¤\97तà¤\82 (copyright) à¤¯à¤¤à¥\8d à¤­à¤µà¤¤à¤¿, à¤¤à¤¤à¥\8d à¤µà¤¿à¤¨à¤¾ à¤\85नà¥\81मतà¥\8dया à¤\85तà¥\8dर à¤²à¤¿à¤\96तà¥\81à¤\82 à¤¨ à¤¶à¤\95à¥\8dयतà¥\87 à¥¤</strong>",
+    "longpageerror": "<strong>दोषः : भवता/भवत्या लिखितः पाठः  {{PLURAL:$1|सहाष्टकं|$1 सहाष्टकानि}} दीर्घः अस्ति । एषः पाठः बृह्त्तमसीमया अपेक्षया {{PLURAL:$2|सहाष्टकं|$2 सहाष्टकानि}} दीर्घः अस्ति ।(सहस्राष्टकानि (kilobytes) इत्यस्य सङ्क्षेपः सहाष्टकम्)</strong>\nएतत् रक्षितुं न शक्यते ।",
+    "readonlywarning": "<strong>पूर्वसूचना : दत्तांशः (database) किलितः अस्ति । अतः अधुना भवान्/भवती स्वस्य सम्पादनं रक्षितुं न शक्नोति ।</strong>\nस्वस्य परिवर्तितस्य लेखस्य .txt .doc वा सञ्चिकां निर्माय किञ्चित् कालानन्तरं रक्षतु । \nदत्तांश-किलनस्य कारणं प्रबन्धकेन दत्तं यत्, : $1",
+    "protectedpagewarning": "'''पूर्वसूचना : पृष्ठमेतत् संरक्षितं वर्तते । अतः केवलं प्रबन्धकाः अत्र सम्पादनं कर्तुं शक्नुवन्ति ।'''\n\nसद्यःकालीना संरक्षितावलिः (log) अधः दत्ता अस्ति :",
+    "semiprotectedpagewarning": "'''पà¥\82रà¥\8dवसà¥\82à¤\9aना : à¤ªà¥\83षà¥\8dठमà¥\87ततà¥\8d à¤¸à¤\82रà¤\95à¥\8dषितà¤\82 à¤µà¤°à¥\8dततà¥\87 à¥¤ à¤\85तà¤\83 à¤\95à¥\87वलà¤\82 à¤ªà¤\9eà¥\8dà¤\9cिà¤\95à¥\83तयà¥\8bà¤\9cà¤\95ाà¤\83 à¤\85तà¥\8dर à¤¸à¤®à¥\8dपादनà¤\82 à¤\95रà¥\8dतà¥\81à¤\82 à¤¶à¤\95à¥\8dनà¥\81वनà¥\8dति à¥¤'''\n\nसदà¥\8dयà¤\83à¤\95ालà¥\80ना à¤¸à¤\82रà¤\95à¥\8dषितावलिà¤\83 (log) à¤\85धà¤\83 à¤¦à¤¤à¥\8dता à¤\85सà¥\8dति :",
+    "cascadeprotectedwarning": "'''पूर्वसूचना :''' पृष्ठमेतत् संरक्षितं वर्तते । अतः केवलं प्रबन्धकाः अत्र सम्पादनं कर्तुं शक्नुवन्ति ।\nनिम्ननियमान्तर्गतम् एतत्{{PLURAL:$1|पृष्ठं रक्षितं|पृष्ठानि रक्षितानि}}:",
+    "titleprotectedwarning": "'''पूर्वसूचना : एतत् पृष्ठं संरक्षितम् अस्ति । अतः अस्य सम्पादनं कर्तुं [[Special:ListGroupRights|विशेषाधिकारः]] अपेक्ष्यते ।'''\nसद्यःकालीना संरक्षितावलिः (log) अधः दत्ता अस्ति :",
     "templatesused": "अस्मिन् पृष्ठे प्रयुक्त{{PLURAL:$1|फलकम्|फलकानि}}:",
-    "templatesusedpreview": "अस्मिन् प्राग्दृश्ये प्रयुक्ताः {{PLURAL:$1|बिंबधराः |बिंबधराः}}:",
-    "templatesusedsection": "{{PLURAL:$1|Template|Templates}} अस्मिन् विभागे उपयुक्तम् ।",
+    "templatesusedpreview": "अस्मिन् प्राग्दृश्ये प्रयुक्त{{PLURAL:$1|फलकम्|फलकानि}}:",
+    "templatesusedsection": "अस्मिन् विभागे प्रयुक्त{{PLURAL:$1|फलकम्|फलकानि}}:",
     "template-protected": "(संरक्षितम्)",
     "template-semiprotected": "अर्धसंरक्षितम्",
     "hiddencategories": "इदं पृष्ठं {{PLURAL:$1|1 निगूढे वर्गे |$1 निगूढेषु वर्गेषु}} अन्तर्भवति :",
-    "nocreatetext": "{{SITENAME}} à¤¨à¥\82तनपà¥\81à¤\9fनिरà¥\8dमाणसà¥\8dय à¤\95à¥\8dषमता à¤¨à¤¿à¤¯à¤¤à¤¾ à¥¤ à¤µà¤°à¥\8dतमानापà¥\81à¤\9fानाà¤\82 à¤¸à¤®à¥\8dपादनारà¥\8dथà¤\82 à¤¨à¤¿à¤°à¥\8dà¤\97à¤\9aà¥\8dà¤\9bतà¥\81 à¥¤ à¤\85थवा [[Special:UserLogin|log in or create an account]].",
-    "nocreate-loggedin": "नà¥\82तनपà¥\81à¤\9fनिरà¥\8dमारà¥\8dथम् अनुमतिः नास्ति ।",
-    "sectioneditnotsupported-title": "विभाà¤\97समà¥\8dपादनà¤\82 à¤¨ à¤ªà¥\8bषितमà¥\8d à¥¤",
-    "sectioneditnotsupported-text": "à¤\85सà¥\8dमिनà¥\8d à¤ªà¥\81à¤\9fà¥\87 à¤µà¤¿à¤­à¤¾à¤\97समà¥\8dपादनणà¥\8d à¤¨ à¤ªà¥\8bषितमà¥\8d ।",
-    "permissionserrors": "à¤\85नà¥\81à¤\9cà¥\8dà¤\9eा-विभà¥\8dरमाः",
-    "permissionserrorstext": "भवानà¥\8d à¤¤à¤¤à¥\8d à¤\95रà¥\8dतà¥\81à¤\82 à¤\85नà¥\81à¤\9cà¥\8dà¤\9eाà¤\82 à¤¨ à¤§à¤¾à¤°à¤¯à¤¤à¤¿ {{PLURAL:$1|à¤\85धà¥\8bऽà¤\99à¥\8dà¤\95ितातà¥\8d à¤\95ारणातà¥\8d |à¤\85धà¥\8bऽà¤\99à¥\8dà¤\95ितà¥\87भà¥\8dयà¤\83 à¤\95ारणà¥\87भà¥\8dयà¤\83:}}",
+    "nocreatetext": "{{SITENAME}} à¤\9cालसà¥\8dथानà¥\87ऽसà¥\8dमिनà¥\8d à¤¨à¤µà¥\80नपà¥\83षà¥\8dठनिरà¥\8dमातà¥\81मà¥\8d à¤\85नà¥\81मतिà¤\83 à¤¨ à¤µà¤¿à¤¦à¥\8dयतà¥\87 à¥¤\nभवानà¥\8d/भवतà¥\80 à¤ªà¥\8dरतिà¤\97तà¥\8dवा à¤µà¤¿à¤¦à¥\8dयमानà¤\82 à¤ªà¥\83षà¥\8dठà¤\82 à¤¸à¤®à¥\8dपादयतà¥\81 à¤¶à¤\95à¥\8dनà¥\8bति à¥¤  à¤¸à¤®à¥\8dपादयितà¥\81à¤\82 [[Special:UserLogin|पà¥\8dरविशà¥\8dयतामà¥\8d à¤¸à¤¦à¤¸à¥\8dयता à¤ªà¥\8dरापà¥\8dयतामà¥\8d à¤µà¤¾]].",
+    "nocreate-loggedin": "भवतà¤\83/भवतà¥\8dयाà¤\83 à¤ªà¤¾à¤°à¥\8dशà¥\8dवà¥\87 à¤¨à¤µà¥\80नपà¥\83षà¥\8dठà¤\82 à¤°à¤\9aितà¥\81म् अनुमतिः नास्ति ।",
+    "sectioneditnotsupported-title": "विभाà¤\97सà¥\8dय à¤¸à¤®à¥\8dपादनà¤\82 à¤¶à¤\95à¥\8dयà¤\82 à¤¨à¤¾à¤¸à¥\8dति",
+    "sectioneditnotsupported-text": "पà¥\83षà¥\8dठà¥\87ऽसà¥\8dमिनà¥\8d à¤µà¤¿à¤­à¤¾à¤\97समà¥\8dपादनà¤\82 à¤¶à¤\95à¥\8dयà¤\82 à¤¨à¤¾à¤¸à¥\8dति ।",
+    "permissionserrors": "à¤\85नà¥\81मतिदà¥\8bषः",
+    "permissionserrorstext": "à¤\8fततà¥\8d à¤\95रà¥\8dतà¥\81à¤\82 à¤­à¤µà¤¤à¤\83/भवतà¥\8dयाà¤\83 à¤ªà¤¾à¤°à¥\8dशà¥\8dवà¥\87 à¤\85नà¥\81मति à¤¨à¤¾à¤¸à¥\8dति, à¤¨à¤¿à¤®à¥\8dन{{PLURAL:$1|à¤\95ारणमà¥\8d|à¤\95ारणानि}}:",
     "permissionserrorstext-withaction": "$1 निम्नकारणत्वात्  $2 सम्पादनस्य अनुमतिः नास्ति ।\n{{PLURAL:$1|कारणम्|कारणानि}}:",
-    "recreate-moveddeleted-warn": "'''पूर्वसूचना: पूर्वम् अपाकृतं पृष्टं भवता रच्यमानम् अस्ति ।'''\nअस्य पृष्ठस्य सम्पादनं करणात् प्राक् गभीरतया चिन्तनं करोतु ।\nअस्य पृष्ठस्य निर्माणं न्यायसङ्गतम् इति भवतः/भवत्याः मतमस्ति चेत् अत्र परिवर्तनं करोतु । सौकर्यार्थं पृष्ठ-अपाकरणस्य प्राक्तनसम्पादनस्य आवलिः अत्र वर्तते ।",
+    "recreate-moveddeleted-warn": "'''पूर्वसूचना: पूर्वम् अपाकृतं पृष्टं भवता रच्यमानम् अस्ति ।'''\nअस्य पृष्ठस्य सम्पादनं करणात् प्राक् गभीरतया चिन्तनं करोतु ।\nअस्य पृष्ठस्य निर्माणं न्यायसङ्गतम् इति भवतः/भवत्याः मतमस्ति चेत्, अत्र परिवर्तनं करोतु । सौकर्यार्थं पृष्ठ-अपाकरणस्य प्राक्तनसम्पादनस्य आवलिः अत्र दीयते ।",
     "moveddeleted-notice": "इदं पृष्ठम् अपाकृतम् अस्ति।\nअस्य अपाकरणस्य, स्थानान्तरणस्य च विवरणम् अधः प्रदत्तम् ।",
-    "log-fulllog": "पूर्ण प्रवर्तनरेख पश्यतु",
-    "edit-hook-aborted": "पाशेन (हुक् इत्यनेन) सम्पादनं परित्यक्तम्।\nअनेन न किमपि कारणं प्रदत्तम्।",
-    "edit-gone-missing": "पà¥\83षà¥\8dठà¤\82 à¤ªà¤°à¤¿à¤µà¤°à¥\8dतितà¥\81à¤\82 à¤¨à¤¾à¤ªà¤¾à¤°à¤¯à¤¤à¥\8d।\nपà¥\8dरतà¥\80यतà¥\87 à¤¯à¤¦à¤¿à¤¦à¤\82 à¤\85पाà¤\95à¥\83तमसà¥\8dति।",
-    "edit-conflict": "सम्पादनयोः/सम्पादनानां अन्तर्विरोधः।",
-    "edit-no-change": "भवतà¤\83 à¤¸à¤®à¥\8dपादनमà¥\8d à¤\89पà¥\87à¤\95à¥\8dषितमà¥\8d, à¤¯à¤¤à¥\8b à¤¹à¤¿ à¤­à¤µà¤¤à¤¾ à¤ªà¤¾à¤ à¥\87 à¤¨ à¤\95िमपि à¤ªà¤°à¤¿à¤µà¤°à¥\8dतनà¤\82 à¤\95à¥\83तमà¥\8d।",
+    "log-fulllog": "पूर्णसंरक्षितावलिं दृश्यताम्",
+    "edit-hook-aborted": "hook द्वारा सम्पादनक्रिया मध्ये एव स्थगिता । स्थगनस्य कारणं न दत्तम् ।",
+    "edit-gone-missing": "à¤\85सà¥\8dमिनà¥\8d à¤ªà¥\83षà¥\8dठà¥\87 à¤ªà¤°à¤¿à¤µà¤°à¥\8dतनà¤\82 à¤¨à¤¾à¤­à¥\82तà¥\8d à¥¤\nà¤\8fततà¥\8d à¤ªà¥\83षà¥\8dठà¤\82 à¤ªà¥\81रा à¤\8fव à¤\95à¥\87नापि à¤\85पाà¤\95à¥\83तमà¥\8d à¤\87ति à¤­à¤¾à¤¤à¤¿ ।",
+    "edit-conflict": "सम्पादनयोः अन्तर्विरोधः ।",
+    "edit-no-change": "भवता/भवतà¥\8dया à¤\95à¥\83तà¤\82 à¤¸à¤®à¥\8dपादमà¥\8d à¤\85वà¤\97णितमà¥\8d à¥¤ à¤\95ारणà¤\82 à¤²à¥\87à¤\96à¥\87 à¤¨ à¤\95िमपि à¤ªà¤°à¤¿à¤µà¤°à¥\8dतनà¤\82 à¤\9cातमसà¥\8dति ।",
     "postedit-confirmation": "सम्पादनं रक्षितम् ।",
-    "edit-already-exists": "नूतनं पृष्ठं स्रष्टुं नापारयत्।\nइदं पूर्वे एव विद्यते।",
-    "defaultmessagetext": "सन्देशपाठं स्थिरयतु ।",
-    "invalid-content-data": "अमान्यः सामग्रीदत्तांशः",
-    "content-not-allowed-here": "[[$2]] इति पृष्ठे \"$1\" सामग्री अनुमता नास्ति।",
-    "editwarning-warning": "अस्मात् पृष्ठात् गमनेन अत्र भवता कृतानि परिवर्तनानि निष्फलानि भवेयुः ।\nभवता यदि प्रविष्टं तर्हि मम इष्टतमानि इत्यत्र अस्मिन् विभागे सम्पादनेन एषः प्रबोधः यथा न आगच्छेत् तथा कर्तुं शक्यते ।",
+    "edit-already-exists": "नूतनपृष्ठस्य निर्माणं नाभूत् ।\nपूर्वस्मादेव एतत् पृष्ठं विद्यते ।",
+    "defaultmessagetext": "मूलसन्देशः",
+    "content-failed-to-parse": "$1 कृते $2 इत्यस्य विभाजनं विफलम् अभवत् । दोषः : $3",
+    "invalid-content-data": "अयोग्यः लेखः",
+    "content-not-allowed-here": "[[$2]] पृष्ठे \"$1\" सामग्री अनुमता नास्ति",
+    "editwarning-warning": "एतत् पृष्ठं त्यक्तवा यदि गमिष्यति, तर्हि भवता/भवत्या कृतस्य सम्पादनस्य रक्षणं न भविष्यति ।\n\nभवता/भवत्या यदि प्रवेशः प्राप्तः अस्ति, तर्हि एषा सूचना अत्र \"{{int:prefs-editing}}\" निगूढितुं शक्यते ।",
+    "editpage-notsupportedcontentformat-title": "लेखस्य प्रारूपम् अयोग्यम्",
+    "editpage-notsupportedcontentformat-text": "लेखस्य सामग्र्याः $1 इति प्रारूपं $2 सामग्री-उदाहरणानुगुणं नास्ति ।",
     "content-model-wikitext": "विकिपाठः",
     "content-model-text": "शुद्धपाठः",
     "content-model-javascript": "जावालिपिः",
     "content-model-css": "सी-एस्-एस्",
-    "expensive-parserfunction-warning": "'''प्रबोधः :''' अस्मिन् पृष्ठे प्रभूतानि जटिलानि पार्सर्-फ़ंक्शन्-आह्वानानि सन्ति।\nअत्र $2 संख्यातः  {{PLURAL:$2|न्यूनं आह्वानं|न्यूनानि आह्वानानि}} भवितव्यानि, सद्यः तत्र {{PLURAL:$1 $1 आह्वानं विद्यते|$1 आह्वानानि विद्यन्ते}}।",
-    "expensive-parserfunction-category": "पà¥\8dरभà¥\82तà¥\87भà¥\8dयà¤\83 à¤\9cà¤\9fिलà¥\87भà¥\8dयà¤\83 à¤ªà¤¾à¤°à¥\8dसरà¥\8d-फà¤\82à¤\95à¥\8dशनà¥\8d-à¤\86हà¥\8dवानà¥\87भà¥\8dयà¤\83 à¤¯à¥\81à¤\95à¥\8dतानि à¤ªà¥\83षà¥\8dठाणि।",
+    "expensive-parserfunction-warning": "<strong>पूर्वसूचना :</strong> अस्मिन् पृष्ठे बहवः विभाजिताः नियोजिताः (functions) विद्यन्ते ।\n\nअत्र न्यूनातिन्यूनं $2 {{PLURAL:$2|आह्वानं|आह्वानानि}} शक्यते । तत्र {{PLURAL:$1|अधुना $1 आह्वाहनं|अधिना $1 आह्वाहनानि}}",
+    "expensive-parserfunction-category": "à¤\85सà¥\8dमिनà¥\8d à¤ªà¥\83षà¥\8dठà¥\87 à¤¬à¤¹à¤µà¤\83 à¤µà¤¿à¤­à¤¾à¤\9cिताà¤\83 à¤¨à¤¿à¤¯à¥\8bà¤\9cिताà¤\83 (functions) à¤µà¤¿à¤¦à¥\8dयनà¥\8dतà¥\87 ।",
     "post-expand-template-inclusion-warning": "'''पूर्वसूचना:''' फलकस्य आकारः बृहत् वर्तते । कानिचन फलकानि नान्तर्भविष्यन्ति ।",
     "post-expand-template-inclusion-category": "सूचनाफलकस्य अपेक्षया पृष्ठं बृहत् वर्तते ।",
     "post-expand-template-argument-warning": "'''पूर्वसूचना''' अस्मिन् पृष्ठे स्थितस्य फलकस्य एकः विकल्पः बहु बृहत् वर्तते । तस्य विकल्पस्य अंशाः अपाकृताः ।",
     "post-expand-template-argument-category": "येषु पृष्ठेषु फलके स्थिताः विकल्पाः न पूरिताः तेषां पृष्ठानाम् आवलिः",
-    "parser-template-loop-warning": "बिमà¥\8dबधर-पाशà¤\83 à¤ªà¥\8dरापà¥\8dतà¤\83: [[$1]]",
-    "parser-template-recursion-depth-warning": "बिमà¥\8dबधर-पà¥\81नरावरà¥\8dतनारà¥\8dथà¤\82 à¤\97हनतायाà¤\83 à¤¸à¥\80मा à¤\85तिà¤\95à¥\8dरानà¥\8dताऽसà¥\8dति ($1)",
-    "language-converter-depth-warning": "भाषा-परिवरà¥\8dतà¤\95सà¥\8dय à¤\97हनतायाà¤\83 à¤¸à¥\80मा à¤\85तिà¤\95à¥\8dरानà¥\8dताऽसà¥\8dति (*$1)",
-    "node-count-exceeded-category": "सनà¥\8dधिà¤\97णनमà¥\8d à¤\85तिà¤\95à¥\8dरानà¥\8dतपà¥\81à¤\9fानि à¥¤",
-    "node-count-exceeded-warning": "सनà¥\8dधिà¤\97णनà¥\87न à¤¤à¤¿à¤\95à¥\8dरानà¥\8dतपà¥\81à¤\9fमà¥\8d à¥¤",
-    "expansion-depth-exceeded-category": "पà¥\81à¤\9fविसà¥\8dतारसà¥\8dय à¤\97ाहà¤\83 à¤\85तिà¤\95à¥\8dरानà¥\8dतà¤\83 à¥¤",
-    "expansion-depth-exceeded-warning": "विसà¥\8dतारà¤\97ाहातिà¤\95à¥\8dरानà¥\8dतपà¥\81à¤\9fमà¥\8d à¥¤",
-    "parser-unstrip-loop-warning": "अपट्टरन्धः दृष्टः ।",
-    "parser-unstrip-recursion-limit": "अपट्टपुनरवतरणमितिः अतिक्रान्ता ।$1",
+    "parser-template-loop-warning": "फलà¤\95सà¥\8dय à¤ªà¤°à¤¿à¤\95à¥\8dरमà¤\83 (loop) à¤ªà¥\8dरापà¥\8dतà¤\83 : [[$1]]",
+    "parser-template-recursion-depth-warning": "फलà¤\95-पà¥\8dरतà¥\8dयावरà¥\8dतनसà¥\8dय (recursion) à¤¸à¥\80मा à¤¸à¤®à¤¾à¤ªà¥\8dता ($1)",
+    "language-converter-depth-warning": "भाषा-परिवरà¥\8dतà¤\95सà¥\8dय à¤¸à¥\80मा à¤¸à¤®à¤¾à¤ªà¥\8dता ($1)",
+    "node-count-exceeded-category": "यà¥\87षà¥\81 à¤¸à¤¨à¥\8dधà¥\87à¤\83 (node) à¤¸à¥\80मा à¤¸à¤®à¤¾à¤ªà¥\8dता, à¤¤à¥\87षाà¤\82 à¤ªà¥\83षà¥\8dठानामà¥\8d à¤\86वलिà¤\83",
+    "node-count-exceeded-warning": "पà¥\83षà¥\8dठà¥\87ऽसà¥\8dमिनà¥\8d à¤¸à¤¨à¥\8dधà¥\87à¤\83 (node) à¤¸à¥\80मा à¤¸à¤®à¤¾à¤ªà¥\8dता",
+    "expansion-depth-exceeded-category": "यà¥\87षà¥\81 à¤µà¤¿à¤¸à¥\8dतारसà¥\80मा à¤¸à¤®à¤¾à¤ªà¥\8dता, à¤¤à¥\87षाà¤\82 à¤ªà¥\83षà¥\8dठानामà¥\8d à¤\86वलिà¤\83",
+    "expansion-depth-exceeded-warning": "पà¥\83षà¥\8dठà¥\87ऽसà¥\8dमिनà¥\8d à¤µà¤¿à¤¸à¥\8dतारसà¥\80मा à¤¸à¤®à¤¾à¤ªà¥\8dता",
+    "parser-unstrip-loop-warning": "Unstrap परिक्रमः (loop) प्राप्तः",
+    "parser-unstrip-recursion-limit": "Unstrip इत्यस्य प्रत्यावर्तनस्य (recursion) सीमा समाप्ता ($1)",
     "converter-manual-rule-error": "मानवीये भाषापरिवर्तने दोषः दृष्टः ।",
-    "undo-success": "सम्पादनमिदं विपरीतीकर्तुं शक्यते।\nकृपया अधस्तात् तुलनां दृष्ट्वा निश्चितीकरोतु यत् भवान् एवमेव कर्तुमिच्छति। तदा भवान् विपरीतीकर्तुं निम्नांकितानि परिवर्तनानि रक्षतु।",
-    "undo-failure": "सम्पादनम् अकर्तुं न पारयत् यस्मात् मध्ये परस्परविरोधीनि सम्पादनानि अभवन्।",
-    "undo-norev": "इदं सम्पादनं अकर्तुं न पारयत् यस्मात् एतत् न विद्यते अथवा अपाकृतस्ति।",
-    "undo-summary": " [[Special:Contributions/$2|$2]] ([[User talk:$2|talk]]) इत्यनेन कृताम् $1 इति आवृत्तिम् अकरोतु",
-    "cantcreateaccounttitle": "लेखा स्रष्टुं न शक्यते",
-    "cantcreateaccount-text": "('''$1''') इति आइपिसंकेतात् लेखासृजनम् [[User:$3|$3]] इत्यनेन अवरुद्धीकृतः अस्ति।\nएतदर्थं $3 इत्यनेन प्रदत्तं कारणम्''$2'' इत्यस्ति।",
+    "undo-success": "एतत् सम्पादनं पूर्ववत् कर्तुं शक्यते ।\nकृपया अधः दत्तयोः तुलनां कृत्वा यत् आवश्यकं, तत् संरक्षतु । ततः पूर्ववत्-करणप्रक्रिया समाप्तं भविष्यति ।",
+    "undo-failure": "सम्पादनं पूर्ववत् कर्तुं न शक्यते । कारणं मध्ये परस्परविपरितानि सम्पादनानि अभवन् ।",
+    "undo-norev": "सम्पादनमिदं पूर्ववत् कर्तुं न शक्यते । कारणं सम्पादनम् पूर्वमेव अपाकृतं अथवा न विद्यते ।",
+    "undo-nochange": "पूर्वमेव एतत् सम्पादनं पूर्ववत् कृतं स्यात् ।",
+    "undo-summary": "[[Special:Contributions/$2|$2]] ([[User talk:$2|talk]]) द्वारा कृता  $1 पूर्ववत्-प्रक्रिया निरस्तीक्रियताम् ।",
+    "undo-summary-username-hidden": "निगूढितयोजकद्वारा कृता  $1 पूर्ववत्-प्रक्रिया निरस्तीक्रियताम् ।",
+    "cantcreateaccounttitle": "सदस्यता प्राप्तुं न शक्यते",
+    "cantcreateaccount-text": "(<strong>$1</strong>) इत्यस्य संविदः (IP) कृते सदस्यता प्राप्तुं न शक्यते । कारणं [[User:$3|$3]] द्वारा सा संवित्सङ्ख्या प्रतिबन्धिता अस्ति । \n\n$3 इत्यनेन कारणं दत्तं यत्, <em>$2</em>",
+    "cantcreateaccount-range-text": "सदस्यताप्राप्तेः सीमा-आक्रान्तासु '''$1''' अन्तर्जालसंवित्सु (IP) भवतः/भवत्याः अन्तर्जालसंवद् ('''$4''') अन्तर्भवति । अतः [[User:$3|$3]] द्वारा भवतः/भवत्याः अन्तर्जालसंविद् प्रतिबन्धिता ।\n\n$3 इत्यनेन कारणं दत्तं यत्, ''$2''",
     "viewpagelogs": "अस्य पृष्ठस्य संरक्षितावलिः (logs) दृश्यताम्",
-    "nohistory": "à¤\85सà¥\8dय à¤ªà¥\83षà¥\8dठसà¥\8dय à¤\95à¥\83तà¥\87 à¤ªà¥\83षà¥\8dठà¥\87तिहासà¤\83 à¤¨ à¤µà¤°à¥\8dततà¥\87।",
-    "currentrev": "सदà¥\8dयà¤\83à¤\95ालà¥\80ना आवृत्तिः",
+    "nohistory": "à¤\85सà¥\8dय à¤ªà¥\83षà¥\8dठसà¥\8dय à¤\87तिहासà¤\83 à¤¨ à¤µà¤°à¥\8dततà¥\87 ।",
+    "currentrev": "नà¥\82तनतमा आवृत्तिः",
     "currentrev-asof": "$1 समयस्य संस्करणम्",
     "revisionasof": "$1 इत्यस्य संस्करणं",
     "revision-info": "$1 पर्यन्तं $2 द्वारा जातानां परिवर्तनानाम् आवलिः",
     "last": "पूर्वतनम्",
     "page_first": "प्रथमम्",
     "page_last": "अन्तिमम्",
-    "histlegend": "भेदस्य चयनम्: आवृत्तिभेदस्य दर्शनाय अग्रे प्रदत्ता रेडियोमञ्जूषा नुद्यताम्, एण्टर्-कुड्मलं नुद्यताम्, अधः दत्तं कुड्मलं वा नुद्यताम् । <br />\nनूतनसंस्करणम् = नूतनासु आवृत्तिषु भेदः, \n(पूर्वतनम्) = पूर्वतनासु आवृत्तिषु भेदः, (लघु) = लघु सम्पादनम्",
-    "history-fieldset-title": "अन्वेषणस्य (browse) इतिहासः",
+    "histlegend": "भेदस्य चयनम् : आवृत्तिभेदस्य दर्शनाय अग्रे प्रदत्ता रेडियो-मञ्जूषा नुद्यताम्, एण्टर्-कुड्मलं नुद्यताम्, अधः दत्तं कुड्मलं वा नुद्यताम् । <br />\nनूतनसंस्करणम् = नूतनासु आवृत्तिषु भेदः, \n(पूर्वतनम्) = पूर्वतनासु आवृत्तिषु भेदः, (लघु) = लघु सम्पादनम्",
+    "history-fieldset-title": "अन्वेषणस्य इतिहासः",
     "history-show-deleted": "केवलम् अपाकृतम्",
     "histfirst": "पुरातनतमम्",
     "histlast": "नूतनतमम्",
-    "historysize": "({{PLURAL:$1|1 à¤¬à¥\88à¤\9fमà¥\8d|$1 à¤¬à¥\88à¤\9fानि}})",
+    "historysize": "({{PLURAL:$1|1 à¤\85षà¥\8dà¤\9fà¤\95à¤\82|$1 à¤\85षà¥\8dà¤\9fà¤\95ानि}})",
     "historyempty": "(रिक्तम्)",
-    "history-feed-title": "à¤\86वरà¥\8dतनà¥\87तिहासà¤\83",
-    "history-feed-description": "विà¤\95à¥\8dयामà¥\8d à¤\85सà¥\8dय à¤ªà¥\83षà¥\8dठसà¥\8dय à¤\86वरà¥\8dतनेतिहासः",
+    "history-feed-title": "सà¤\82सà¥\8dà¤\95रणसà¥\8dय à¤\87तिहासà¤\83",
+    "history-feed-description": "à¤\85सà¥\8dमिनà¥\8d à¤µà¤¿à¤\95ि-à¤\9cालसà¥\8dथानà¥\87 à¤¤à¤¸à¥\8dमà¥\88 à¤ªà¥\83षà¥\8dठाय à¤¸à¤\82सà¥\8dà¤\95रणेतिहासः",
     "history-feed-item-nocomment": "$1 द्वारा $3 दिनाङ्के $4 समये",
-    "history-feed-empty": "याà¤\9aितà¤\82 à¤ªà¥\83षà¥\8dठà¤\82 à¤¨ à¤µà¤¿à¤¦à¥\8dयतà¥\87।\nà¤\87दà¤\82 à¤µà¤¿à¤\95ितà¤\83 à¤\85पाà¤\95à¥\83तमà¥\8d à¤\85थवा à¤ªà¥\81नरà¥\8dनामितà¤\82 à¤¸à¥\8dयातà¥\8d।\nसमà¥\8dबनà¥\8dधितानि à¤¨à¥\82तनानि à¤ªà¥\83षà¥\8dठाणि à¤¸à¤®à¥\8dपà¥\8dरापà¥\8dतà¥\81à¤\82 [[Special:Search|विà¤\95à¥\8dयामà¥\8d à¤\85नà¥\8dवà¥\87षणà¤\82]] à¤\95रà¥\8bतà¥\81।",
+    "history-feed-empty": "à¤\8fततà¥\8d à¤ªà¥\83षà¥\8dठà¤\82 à¤¨ à¤µà¤¿à¤¦à¥\8dयतà¥\87 à¥¤ \nà¤\8fतसà¥\8dय à¤ªà¥\83षà¥\8dठसà¥\8dय à¤¨à¤¾à¤®à¤ªà¤°à¤¿à¤µà¤°à¥\8dतनमà¥\8d, à¤\85पाà¤\95रणà¤\82 à¤\9a à¤\95à¥\83तà¤\82 à¤¸à¥\8dयातà¥\8d à¥¤ \n à¤\85नà¥\87न à¤¸à¤®à¥\8dबदà¥\8dधानि à¤ªà¥\83षà¥\8dठानि [[Special:Search|विà¤\95ि-à¤\9cालसà¥\8dथानà¥\87 à¤\85नà¥\8dविषà¥\8dयतामà¥\8d]] ।",
     "rev-deleted-comment": "(सम्पादनस्य सारः अपाकृतमस्ति)",
     "rev-deleted-user": "(प्रयोक्तृनाम अपाकृतमस्ति)",
     "rev-deleted-event": "(अभिलेखन-क्रिया अपाकृताऽस्ति)",
     "prefs-skin": "त्वक्",
     "skin-preview": "प्राग्दृश्यम्",
     "datedefault": "वरीयांसि नास्ति",
-    "prefs-beta": "आवर्णलक्षणानि ।",
     "prefs-datetime": "दिनाङ्कः, समयः च",
     "prefs-labs": "प्रयोगशालालक्षणानि ।",
     "prefs-user-pages": "योजकपुटानि ।",
     "upload-permitted": "अनुमतसञ्चिकाभेदाः $1.",
     "upload-preferred": "अनुमतसञ्चिकाभेदाः $1.",
     "upload-prohibited": "अनुमतसञ्चिकाभेदाः $1.",
-    "uploadlog": "उत्तरणस्य सूची ।",
     "uploadlogpage": "उपारोहिताऽऽवलिः (Upload log)",
     "uploadlogpagetext": "अधः सद्यः काले उत्तारितसञ्चिकानाम् आवली अस्ति ।\nअधिकदृश्यविवरणार्थम् एतत् पश्यतु [[Special:NewFiles|gallery of new files]]",
     "filename": "सञ्चिकानाम",
     "filereuploadsummary": "सञ्चिकापरिवर्तनानि ।",
     "filestatus": "प्रतिकृत्यधिकारस्य स्थितिः ।",
     "filesource": "मूल:",
-    "uploadedfiles": "आरोपिताः सञ्चिकाः",
     "ignorewarning": "पूर्वसूचनां निर्लक्ष्य सञ्चिकाः कथञ्चित् संरक्षतु ।",
     "ignorewarnings": "पूर्वसूचनाः निर्लक्षतु ।",
     "minlength1": "सञ्चिकानाम न्यूनतिन्यूनम् एकाक्षरं भवेत् ।",
     "overwroteimage": "\"[[$1]]\" इत्यस्य नूतनावतरणम् उत्तारयतु ।",
     "uploaddisabled": "सक्रियम् उत्तारयतु ।",
     "copyuploaddisabled": "निष्क्रियतः यु.आर्.एल् तः उत्तारयतु  ।",
-    "uploadfromurl-queued": "ते उत्तारणम् अनुपङ्कौ अस्ति ।",
     "uploaddisabledtext": "उत्तारितसञ्चिकाः निष्क्रियाः ।",
     "php-uploaddisabledtext": "PHP मध्ये उत्तारितसञ्चिकाः निष्क्रियाः ।",
     "uploadscripted": "HTMLयुक्ताः अथवा लिपिसङ्केतयुक्ताः सञ्चिकाः जालदर्शिकया बाधिताः ।",
     "upload-misc-error": "अज्ञातः उत्तारणदोषः ।",
     "upload-misc-error-text": "उत्तारणावसरे कश्चन अज्ञातदोषः उपगतः । \nURL मान्यम् अभिगम्यं वेति परिशील्य पुनः यतताम् ।[[Special:ListUsers/sysop|administrator]]",
     "upload-too-many-redirects": "URL अधिकपुनर्निदेशान् अन्तर्गतम् ।",
-    "upload-unknown-size": "अज्ञात आकार",
     "upload-http-error": "कश्चन HTTP दोषः उपगतः $1",
     "upload-copy-upload-invalid-domain": "अस्मिन् कोशे प्रतिकृत्युत्तारणम् उपलब्धं नास्ति ।",
     "backend-fail-stream": "सञ्चिका क्रमगता न $1.",
     "img-auth-streaming": "\"$1\"इत्यस्य प्रवाहिनी ।",
     "img-auth-public": "स्वायत्तविकितः सञ्चिकाः नेतुम् अयं कार्यक्रमः img_auth.php उपयुज्यते ।\nएषा विकिः सार्वजनिकविकिः इति  दृढिता । \nवैकल्पिकसुरक्षार्थं img_auth.php अपलपितः । ।",
     "img-auth-noread": "\"$1\"पठने योजकस्य अभिगमनं नास्ति ।",
-    "img-auth-bad-query-string": " URL मध्ये अमान्यं प्रश्नतन्तुः अस्ति ।",
     "http-invalid-url": " $1 इति अमान्यम् URL ।",
     "http-invalid-scheme": "\"$1\"योजनायुक्तं URLs नानुमोदितानि ।",
     "http-request-error": " अज्ञातदोषात् HTTP अभ्यर्थनं निष्पलम् ।",
     "filehist-dimensions": "आयामाः",
     "filehist-filesize": "सञ्चिकाकारः ।",
     "filehist-comment": "टिप्पणी",
-    "filehist-missing": "सञ्चिका विनष्टा ।",
     "imagelinks": "सञ्चिकायाः उपयोगः",
     "linkstoimage": "{{PLURAL:$1|अधो निर्दिष्टपृष्ठस्य परिसन्धयः संलग्नाः सन्ति|$1 अधो निर्दिष्टपृष्ठानां परिसन्धिः संलग्ना अस्ति}}:",
     "linkstoimage-more": "{{PLURAL:$1|$1}} तः अधिकपुटानि अस्यां सञ्चिकायां योज्यन्ते । \nअधोनिदेशितसूची सञ्चिकाभिः योजनीयपुटानि पश्यति ।{{PLURAL:$1|$1 पृष्ठ|$1 पृष्ठ}} \n[[Special:WhatLinksHere/$2|पूर्णसूची]] अपि लभ्यते ।",
     "booksources-invalid-isbn": "दत्तं ISBN मान्यम् इति  न भाति । मूलस्रोततः प्रतिकृतीः कर्तुं परिशीलयतु ।",
     "specialloguserlabel": "आचारी :",
     "speciallogtitlelabel": "लक्ष्यम् (शीर्षकम् / योजकः)",
-    "log": "सà¤\82सक्षितावल्यः (Logs)",
+    "log": "सà¤\82रक्षितावल्यः (Logs)",
     "all-logs-page": "सर्वसार्वजनिकप्रवेशः ।",
     "alllogstext": "{{SITENAME}}इत्यस्य उबलब्धप्रवेशानां  संयुक्तप्रदर्शनम् ।\nप्रवेशप्रकारं चित्वा भवान् दृश्यं क्षाययितुं शक्नोति । योजकनाम,  सदस्य नाम (ह्रस्वदीर्घाक्षरसंवादी) प्रभावितपुटम् ।",
     "logempty": "प्रवेशे मेलयुक्तपुटं नास्ति ।",
     "emailuser-title-notarget": "ईपत्र योजकः",
     "emailpage": "ई-मेल योजक",
     "emailpagetext": "अस्मै योजकाय विद्युन्मानपत्रं प्रेषयितुम् अधो दत्तप्रपत्रम् उपयोक्तुं शक्नोति । \n[[Special:Preferences|your user preferences]] अत्र भवता विनिवेशितः वि-पत्रसङ्केतः सकाशात् इति स्थाने प्रतिभाति । अनेन स्वीकर्ता साक्षात् प्रत्युत्तरं दातुं प्रभविष्यति ।",
-    "usermailererror": "पत्राचारपदार्थस्य प्रत्यागतदोषः ।",
     "defemailsubject": "{{SITENAME}}\"$1\" इति योजकात् विद्युन्मानपत्रम् ।",
     "usermaildisabled": "योजकस्य विद्युन्मानपत्रं निष्क्रियम् ।",
     "usermaildisabledtext": "अस्यां विक्याम् अन्ययोजकेभ्यः विद्युन्मानपत्रं प्रेषयितुं नै शक्नोति ।",
     "noemailtitle": "विद्युन्मानपत्रसङ्केतः नास्ति ।",
     "noemailtext": "अस्य योजकस्य निरिदिष्टः विद्युन्मानपत्रसङ्केतः नास्ति ।",
-    "nowikiemailtitle": "विद्युन्मानपत्रम् अननुमतम् ।",
     "nowikiemailtext": "अयं योजकः अन्ययोजकेभ्यः विद्युन्मानपत्राणि स्वीकार्तुं नेच्छति ।",
     "emailnotarget": "स्वीकर्तुः अस्तित्वविहीनम् अथवा अमान्यं योजकनाम  ।",
     "emailtarget": "स्वीकर्तुः योजकनाम लिखतु ।",
     "nowatchlist": "अवलोकनावल्यां पदार्थः नास्ति ।",
     "watchlistanontext": "अवलोकनपट्टिकायां पुटं दृष्टुं सम्पादयितुं वा  $1  करोतु ।",
     "watchnologin": "न नामाभिलितम्",
-    "watchnologintext": "अवलोकनावलीं परिवर्तयितुं भवता नामाभिलेखनं करणीयम् ।[[Special:UserLogin|logged in]]",
     "addwatch": "अवलोकनावलीं योजयतु ।",
     "addedwatchtext": "भवतः [[Special:Watchlist|ध्यानसूचिकायां]] \"[[:$1]]\" इत्येतत् योजितमस्ति।\nइदानींप्रभृति अस्मिन् पृष्ठे तथा अस्य चर्चापृष्ठे सन्तः परिवर्तनानि भवतः निरीक्षासूचिकायां द्रक्ष्यन्ते तथा च [[Special:RecentChanges|सद्यःपरिवर्तितानां सूचिकायां]] इदं पृष्ठं स्थूलाक्षरैः द्रक्ष्यते, यस्मात् भवान् सरलतया इदं पश्यतु <p>निरीक्षासूचिकातः निराकर्तुमिच्छति चेत्, \"मा निरीक्षताम्\" इत्यसमिन् नोदयतु।",
     "removewatch": "अवलोकनावलीतः अपनयतु ।",
     "watching": "निरीक्षते...",
     "unwatching": "निरीक्षाम् अपाकरोति...",
     "watcherrortext": " \"$1\" कृते अवलोकनावल्याः व्यवस्थापरिवर्तनावसरे दोषः संविधितः ।",
-    "enotif_mailer": "{{SITENAME}} सूचितः विद्युन्मानपत्रप्रेषकः ।",
     "enotif_reset": "सन्दर्शितानि इति सर्वपुटानि अङ्कयतु ।",
     "enotif_impersonal_salutation": "{{SITENAME}} योजक",
     "enotif_subject_deleted": "{{SITENAME}} पृष्ठं $1 इत्येतत् {{gender:$2 इत्यनेन|$2 इत्यनया}} अपाकृतमस्ति।",
     "excontent": "\"$1\" आधेयः आसीत् ।",
     "excontentauthor": "आधेयः $1आसीत् । अपि च योगदाता तु \"[[Special:Contributions/$2|$2]]\" आसीत् ।",
     "exbeforeblank": "रिक्तीकरणात् पूर्वम् आधेयः \"$1\" आसीत् ।",
-    "exblank": "पुटं रिक्तमासीत् ।",
     "delete-confirm": "विलुप्यताम् \"$1\"",
     "delete-legend": "विलुप्यताम्",
     "historywarning": "' पूर्वसूचना ''' भवता अपमर्जनसिद्धपुटे बहुशः  $1 इतिहासयुक्तः अस्ति ।{{PLURAL:$1|revision|revisions}}:",
     "importunknownsource": "अज्ञातायातस्रोतप्रकारः ।",
     "importcantopen": "आयातसञ्चिकाः उद्घाटयितुं न शक्यते ।",
     "importbadinterwiki": "प्रदुष्टः अन्तर्विक्यनुबन्धः ।",
-    "importnotext": "रिक्तम् अथवा पाठः नास्ति ।",
     "importsuccess": "आयातः समाप्तः ।",
-    "importhistoryconflict": "उपलब्धाः इतिहासपुनरावृत्तयः परस्परं विपरीताः। (एतत्पुटं पूर्वमेव आयातम् इति भाति ।)",
     "importnosources": "कोऽपि ट्रान्स्विकि आयातः नोपलब्धः अपि च प्रत्यक्षेतिहासस्य उत्तारणं निष्कियम् ।",
     "importnofile": "कापि आयातसञ्चिका उत्तारिता ।",
     "importuploaderrorsize": "आयातसञ्चिकाः अनुत्तारिताः। अस्याः आकारः अधिकतरः अस्ति ।",
index 29cc80c..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": "Кэтэбил тиһигиттэн сот",
index 6f37089..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",
index 7394b8c..606ab5e 100644 (file)
     "accountcreatedtext": "The uiser accoont fer [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|tauk]]) haes been cræftit.",
     "createaccount-title": "Accoont makin for {{SITENAME}}",
     "createaccount-text": "Somebodie cræftit aen accoont fer yer wab-mail address oan {{SITENAME}} ($4) named \"$2\", wi passwaird \"$3\".\nYe shid log in n chynge yer passwaird nou.\n\nYe can ignore this message, gif this accoont wis cræftit bi mistak.",
-    "usernamehasherror": "Uisername canna contain hash chairacters",
     "login-throttled": "Ye'v makit ower monie recynt login attempts.\nPlease wait $1 afore giein it anither gae.",
     "login-abort-generic": "Yer login wisna successful - Aborted",
     "loginlanguagelabel": "Leid: $1",
     "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",
     "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",
     "uploadlogpage": "Uplaid log",
     "uploadlogpagetext": "Ablo is a leet o the maist recent file uplaids.",
     "filedesc": "Ootline",
     "filereuploadsummary": "File chynges:",
     "filestatus": "Copyricht status:",
     "filesource": "Soorce:",
-    "uploadedfiles": "Uplaidit files",
     "ignorewarning": "Ignore warnishment n hain file oniewey.",
     "ignorewarnings": "Ignore ony warnins",
     "minlength1": "Filenames maun be at least yin letter.",
     "overwroteimage": "uplaided ae new version o \"[[$1]]\"",
     "uploaddisabled": "Sorry, uplaidin is disabled.",
     "copyuploaddisabled": "Uplaid bi URL disabled.",
-    "uploadfromurl-queued": "Yer uplaid haes been pit in line.",
     "uploaddisabledtext": "File uplaids ar disabled.",
     "php-uploaddisabledtext": "File uplaids ar disabled in PHP.\nPlease check the file_uploads settin.",
     "uploadscripted": "This file hauds HTML or script code that micht be wrang interpretit bi a wab brouser.",
     "upload-misc-error": "Onkent uplaid mistake",
     "upload-misc-error-text": "Aen onkent mistak occurred during the uplaid.\nPlease vereefie that the URL is valit n accessible n gie it anither gae.\nGif the proablem persists, contact aen [[Special:ListUsers/sysop|admeenistrater]].",
     "upload-too-many-redirects": "The URL contained oewr monie reguidals",
-    "upload-unknown-size": "Onkent size",
     "upload-http-error": "Aen HTTP mistake occurred: $1",
     "upload-copy-upload-invalid-domain": "Copie uplaids arna available fae this domain.",
     "backend-fail-stream": "Coudna stream file \"$1\".",
     "img-auth-streaming": "Streamin \"$1\".",
     "img-auth-public": "The function o img_auth.php is tae ootpit files fae ae preevate wiki.\nThis wiki is confeegured aes ae publeec wiki.\nFr optimal securitie, img_auth.php is disabled.",
     "img-auth-noread": "Uiser disna hae access tae read \"$1\".",
-    "img-auth-bad-query-string": "The URL haaes aen onvalid speirin string.",
     "http-invalid-url": "Onvalid URL: $1",
     "http-invalid-scheme": "URLs wi the \"$1\" preefix ar naw supported.",
     "http-request-error": "HTTP request failed cause o onkent mistak.",
     "filehist-user": "Uiser",
     "filehist-dimensions": "Dimensions",
     "filehist-comment": "Comment",
-    "filehist-missing": "File missin",
     "imagelinks": "File uisage",
     "linkstoimage": "The follaein {{PLURAL:$1|page airts|$1 pages airt}} tae this file:",
     "linkstoimage-more": "Mair than $1 {{PLURAL:$1|page airts|pages airt}} til this file.\nThe follaein leet shaws the {{PLURAL:$1|first page airtin|first $1 page airtins}} til this file yinlie.\nAe [[Special:WhatLinksHere/$2|ful leet]] is available.",
     "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.",
+    "noindex-category-desc": "The page haes ae <code><nowiki>__NOINDEX__</nowiki></code> 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 <code><nowiki>__INDEX__</nowiki></code> 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 <code>$wgMaxArticleSize</code>, sae some templates were na makit muckler.",
+    "post-expand-template-argument-category-desc": "Efter makin ae template argument muckler (sommit in triple braces, lik <code>{{{Foo}}})</code>, the page is muckler than <code>$wgMaxArticleSize</code>.",
     "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.",
+    "hidden-category-category-desc": "This is ae categerie wi <code><nowiki>__HIDDENCAT__</nowiki></code> 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",
     "emailuser-title-notarget": "Wab-mail uiser",
     "emailpage": "Wab-mail uiser",
     "emailpagetext": "Ye can uise the form ablo tae send ae wab-mail message til this {{GENDER:$1|uiser}}.\nThe wab-mail address that ye entered in [[Special:Preferences|yer uiser preeferances]] will kith aes the \"Fae\" address o the wab-mail, sae that the receepient will be able tae replie directlie til ye.",
-    "usermailererror": "Mail object returned mistak:",
     "defemailsubject": "{{SITENAME}} wab-mail fae uiser \"$1\"",
     "usermaildisabled": "Uiser wab-mail disablit",
     "usermaildisabledtext": "Ye canna send wab-mail til ither uisers oan this wiki",
     "noemailtitle": "Nae e-mail address",
     "noemailtext": "This uiser haesna speceefied ae valid wab-mail address.",
-    "nowikiemailtitle": "Naw wab-mail permitit",
     "nowikiemailtext": "This uiser haes choosen tae naw receeve wab-mail fae ither uisers.",
     "emailnotarget": "Non-exeestent or onvalit uisername fer receepeeant.",
     "emailtarget": "Enter uisername o reeceepeeant",
     "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",
     "watching": "Watchin...",
     "unwatching": "Unwatchin...",
     "watcherrortext": "Ae mistak occurred while chyngin yer watchleet settins fer \"$1\".",
-    "enotif_mailer": "{{SITENAME}} annooncemant mailer",
     "enotif_reset": "Merk aa pages visitit",
     "enotif_impersonal_salutation": "{{SITENAME}} uiser",
     "enotif_subject_deleted": "{{SITENAME}} page $1 haes been {{GENDER:$2|delytit}} bi $2",
     "excontent": "content wis: '$1'",
     "excontentauthor": "content wis: '$1' (n the ae contreebuter wis '[[Special:Contributions/$2|$2]]')",
     "exbeforeblank": "content afore blankin wis: '$1'",
-    "exblank": "page wis tuim",
     "delete-confirm": "Delyte \"$1\"",
     "delete-legend": "Delyte",
     "historywarning": "<strong>Warnishment:</strong> The page that ye'r aboot tae delyte haes ae histerie wi approximatelie $1 {{PLURAL:$1|reveesion|reveesions}}:",
     "imported-log-entries": "Imported $1 {{PLURAL:$1|log entrie|log entries}}.",
     "importunknownsource": "Onkent import soorce type",
     "importcantopen": "Coudna apen import file",
-    "importnotext": "Tuim or nae tex",
     "importsuccess": "Importit fine!",
-    "importhistoryconflict": "Conflictin histerie reveesion exeests (micht hae importit this page afore)",
     "importnosources": "Nae transwiki import soorces haes been defined n direct histerie uplaids is disabled.",
     "importnofile": "Naw import file wis uplaided.",
     "importuploaderrorsize": "Uplaid o import file failed.\nThe file is muckler than the permitit uplaid size.",
index 76aeb70..8eeaa66 100644 (file)
     "disclaimers": "غيرجوابداريناما",
     "disclaimerpage": "Project:عام غيرجوابدارينامو",
     "edithelp": "مدد براءِ ترميم",
-    "helppage": "Help:فهرست",
     "mainpage": "مُک صفحو",
     "mainpage-description": "مُک صفحو",
     "policy-url": "Project:پاليسي",
index 795a707..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",
index 4314c32..f44eb45 100644 (file)
     "currentevents-url": "Project:Âsango",
     "disclaimers": "Zïngö-lê",
     "disclaimerpage": "Project:Zïngö-lê",
-    "helppage": "Help:Münä",
     "mainpage": "Gä nzönî",
     "mainpage-description": "Gä nzönî",
     "portal": "Âsëwä",
index de1115f..117080e 100644 (file)
     "accountcreatedtext": "Korisnički račun za $1 je kreiran. Кориснички налог за $1 је креиран.",
     "createaccount-title": "Pravljenje korisničkog računa za {{SITENAME}}",
     "createaccount-text": "Neko je napravio korisnički račun za vašu e-mail adresu na {{SITENAME}} ($4) sa imenom \"$2\", i sa šifrom \"$3\".\nTrebali biste se prijaviti i promjeniti šifru.\n\nMožete ignorisati ovu poruku, ako je korisnički račun napravljen greškom.",
-    "usernamehasherror": "Korisničko ime ne može sadržavati haš znakove",
     "login-throttled": "Previše puta ste se pokušali prijaviti.\nMolimo Vas da sačekate prije nego što pokušate ponovo.",
     "login-abort-generic": "Vaša prijava nije bila uspješna – Prekinuto",
     "loginlanguagelabel": "Jezik: $1",
     "suspicious-userlogout": "Vaš zahtjev za odjavu je odbijen jer je poslan preko pokvarenog preglednika ili keširanog proksija.",
+    "pt-login": "Prijavi me / Пријави ме",
+    "pt-login-button": "Prijavi me / Пријави ме",
+    "pt-createaccount": "Napraviti novi nalog / Направити нови налог",
     "pt-userlogout": "Odjavi se / Одјави се",
     "php-mail-error-unknown": "Nepoznata greška u PHP funkciji mail()",
     "user-mail-no-addy": "Pokušaj slanja e-maila bez e-mail adrese.",
     "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",
     "upload-permitted": "Podržane vrste datoteka: $1.",
     "upload-preferred": "Preferirane vrste datoteka: $1.",
     "upload-prohibited": "Zabranjene vrste datoteka: $1.",
-    "uploadlog": "registar postavljanja",
     "uploadlogpage": "Registar postavljanja",
     "uploadlogpagetext": "Ispod je popis najnovijih postavljanja datoteka.\nVidi [[Special:NewFiles|galeriju novih datoteka]] za slikovitiji pregled.",
     "filename": "Ime fajla / Име датотеке",
     "filereuploadsummary": "Izmjene datoteke:",
     "filestatus": "Status autorskih prava:",
     "filesource": "Izvor / Извор",
-    "uploadedfiles": "Postavljene datoteke",
     "ignorewarning": "Zanemari upozorenja i sačuvaj datoteku",
     "ignorewarnings": "Zanemari sva upozorenja",
     "minlength1": "Ime datoteke mora imati barem jedno slovo.",
     "overwroteimage": "postavljena nova verzija datoteke \"[[$1]]\"",
     "uploaddisabled": "Slanje fajlova je isključeno",
     "copyuploaddisabled": "Postavljanje putem URL nije omogućeno.",
-    "uploadfromurl-queued": "Vaše postavljanje je na čekanju.",
     "uploaddisabledtext": "Postavljanje datoteka je onemogućeno.",
     "php-uploaddisabledtext": "Postavljanje datoteka preko PHP je onemogućeno. \nMolimo provjerite postavku za postavljanje datoteka.",
     "uploadscripted": "Ova datoteka sadrži HTML ili skriptni kod koji može izazvati grešku kod internet preglednika.",
     "upload-misc-error": "Nepoznata greška pri postavljanju",
     "upload-misc-error-text": "Desila se nepoznata greška pri postavljanju.\nMolimo Vas provjerite da li je URL tačan i dostupan pa pokušajte ponovo.\nAko se problem ne riješi, kontaktirajte [[Special:ListUsers/sysop|administratora]].",
     "upload-too-many-redirects": "URL sadrži previše preusmjerenja",
-    "upload-unknown-size": "Nepoznata veličina",
     "upload-http-error": "Desila se HTTP greška: $1",
     "upload-copy-upload-invalid-domain": "Kopije postavljanja nisu dostupni na ovom domenu.",
     "backend-fail-stream": "Ne mogu da emitujem datoteku $1.",
     "img-auth-streaming": "Tok \"$1\".",
     "img-auth-public": "Funkcija img_auth.php služi za izlaz datoteka sa privatnih wikija.\nOva wiki je postavljena kao javna wiki.\nZa optimalnu sigurnost, img_auth.php je onemogućena.",
     "img-auth-noread": "Korisnik nema pristup za čitanje \"$1\".",
-    "img-auth-bad-query-string": "URL ima nevaljan izraz upita.",
     "http-invalid-url": "Nevaljan URL: $1",
     "http-invalid-scheme": "URLovi za koje šema \"$1\" nije podržana",
     "http-request-error": "HTTP zahtjev nije uspio zbog nepoznate pogreške.",
     "filehist-dimensions": "Dimenzije",
     "filehist-filesize": "Veličina datoteke",
     "filehist-comment": "Komentar",
-    "filehist-missing": "Datoteka nedostaje",
     "imagelinks": "Upotreba datoteke",
     "linkstoimage": "{{PLURAL:$1|Sljedeća stranica koristi|Sljedećih $1 stranica koriste}} ovu sliku:",
     "linkstoimage-more": "Više od $1 {{PLURAL:$1|stranice povezuje|stranica povezuje}} na ovu datoteku.\nSlijedeći popis prikazuje {{PLURAL:$1|stranice koje|prvih $1 stranica koje}} vode na ovu datoteku.\n[[Special:WhatLinksHere/$2|Ovdje se nalazi]] potpuni popis.",
     "emailuser-title-notarget": "Slanje e-maila korisniku",
     "emailpage": "Pošalji e-mail ovom korisniku",
     "emailpagetext": "Možete da koristite donji obrazac da pošaljete e-mail {{GENDER:$1|ovom korisniku|ovoj korisnici|ovom korisniku|}}.\nE-mail koju ste uneli u vašim [[Special:Preferences|postavkama]] će se prikazati u polju \"Od:\", tako da će primalac moći da vam odgovori direktno.",
-    "usermailererror": "Objekat maila je vratio grešku:",
     "defemailsubject": "{{SITENAME}} e-mail od korisnika \"$1\"",
     "usermaildisabled": "Korisnički e-mail onemogućen",
     "usermaildisabledtext": "Ne možete poslati e-mail drugim korisnicima na ovoj wiki",
     "noemailtitle": "Nema adrese e-pošte",
     "noemailtext": "Ovaj korisnik nije naveo ispravnu adresu e-pošte.",
-    "nowikiemailtitle": "E-mail nije dozvoljen",
     "nowikiemailtext": "Ovaj korisnik je odabrao da ne prima e-mail poštu od drugih korisnika.",
     "emailnotarget": "Neodgovarajuće ili nevaljano korisničko ime za primanje e-maillova.",
     "emailtarget": "Unesite korisnika za primanje e-mailova",
     "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",
     "watching": "Pratim... / Додавање на списак надгледања...",
     "unwatching": "Ne pratim…",
     "watcherrortext": "Desila se greška pri promjeni postavki vašeg spiska praćenja za \"$1\".",
-    "enotif_mailer": "{{SITENAME}} obavještenje o pošti",
     "enotif_reset": "Označi sve strane kao posjećene",
     "enotif_impersonal_salutation": "{{SITENAME}} korisnik",
     "enotif_subject_deleted": "{{SITENAME}} stranicu $1 {{gender:|je izbrisao|je izbrisala|je izbrisao}} $2",
     "excontent": "sadržaj je bio: '$1'",
     "excontentauthor": "sadržaj je bio: '$1' (i jedini korisnik koji je mijenjao bio je '[[Special:Contributions/$2|$2]]')",
     "exbeforeblank": "sadržaj prije brisanja je bio: '$1'",
-    "exblank": "stranica je bila prazna",
     "delete-confirm": "Brisanje \"$1\"",
     "delete-legend": "Obriši",
     "historywarning": "'''Upozorenje''':  Stranica koju želite da obrišete ima historiju sa otprilike $1 {{PLURAL:$1|revizijom|revizije|revizija}}:",
     "importunknownsource": "Nepoznat izvorni tip uvoza",
     "importcantopen": "Ne može se otvoriti uvozna datoteka",
     "importbadinterwiki": "Loš interwiki link",
-    "importnotext": "Prazan ili nepostojeći tekst",
     "importsuccess": "Uvoz dovršen!",
-    "importhistoryconflict": "Postoji konfliktna historija revizija (moguće je da je ova stranica ranije uvezena)",
     "importnosources": "Nisu definirani izvori za transwiki uvoz i neposredna postavljanja historije su onemogućena.",
     "importnofile": "Uvozna datoteka nije postavljena.",
     "importuploaderrorsize": "Postavljanje uvozne datoteke nije uspjelo.\nDatoteka je veća od dozvoljene veličine za postavljanje.",
index 04b2afd..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": "මුරලැයිස්තුවෙන් ඉවත් කරන්න",
index e79be0a..a5b45ba 100644 (file)
     "createacct-imgcaptcha-ph": "Zadajte text, ktorý vidíte vyššie",
     "createacct-submit": "Vytvoriť účet",
     "createacct-another-submit": "Vytvoriť ďalší účet",
-    "createacct-benefit-heading": "{{grammar:4sg|{{SITENAME}}}} tvoria ľudia ako vy.",
+    "createacct-benefit-heading": "{{GRAMMAR:akuzatív|{{SITENAME}}}} tvoria ľudia ako vy.",
     "createacct-benefit-body1": "{{PLURAL:$1|úprava|úpravy|úprav}}",
     "createacct-benefit-body2": "{{PLURAL:$1|stránka|stránky|stránok}}",
     "createacct-benefit-body3": "{{PLURAL:$1|nedávny prispievateľ|nedávni prispievatelia|nedávnych prispievateľov}}",
     "accountcreatedtext": "Používateľský účet [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|diskusia]]) bol vytvorený.",
     "createaccount-title": "Vytvorenie účtu na {{GRAMMAR:lokál|{{SITENAME}}}}",
     "createaccount-text": "Niekto vytvoril účet pre vašu emailovú adresu na {{GRAMMAR:lokál|{{SITENAME}}}}\n($4) s názvom „$2“, s heslom „$3“. Mali by ste sa prihlásiť a svoje heslo teraz zmeniť.\n\nAk bol účet vytvorený omylom, túto správu môžete ignorovať.",
-    "usernamehasherror": "Používateľské meno nemôže obsahovať znak mriežky.",
     "login-throttled": "Uskutočnili ste príliš mnoho neúspešných pokusov o prihlásenie.\nProsím, počkajte $1 predtým, než to skúsite znova.",
     "login-abort-generic": "Vaše prihlásenie nebolo úspešné - zrušené",
     "loginlanguagelabel": "Jazyk: $1",
     "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",
     "upload-permitted": "Povolené typy súborov: $1.",
     "upload-preferred": "Uprednostňované typy súborov: $1.",
     "upload-prohibited": "Zakázané typy súborov: $1.",
-    "uploadlog": "Záznam nahrávaní",
     "uploadlogpage": "Záznam nahrávaní",
     "uploadlogpagetext": "Nižšie je zoznam nedávno nahraných súborov.\nVizuálny prehľad nájdete v [[Special:NewFiles|galérii novo nahraných súborov]].",
     "filename": "Názov súboru",
     "filereuploadsummary": "Zmeny súboru:",
     "filestatus": "Stav autorských práv:",
     "filesource": "Zdroj:",
-    "uploadedfiles": "Nahrané súbory",
     "ignorewarning": "Ignorovať varovanie a súbor napriek tomu uložiť",
     "ignorewarnings": "Ignorovať všetky varovania",
     "minlength1": "Názvy súborov musia mať aspoň jedno písmeno.",
     "overwroteimage": "bola nahraná nová verzia „[[$1]]“",
     "uploaddisabled": "Prepáčte, nahrávanie je vypnuté.",
     "copyuploaddisabled": "Nahrávanie prostredníctvom URL nie je povolené.",
-    "uploadfromurl-queued": "Súbor, ktorý ste dali nahrať bol uložený do fronty.",
     "uploaddisabledtext": "Nahrávanie súborov je vypnuté.",
     "php-uploaddisabledtext": "Nahrávanie PHP súborov je vypnuté. Prosím, skontrolujte nastavenie file_uploads.",
     "uploadscripted": "Tento súbor obsahuje kód HTML alebo skript, ktorý može byť chybne interpretovaný prehliadačom.",
     "upload-misc-error": "Neznáma chyba pri nahrávaní",
     "upload-misc-error-text": "Počas nahrávania sa vyskytla neznáma chyba.\nProsím, overte, že URL je platný a dostupný a skúste znova.\nAk problém pretrváva, kontaktujte [[Special:ListUsers/sysop|správcu systému]].",
     "upload-too-many-redirects": "URL obsahoval príliš mnoho presmerovaní",
-    "upload-unknown-size": "Neznáma veľkosť",
     "upload-http-error": "Vyskytla sa chyba HTTP: $1",
     "upload-copy-upload-invalid-domain": "Kopírovanie nahraných súborov nie je dostupné z tejto domény.",
     "backend-fail-stream": "$1 je názov súboru.",
     "img-auth-streaming": "Streamovanie „$1“.",
     "img-auth-public": "Funkciou img_auth.php je výstup súborov zo súkromnej wiki.\nNastavená wiki je verejná.\nAby bolo zabezpečenie optimálne, img_auth.php je vypnutý.",
     "img-auth-noread": "Používateľ nemá prístup na čítanie „$1“.",
-    "img-auth-bad-query-string": "URL má neplatný reťazec požiadavky.",
     "http-invalid-url": "Neplatný URL: $1",
     "http-invalid-scheme": "URL so schémou „$1“ nie sú podporované",
     "http-request-error": "Požiadavka HTTP zlyhala z neznámych dôvodov.",
     "filehist-dimensions": "rozmery",
     "filehist-filesize": "veľkosť súboru",
     "filehist-comment": "komentár",
-    "filehist-missing": "Súbor chýba",
     "imagelinks": "Použitie súboru",
     "linkstoimage": "Na tento obrázok {{PLURAL:$1|odkazuje nasledujúca stránka|odkazujú nasledujúce $1 stránky|odkazuje nasledujúcich $1 stránok}}:",
     "linkstoimage-more": "Viac ako $1 {{PLURAL:$1|stránka odkazuje|stránky odkazujú|stránok odkazuje}} na tento súbor.\nNasledovný zoznam zobrazuje {{PLURAL:$1|prvú stránku odkazujúcu|prvé $1 stránky odkazujúce|prvých $1 stránok odkazujúcich}} iba na tento súbor.\nMôžete si pozrieť [[Special:WhatLinksHere/$2|úplný zoznam]].",
     "emailuser-title-notarget": "E-mail používateľovi",
     "emailpage": "E-mail používateľovi",
     "emailpagetext": "Pomocou nasledovného formulára môžete {{GENDER:$1|tomuto používateľovi|tejto používateľke}} poslať e-mailovú správu.\nMailová adresa, ktorú ste zadali vo svojich [[Special:Preferences|nastaveniach]] sa zobrazí ako adresa odosielateľa mailu, aby vám mohol príjemca priamo odpovedať.",
-    "usermailererror": "Emailový program vrátil chybu:",
     "defemailsubject": "email {{GRAMMAR:genitív|{{SITENAME}}}} od používateľa „$1“",
     "usermaildisabled": "Používateľ má vypnuté používanie emailu",
     "usermaildisabledtext": "Nemôžete posielať emaily ostatným používateľom na tejto wiki",
     "noemailtitle": "Chýba e-mailová adresa",
     "noemailtext": "Tento používateľ neuviedol svoju platnú e-mailovú adresu.",
-    "nowikiemailtitle": "Posielanie emailov nie je umožnené",
     "nowikiemailtext": "Tento používateľ sa rozhodol, že si neželá prijímať emaily od ostatných používateľov.",
     "emailnotarget": "Neexistujúce alebo neplatné používateľské meno príjemcu.",
     "emailtarget": "Zadajte používateľské meno príjemcu",
     "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",
     "watching": "Pridávam do zoznamu sledovaných...",
     "unwatching": "Odoberám zo zoznamu sledovaných...",
     "watcherrortext": "Vyskytla sa chyba počas zmeny nastavenia vášho zoznamu sledovaných pre „$1“.",
-    "enotif_mailer": "Upozorňovač {{GRAMMAR:genitív|{{SITENAME}}}}",
     "enotif_reset": "Označiť všetky stránky ako „navštívené“",
     "enotif_impersonal_salutation": "používateľ {{GRAMMAR:genitív|{{SITENAME}}}}",
     "enotif_subject_deleted": "Stránku {{GENDER:genitív|{{SITENAME}}}} „$1“ odstránil používateľ $2",
     "excontent": "obsah bol: „$1“",
     "excontentauthor": "obsah bol: „$1“ (a jediný autor bol [[Special:Contributions/$2]])",
     "exbeforeblank": "obsah pred vyčistením stránky bol: '$1'",
-    "exblank": "stránka bola prázdna",
     "delete-confirm": "Zmazať „$1“",
     "delete-legend": "Zmazať",
     "historywarning": "'''Upozornenie:''' Stránka, ktorú sa chystáte zmazať má históriu obsahujúcu približne $1 {{PLURAL:$1|revíziu|revízie|revízií}}:",
     "importunknownsource": "Neznámy typ zdroja pre import",
     "importcantopen": "Nedal sa otvoriť súbor importu",
     "importbadinterwiki": "Zlý interwiki odkaz",
-    "importnotext": "Prázdny alebo žiadny text",
     "importsuccess": "Import dokončený!",
-    "importhistoryconflict": "Existujú konfliktné histórie revízií (možno už bola táto stránka importovaná)",
     "importnosources": "Neboli definované žiadne zdroje pre transwiki import a priame nahranie histórie je vypnuté.",
     "importnofile": "Nebol nahraný import súbor.",
     "importuploaderrorsize": "Nahranie alebo import súboru zlyhal. Súbor je väčší ako maximálna povolená veľkosť.",
index 1395119..a3334fe 100644 (file)
     "permalink": "Trajna povezava",
     "print": "Tisk",
     "view": "Ogled",
+    "view-foreign": "Ogled na: $1",
     "edit": "Uredi stran",
+    "edit-local": "Uredi lokalni opis",
     "create": "Ustvari",
+    "create-local": "Dodaj lokalni opis",
     "editthispage": "Uredi stran",
     "create-this-page": "Ustvari stran",
     "delete": "Briši",
     "accountcreatedtext": "Ustvarili smo uporabniški račun za [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|pogovor]]).",
     "createaccount-title": "Ustvarjanje računa za {{GRAMMAR:tožilnik|{{SITENAME}}}}",
     "createaccount-text": "Nekdo je ustvaril račun $2 na {{GRAMMAR:dajalnik|{{SITENAME}}}} ($4). Geslo za »$2« je »$3«. Priporočljivo je, da se prijavite in spremenite svoje geslo sedaj.\n\nTo sporočilo lahko prezrete, če je bil račun ustvarjen pomotoma.",
-    "usernamehasherror": "Uporabniško ime ne sme vsebovati ''hash'' znakov",
     "login-throttled": "Nedavno ste izvedli preveč poskusov prijave.\nProsimo, počakajte $1, preden poskusite znova.",
     "login-abort-generic": "Vaša prijava ni bila uspešna – Prekinjeno",
     "loginlanguagelabel": "Jezik: $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",
     "upload-permitted": "Dovoljene vrste datotek: $1.",
     "upload-preferred": "Priporočene vrste datotek: $1.",
     "upload-prohibited": "Prepovedane vrste datotek: $1.",
-    "uploadlog": "dnevnik nalaganja",
     "uploadlogpage": "Dnevnik nalaganja datotek",
     "uploadlogpagetext": "Prikazan je seznam nedavno naloženih datotek.\nZa grafični pogled obiščite [[Special:NewFiles|galerijo novih datotek]].",
     "filename": "Ime datoteke",
     "filereuploadsummary": "Spremembe datoteke:",
     "filestatus": "Položaj avtorskih pravic:",
     "filesource": "Vir:",
-    "uploadedfiles": "Naložene datoteke",
     "ignorewarning": "Naloži kljub opozorilu",
     "ignorewarnings": "Prezri vsa opozorila",
     "minlength1": "Imena datotek morajo biti dolga vsaj eno črko.",
     "overwroteimage": "je naložil(-a) novo različico datoteke »[[$1]]«",
     "uploaddisabled": "Nalaganje je onemogočeno",
     "copyuploaddisabled": "Nalaganje preko URL je onemogočeno",
-    "uploadfromurl-queued": "Vaše nalaganje je bilo postavljeno v čakalno vrsto.",
     "uploaddisabledtext": "Nalaganje datotek je onemogočeno.",
     "php-uploaddisabledtext": "Nalaganje datotek je onemogočeno v PHP.\nProsimo preverite file_uploads nastavitev.",
     "uploadscripted": "Datoteka vsebuje HTML- ali skriptno kodo, ki bi jo lahko brskalnik razlagal napačno.",
     "upload-misc-error": "Neznana napaka pri nalaganju",
     "upload-misc-error-text": "Med nalaganjem je prišlo do neznane napake.\nProsimo, preverite veljavnost in dostopnost naslova URL ter poskusite ponovno.\nČe se težava ponavlja, kontaktirajte [[Special:ListUsers/sysop|administratorja]].",
     "upload-too-many-redirects": "URL vsebuje preveč preusmeritev",
-    "upload-unknown-size": "neznana velikost",
     "upload-http-error": "Prišlo je do napake HTTP: $1",
     "upload-copy-upload-invalid-domain": "Nalaganje kopij s te domene ni možno.",
     "backend-fail-stream": "Ne morem pretakati datoteke $1.",
     "img-auth-streaming": "Pretakanje »$1«.",
     "img-auth-public": "Funkcija img_auth.php je izvoz datotek iz zasebnega wikija.\nTa wiki je konfiguriran kot javni wiki.\nZa optimalno varnost je img_auth.php onemogočen.",
     "img-auth-noread": "Uporabnik nima dostopa za branje »$1«.",
-    "img-auth-bad-query-string": "URL ima neveljavni niz poizvedbe.",
     "http-invalid-url": "Napačen URL: $1",
     "http-invalid-scheme": "URL-naslovi s shemo »$1« niso podprti.",
     "http-request-error": "Zahteva HTTP ni uspela zaradi neznane napake.",
     "filehist-dimensions": "Velikost",
     "filehist-filesize": "Velikost datoteke",
     "filehist-comment": "Komentar",
-    "filehist-missing": "Datoteka manjka",
     "imagelinks": "Uporaba datoteke",
     "linkstoimage": "Datoteka je del {{PLURAL:$1|naslednje $1 strani|naslednjih $1 strani}} {{GRAMMAR:rodilnik|{{SITENAME}}}}:",
     "linkstoimage-more": "Na to datoteko se {{PLURAL:$1|povezuje več kot $1 stran|povezujeta več kot $1 strani|povezujejo več kot $1 strani|povezuje več kot $1 strani}}.\nNaslednji seznam obsega samo {{PLURAL:$1|prvo stran, ki se povezuje|prvi $1 strani, ki se povezujeta|prve $1 strani, ki se povezujejo|prvih $1 strani, ki se povezujejo}} na datoteko.\nNa razpolago je tudi [[Special:WhatLinksHere/$2|popoln seznam]].",
     "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",
+    "listgrouprights-namespaceprotection-header": "Omejitve imenskih prostorov",
+    "listgrouprights-namespaceprotection-namespace": "Imenski prostor",
+    "listgrouprights-namespaceprotection-restrictedto": "Pravice, ki uporabniku omogočajo urejanje",
     "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.",
+    "noindex-category-desc": "Stran vsebuje čarobno besedo <code><nowiki>__NOINDEX__</nowiki></code> (in je v imenskem prostoru, ki dovoljuje to oznako) in posledično je roboti ne indeksirajo.",
+    "index-category-desc": "Stran vsebuje čarobno besedo <code><nowiki>__INDEX__</nowiki></code> (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 <code>$wgMaxArticleSize</code>, zato nekaterih predlog nismo razširili.",
+    "post-expand-template-argument-category-desc": "Po razširitvi argumentov predloge (nekaj v trojnih narekovajih, npr. <code>{{{Foo}}})</code> je stran večja od <code>$wgMaxArticleSize</code>.",
     "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.",
+    "hidden-category-category-desc": "To je kategorija s <code><nowiki>__HIDDENCAT__</nowiki></code>, 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",
     "emailuser-title-notarget": "Pošlji uporabniku e-pismo",
     "emailpage": "Pošlji uporabniku e-pismo",
     "emailpagetext": "S spodnjim obrazcem lahko {{GENDER:$1|uporabniku|uporabnici}} pošljete e-poštno sporočilo.\nE-poštni naslov, ki ste ga vpisali v [[Special:Preferences|uporabniških nastavitvah]], bo v e-sporočilu naveden kot naslov »Od:«, tako da bo {{GENDER:$1|prejemnik lahko odgovoril|prejemnica lahko odgovorila}} neposredno vam.",
-    "usermailererror": "Predmet e-pošte je vrnil napako:",
     "defemailsubject": "Elektronska pošta {{GRAMMAR:rodilnik|{{SITENAME}}}} od uporabnika »$1«",
     "usermaildisabled": "Uporabniška e-pošta je onemogočena",
     "usermaildisabledtext": "Na tem wikiju ne morete poslati e-pošte drugim uporabnikom",
     "noemailtitle": "Ni e-poštnega naslova",
     "noemailtext": "Uporabnik ni navedel veljavnega e-poštnega naslova.",
-    "nowikiemailtitle": "E-pošta ni dovoljena",
     "nowikiemailtext": "Ta uporabnik se je odločil, da ne bo prejmal e-pošte od drugih uporabnikov.",
     "emailnotarget": "Neobstoječe ali neveljavno uporabniško ime prejemnika.",
     "emailtarget": "Vnesite uporabniško ime prejemnika",
     "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",
     "watching": "Nadziranje ...",
     "unwatching": "Nenadziranje ...",
     "watcherrortext": "Med spreminjanjem vaših nastavitev spiska nadzora za »$1« je prišlo do napake.",
-    "enotif_mailer": "Obvestilni poštar {{GRAMMAR:rodilnik|{{SITENAME}}}}",
     "enotif_reset": "Označi vse strani kot prebrane",
     "enotif_impersonal_salutation": "Uporabnik {{GRAMMAR:rodilnik|{{SITENAME}}}}",
     "enotif_subject_deleted": "{{GENDER:$2|Uporabnik|Uporabnica}} $2 je {{GENDER:$2|izbrisal|izbrisala}} stran $1 v {{GRAMMAR:dajalnik|{{SITENAME}}}}",
     "excontent": "vsebina: '$1'",
     "excontentauthor": "vsebina: '$1' (edini urejevalec pa '$2')",
     "exbeforeblank": "vsebina pred brisanjem: '$1'",
-    "exblank": "prazna stran",
     "delete-confirm": "Brisanje »$1«",
     "delete-legend": "Izbriši",
     "historywarning": "'''Opozorilo:''' Stran, ki jo želite izbrisati, ima zgodovino s približno $1 {{PLURAL:$1|redakcijo|redakcijama|redakcijami}}:",
     "importunknownsource": "Neznana vrsta vira uvoza",
     "importcantopen": "Neuspešno odpiranje uvožene datoteke",
     "importbadinterwiki": "Slaba jezikovna povezava",
-    "importnotext": "Prazno ali brez besedila",
     "importsuccess": "Uspešno uvoženo!",
-    "importhistoryconflict": "Zgodovina strani vključuje navzkrižno redakcijo (morda je bila stran naložena že prej)",
     "importnosources": "Na tem wikiju je ta možnost onemogočena.",
     "importnofile": "Uvožena ni bila nobena datoteka.",
     "importuploaderrorsize": "Nalaganje datoteke za uvoz ni uspelo.\nDatoteka je večja od dovoljene velikosti nalaganja.",
index 59620c2..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",
index b743f01..1a8edef 100644 (file)
     "disclaimers": "Friijavuohte vastideamis",
     "disclaimerpage": "Project:Bäjjesereaktah",
     "edithelp": "Sjiehtedimmie viehkie",
-    "helppage": "Help:Sisvege",
     "mainpage": "Aalkoebielie",
     "mainpage-description": "Aalkoebielie",
     "portal": "Meatan portaale",
index b55d68a..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",
index 2e6dd55..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",
index 845cf0d..4a3c676 100644 (file)
     "create-this-page": "Направи ову страницу",
     "delete": "Обриши",
     "deletethispage": "Обриши ову страницу",
-    "undeletethispage": "Ð\9fоврати ову страницу",
+    "undeletethispage": "Ð\92рати ову страницу",
     "undelete_short": "Врати {{PLURAL:$1|једну обрисану измену|$1 обрисане измене|$1 обрисаних измена}}",
     "viewdeleted_short": "Погледај {{PLURAL:$1|обрисану измену|$1 обрисане измене|$1 обрисаних измена}}",
     "protect": "Заштити",
     "accountcreatedtext": "Кориснички налог [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|talk]]) је отворен.",
     "createaccount-title": "Отварање корисничког налога за {{SITENAME}}",
     "createaccount-text": "Неко је отворио налог с вашом е-адресом на {{SITENAME}} ($4) под именом $2 и лозинком $3.\nПријавите се и промените своју лозинку.\n\nАко је ово грешка, занемарите ову поруку.",
-    "usernamehasherror": "Корисничко име не може садржати тарабе",
     "login-throttled": "Превише пута сте покушали да се пријавите.\nМолимо вас да сачекате $1 пре него што покушате поново.",
     "login-abort-generic": "Неуспешна пријава – прекинуто",
     "loginlanguagelabel": "Језик: $1",
     "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": "Корисничке странице",
     "upload-permitted": "Дозвољени типови датотека: $1.",
     "upload-preferred": "Препоручени типови датотека: $1.",
     "upload-prohibited": "Забрањени типови датотека: $1.",
-    "uploadlog": "дневник отпремања",
     "uploadlogpage": "Дневник отпремања",
     "uploadlogpagetext": "Испод је списак скорашњих слања.\nПогледајте [[Special:NewFiles|галерију нових датотека]] за лепши преглед.",
     "filename": "Назив датотеке",
     "filereuploadsummary": "Измене датотеке:",
     "filestatus": "Статус ауторског права:",
     "filesource": "Извор:",
-    "uploadedfiles": "Послате датотеке",
     "ignorewarning": "Занемари упозорења и сачувај датотеку",
     "ignorewarnings": "Занемари сва упозорења",
     "minlength1": "Назив датотеке мора имати барем један знак.",
     "overwroteimage": "је послао нову верзију датотеке „[[$1]]“",
     "uploaddisabled": "Отпремање је онемогућено.",
     "copyuploaddisabled": "Слање путем URL адресе је онемогућено.",
-    "uploadfromurl-queued": "Слање је стављено на списак чекања.",
     "uploaddisabledtext": "Отпремање датотека је онемогућено.",
     "php-uploaddisabledtext": "Слање датотека је онемогућено у PHP-у.\nПроверите поставке file_uploads.",
     "uploadscripted": "Датотека садржи HTML или скриптни код који може бити погрешно протумачен од стране прегледача.",
     "upload-misc-error": "Непозната грешка при слању датотеке",
     "upload-misc-error-text": "Непозната грешка при слању датотеке.\nПроверите да ли је адреса исправна и покушајте поново.\nАко се проблем не реши, контактирајте [[Special:ListUsers/sysop|администратора]].",
     "upload-too-many-redirects": "Адреса садржи превише преусмерења",
-    "upload-unknown-size": "Непозната величина",
     "upload-http-error": "Дошло је до HTTP грешке: $1",
     "upload-copy-upload-invalid-domain": "Примерци отпремања нису доступни на овом домену.",
     "backend-fail-stream": "Не могу да емитујем датотеку $1.",
     "img-auth-streaming": "Учитавање „$1“.",
     "img-auth-public": "Сврха img_auth.php је да прослеђује датотеке из приватних викија.\nОвај вики је постављен као јавни.\nРади сигурности, img_auth.php је онемогућен.",
     "img-auth-noread": "Корисник нема приступ за читање „$1“.",
-    "img-auth-bad-query-string": "Адреса има неисправну ниску упита.",
     "http-invalid-url": "Неисправна адреса: $1",
     "http-invalid-scheme": "Адресе са шемом „$1“ нису подржане.",
     "http-request-error": "HTTP захтев није прошао због непознате грешке.",
     "filehist-dimensions": "Димензије",
     "filehist-filesize": "Величина датотеке",
     "filehist-comment": "Коментар",
-    "filehist-missing": "Датотека недостаје",
     "imagelinks": "Употреба датотеке",
     "linkstoimage": "{{PLURAL:$1|Следећа страница користи|$1 следеће странице користе|$1 следећих страница користи}} ову датотеку:",
     "linkstoimage-more": "Више од $1 {{PLURAL:$1|странице|странице|страница}} је повезано с овом датотеком.\nСледећи списак приказује само {{PLURAL:$1|прву страницу повезану|прве $1 странице повезане|првих $1 страница повезаних}} с овом датотеком.\nДоступан је и [[Special:WhatLinksHere/$2|потпуни списак]].",
     "emailuser-title-notarget": "Слање е-поруке кориснику",
     "emailpage": "Слање е-порука",
     "emailpagetext": "Можете да користите доњи образац да пошаљете е-поруку {{GENDER:$1|овом кориснику|овој корисници|овом кориснику|}}.\nЕ-адреса коју сте унели у вашим [[Special:Preferences|подешавањима]] ће се приказати у пољу „Од“, тако да ће прималац моћи да вам одговори директно.",
-    "usermailererror": "Дошло је до грешке при слању поруке:",
     "defemailsubject": "{{SITENAME}} е-адреса {{GENDER:$1|корисника|кориснице|корисника}} $1",
     "usermaildisabled": "Корисничка е-пошта је онемогућена",
     "usermaildisabledtext": "Не можете да шаљете е-поруке другим корисницима на овом викију",
     "noemailtitle": "Нема е-адресе",
     "noemailtext": "Овај корисник није навео исправну е-адресу.",
-    "nowikiemailtitle": "Е-пошта није дозвољена",
     "nowikiemailtext": "Овај корисник је одлучио да не прима е-поруке од других корисника.",
     "emailnotarget": "Непостојеће или неисправно корисничко име примаоца.",
     "emailtarget": "Унос корисничког имена примаоца",
     "nowatchlist": "Ваш списак надгледања је празан.",
     "watchlistanontext": "Морате бити $1 да бисте гледали и уређивали ставке на вашем списку надгледања.",
     "watchnologin": "Нисте пријављени",
-    "watchnologintext": "Морате бити [[Special:UserLogin|пријављени]] да бисте мењали списак надгледања.",
     "addwatch": "Додај на списак надгледања",
     "addedwatchtext": "Страница „[[:$1]]“ је додата на ваш [[Special:Watchlist|списак надгледања]].\nБудуће измене ове странице и њене странице за разговор биће наведене овде.",
     "removewatch": "Уклони са списка надгледања",
     "watching": "Надгледање…",
     "unwatching": "Прекидање надгледања…",
     "watcherrortext": "Дошло је до грешке при промени поставки вашег списка надгледања за „$1“.",
-    "enotif_mailer": "{{SITENAME}} е-обавештење",
     "enotif_reset": "Означи све странице као посећене",
     "enotif_impersonal_salutation": "{{SITENAME}} корисник",
     "enotif_subject_deleted": "Страницу $1 на {{SITENAME}} {{GENDER:$2|обрисао је|обрисала је|обрисао је}} $2",
     "excontent": "садржај је био: „$1“",
     "excontentauthor": "садржај је био: „$1“ (а једини уредник је био „[[Special:Contributions/$2|$2]]“)",
     "exbeforeblank": "садржај пре брисања је био: „$1“",
-    "exblank": "страница је била празна",
     "delete-confirm": "Брисање странице „$1“",
     "delete-legend": "Обриши",
     "historywarning": "'''Упозорење:''' страница коју желите да обришете има историју с приближно $1 {{PLURAL:$1|изменом|измене|измена}}:",
     "importunknownsource": "Непозната врста за увоз",
     "importcantopen": "Не могу да отворим датотеку за увоз",
     "importbadinterwiki": "Неисправна међувики веза",
-    "importnotext": "Празно или без текста",
     "importsuccess": "Увожење је завршено!",
-    "importhistoryconflict": "Постоји сукобљена измена у историји (можда је ова страница већ увезена раније)",
     "importnosources": "Није одређен ниједан међувики извор за увоз, тако да је отпремање историје онемогућено.",
     "importnofile": "Увозна датотека није послата.",
     "importuploaderrorsize": "Не могу да отпремим датотеку за увоз.\nДатотека је већа од дозвољене величине.",
     "tooltip-recreate": "Поново направите страницу иако је обрисана",
     "tooltip-upload": "Започните отпремање",
     "tooltip-rollback": "„Врати“ враћа измене последњег корисника једним кликом",
-    "tooltip-undo": "Ð\92Ñ\80аÑ\9bа ову измену и отвара образац за уређивање.",
+    "tooltip-undo": "Ð\9fониÑ\88Ñ\82ава ову измену и отвара образац за уређивање.",
     "tooltip-preferences-save": "Сачувај поставке",
     "tooltip-summary": "Унесите кратак опис",
     "common.css": "/** CSS постављен овде ће се одразити на све теме */",
     "semicolon-separator": ";&#32;",
     "comma-separator": ",&#32;",
     "colon-separator": ":&#32;",
-    "pipe-separator": "&#32;&#32;",
+    "pipe-separator": "&#32;|&#32;",
     "word-separator": "&#32;",
     "ellipsis": "…",
     "percent": "$1%",
index d57d025..dc9c254 100644 (file)
     "actions": "Radnje",
     "namespaces": "Imenski prostori",
     "variants": "Varijante",
+    "navigation-heading": "Navigacioni meni",
     "errorpagetitle": "Greška",
     "returnto": "Nazad na $1.",
     "tagline": "Izvor: {{SITENAME}}",
     "create-this-page": "Napravi ovu stranicu",
     "delete": "Obriši",
     "deletethispage": "Obriši ovu stranicu",
+    "undeletethispage": "Vrati ovu stranicu",
     "undelete_short": "Vrati {{PLURAL:$1|jednu obrisanu izmenu|$1 obrisane izmene|$1 obrisanih izmena}}",
     "viewdeleted_short": "Pogledaj {{PLURAL:$1|obrisanu izmenu|$1 obrisane izmene|$1 obrisanih izmena}}",
     "protect": "Zaštiti",
     "error": "Greška",
     "databaseerror": "Greška u bazi podataka",
     "databaseerror-text": "Došlo je do greške u upitu baze podataka. Možda je u pitanju programska greška.",
+    "databaseerror-function": "Funkcija: $1",
+    "databaseerror-error": "Greška: $1",
     "laggedslavemode": "'''Upozorenje:''' stranica je možda zastarela.",
     "readonly": "Baza podataka je zaključana",
     "enterlockreason": "Unesite razlog za zaključavanje, uključujući i vreme otključavanja",
     "namespaceprotected": "Nemate dozvolu da uređujete stranice u imenskom prostoru '''$1'''.",
     "customcssprotected": "Nemate dozvolu da menjate ovu CSS stranicu jer sadrži lične postavke drugog korisnika.",
     "customjsprotected": "Nemate dozvolu da menjate ovu stranicu javaskripta jer sadrži lične postavke drugog korisnika.",
+    "mycustomcssprotected": "Nemate dozvolu za menjanje ove CSS stranice.",
+    "mycustomjsprotected": "Nemate dozvolu za menjanje ove JavaScript stranice.",
+    "myprivateinfoprotected": "Nemate dozvolu za menjanje vaših ličnih informacija.",
+    "mypreferencesprotected": "Nemate dozvolu za menjanje vaših podešavanja.",
     "ns-specialprotected": "Posebne stranice se ne mogu uređivati.",
     "titleprotected": "Ovaj naziv je [[User:$1|$1]] zaštitio od pravljenja. Razlog: ''$2''.",
     "filereadonlyerror": "Ne mogu da izmenim datoteku „$1“ jer je riznica „$2“ u režimu za čitanje.\n\nAdministrator koji ju je zaključao ponudio je sledeće objašnjenje: „$3“.",
     "invalidtitle-unknownnamespace": "Neispravan naslov s imenskim prostorom br. $1 i tekstom „$2“",
     "exception-nologin": "Niste prijavljeni",
     "exception-nologin-text": "[[Special:Userlogin|Prijavite se]] da biste pristupili ovoj stranici ili radnji.",
+    "exception-nologin-text-manual": "Morate biti $1 da biste pristupili ovoj stranici ili radnji.",
     "virus-badscanner": "Neispravna postavka: nepoznati skener za viruse: ''$1''",
     "virus-scanfailed": "neuspešno skeniranje (kod $1)",
     "virus-unknownscanner": "nepoznati antivirus:",
     "yourname": "Korisničko ime:",
     "userlogin-yourname": "Korisničko ime",
     "userlogin-yourname-ph": "Unesite vaše korisničko ime",
+    "createacct-another-username-ph": "Unesite korisničko ime",
     "yourpassword": "Lozinka:",
     "userlogin-yourpassword": "Lozinka",
     "userlogin-yourpassword-ph": "Unesite vašu lozinku",
     "gotaccountlink": "Prijava",
     "userlogin-resetlink": "Zaboravili ste podatke za prijavu?",
     "userlogin-resetpassword-link": "Zaboravili ste lozinku?",
+    "userlogin-helplink2": "Pomoć pri prijavljivanju",
+    "userlogin-loggedin": "Već ste prijavljeni kao {{GENDER:$1|$1}}.\nKoristite donji obrazac da biste se prijavili kao drugi korisnik.",
+    "userlogin-createanother": "Otvori još jedan nalog",
     "createacct-join": "Unesite svoje podatke ispod.",
+    "createacct-another-join": "Unesite podatke za novi nalog ispod.",
     "createacct-emailrequired": "Adresa e-pošte",
     "createacct-emailoptional": "Adresa e-pošte (opciono)",
     "createacct-email-ph": "Unesite vašu adresu e-pоšte",
+    "createacct-another-email-ph": "Unesite adresu e-pošte",
     "createaccountmail": "Koristite privremenu, slučajno stvorenu lozinku i pošaljite na navedenu adresu elektronske pošte",
     "createacct-realname": "Pravo ime (opciono)",
     "createaccountreason": "Razlog:",
     "createacct-captcha": "Sigurnosna provera",
     "createacct-imgcaptcha-ph": "Unesite tekst koji vidite iznad",
     "createacct-submit": "Otvori nalog",
+    "createacct-another-submit": "Otvori još jedan nalog",
     "createacct-benefit-heading": "{{SITENAME}} je napravljen od strane ljudi kao što ste vi.",
+    "createacct-benefit-body1": "{{PLURAL:$1|izmena|izmene}}",
+    "createacct-benefit-body2": "{{PLURAL:$1|stranica|stranice}}",
     "createacct-benefit-body3": "skorašnjih {{PLURAL:$1|doprinosa}}",
     "badretype": "Unete lozinke se ne poklapaju.",
     "userexists": "Korisničko ime je zauzeto. Izaberite drugo.",
     "accountcreatedtext": "Korisnički nalog [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|talk]]) je otvoren.",
     "createaccount-title": "Otvaranje korisničkog naloga za {{SITENAME}}",
     "createaccount-text": "Neko je otvorio nalog s vašom e-adresom na {{SITENAME}} ($4) pod imenom $2 i lozinkom $3.\nPrijavite se i promenite svoju lozinku.\n\nAko je ovo greška, zanemarite ovu poruku.",
-    "usernamehasherror": "Korisničko ime ne može sadržati tarabe",
     "login-throttled": "Previše puta ste pokušali da se prijavite. \nMolimo vas da sačekate $1 pre nego što pokušate ponovo.",
     "login-abort-generic": "Neuspešna prijava – prekinuto",
     "loginlanguagelabel": "Jezik: $1",
     "suspicious-userlogout": "Vaš zahtev za odjavu je odbijen jer je poslat od strane neispravnog pregledača ili posrednika.",
+    "createacct-another-realname-tip": "Pravo ime nije obavezno.\nAko izaberete da ga unesete, ono će biti korišćeno za pripisivanje vašeg rada.",
     "pt-login": "Prijavi me",
     "pt-login-button": "Prijavi me",
     "pt-createaccount": "Otvori nalog",
     "pt-userlogout": "Odjavi me",
     "php-mail-error-unknown": "Nepoznata greška u funkciji PHP mail().",
     "user-mail-no-addy": "Pokušali ste da pošaljete poruku bez e-adrese.",
+    "user-mail-no-body": "Pokušano slanje elektronske poruke s praznim ili nerazumno kratkim sadržajem.",
     "changepassword": "Promeni lozinku",
-    "resetpass_announce": "Prijavljeni ste s privremenom lozinkom.\nDa biste završili prijavu, podesite novu lozinku ovde:",
+    "resetpass_announce": "Da biste završili prijavu, podesite novu lozinku ovde.",
     "resetpass_text": "<!-- Ovde unesite tekst -->",
     "resetpass_header": "Promena lozinke naloga",
     "oldpassword": "Stara lozinka:",
     "resetpass-submit-loggedin": "Promeni lozinku",
     "resetpass-submit-cancel": "Otkaži",
     "resetpass-wrong-oldpass": "Neispravna privremena ili tekuća lozinka.\nMožda ste već promenili lozinku ili ste zatražili novu privremenu lozinku.",
+    "resetpass-recycled": "Uneli ste sadašnju lozinku, da bi ste resetovali lozinku morate uneti novu.",
+    "resetpass-temp-emailed": "Prijavili ste se sa privremenim kodom iz e-pošte.\nDa biste završili prijavljivanje morate postaviti novu lozinku ovde:",
     "resetpass-temp-password": "Privremena lozinka:",
+    "resetpass-abort-generic": "Promenu lozinke je sprečio dodatak.",
+    "resetpass-expired": "Vaša lozinka je istekla. Postavite novu lozinku da biste se prijavili.",
+    "resetpass-expired-soft": "Vaša lozinka je istekla i morate postaviti novu. Postavite novu lozinku ili kliknite „{{int:resetpass-submit-cancel}}“ da je postavite kasnije.",
     "passwordreset": "Obnavljanje lozinke",
     "passwordreset-text-one": "Popunite ovaj obrazac da biste resetovali lozinku.",
     "passwordreset-text-many": "{{PLURAL:$1|Ispunite jedno od polja kako bi ste dobili privremenu lozinku na e-poštu.}}",
     "passwordreset-legend": "Poništi lozinku",
     "passwordreset-disabled": "Obnavljanje lozinke je onemogućeno na ovom vikiju.",
+    "passwordreset-emaildisabled": "E-pošta je onemogućena na ovom vikiju.",
     "passwordreset-username": "Korisničko ime:",
     "passwordreset-domain": "Domen:",
     "passwordreset-capture": "Pogledati krajnju poruku?",
     "changeemail-none": "(ništa)",
     "changeemail-submit": "Promeni",
     "changeemail-cancel": "Otkaži",
+    "resettokens-token-label": "$1 (trenutna vrednost: $2)",
     "bold_sample": "Podebljan tekst",
     "bold_tip": "Podebljan tekst",
     "italic_sample": "Iskošeni tekst",
     "copyrightwarning": "Imajte na umu da se svi doprinosi na ovom vikiju smatraju kao objavljeni pod licencom $2 (više na $1).\nAko ne želite da se vaši tekstovi menjaju i razmenjuju bez ograničenja, onda ih ne šaljite ovde.<br />\nIsto tako obećavate da ste vi autor teksta, ili da ste ga umnožili s izvora koji je u javnom vlasništvu.\n'''Ne šaljite radove zaštićene autorskim pravima bez dozvole!'''",
     "copyrightwarning2": "Imajte na umu da se svi doprinosi na ovom vikiju mogu menjati, vraćati ili brisati od drugih korisnika.\nAko ne želite da se vaši tekstovi slobodno menjaju i raspodeljuju, ne šaljite ih ovde.<br />\nIsto tako obećavate da ste vi autor teksta, ili da ste ga umnožili s izvora koji je u javnom vlasništvu (više na $1).\n'''Ne šaljite radove zaštićene autorskim pravima bez dozvole!'''",
     "longpageerror": "'''Greška: tekst koji ste uneli je veličine {{PLURAL:$1|jedan kilobajt|$1 kilobajta|$1 kilobajta}}, što je veće od {{PLURAL:$2|dozvoljenog jednog kilobajta|dozvoljena $2 kilobajta|dozvoljenih $2 kilobajta}}.'''\nStranica ne može biti sačuvana.",
-    "readonlywarning": "'''Upozorenje: baza podataka je zaključana radi održavanja, tako da nećete moći da sačuvate izmene.\nNajbolje bi bilo da umnožite tekst u uređivač teksta i sačuvate ga za kasnije.'''\n\nAdministrator koji je zaključao bazu podataka je naveo sledeće objašnjenje: $1",
+    "readonlywarning": "<strong>Upozorenje: baza podataka je zaključana radi održavanja, tako da trenutno nećete moći da sačuvate izmene.</strong>\nMožda biste želeli sačuvati tekst za kasnije u nekoj tekstualnoj datoteci.\n\nAdministrator koji je zaključao bazu dao je sledeće objašnjenje: $1",
     "protectedpagewarning": "'''Upozorenje: ova stranica je zaštićena, tako da samo administratori mogu da je menjaju.'''\nPoslednja stavka u istoriji je prikazana ispod:",
     "semiprotectedpagewarning": "'''Napomena:''' ova stranica je zaštićena, tako da samo registrovani korisnici mogu da je uređuju.\nPoslednji zapis u dnevniku je prikazan ispod:",
     "cascadeprotectedwarning": "<div style=\"background: #FFBDBD; border: 1px solid #BB7979; color: #000000; font-weight: bold; margin: 2em 0 1em; padding: .5em 1em; vertical-align: middle; clear: both;\">'''Upozorenje:''' Ova stranica je zaštićena tako da je mogu uređivati samo administratori, jer je ona uključena u {{PLURAL:$1|sledeću stranicu koja je|sledeće stranice koje su}} zaštićene „prenosivom“ zaštitom:</div>",
     "content-failed-to-parse": "Ne mogu da raščlanim sadržaj tipa $2 za model $1: $3",
     "invalid-content-data": "Neispravni podaci sadržaja",
     "content-not-allowed-here": "Sadržaj modela „$1“ nije dozvoljen na stranici [[$2]]",
-    "editwarning-warning": "Ako napustite ovu stranicu, izgubićete sve izmene koje ste napravili.\nAko ste prijavljeni, možete onemogućiti ovo upozorenje u svojim podešavanjima, u odeljku „Uređivanje“.",
+    "editwarning-warning": "Ako napustite ovu stranicu, izgubićete sve izmene koje ste napravili.\nAko ste prijavljeni, možete onemogućiti ovo upozorenje u svojim podešavanjima, u odeljku „{{int:prefs-editing}}“.",
     "content-model-wikitext": "vikitekst",
     "content-model-text": "čist tekst",
     "content-model-javascript": "javaskript",
     "undo-failure": "Ova izmena se ne može poništiti zbog konflikta izmena.",
     "undo-norev": "Ne mogu da vratim izmenu jer ne postoji ili je obrisana.",
     "undo-summary": "Poništena izmena $1 {{GENDER:$2|korisnika|korisnice}} [[Special:Contributions/$2|$2]] ([[User talk:$2|razgovor]])",
+    "undo-summary-username-hidden": "Poništi izmenu $1 skrivenog korisnika",
     "cantcreateaccounttitle": "Ne mogu da otvorim nalog",
     "cantcreateaccount-text": "Otvaranje naloga s ove IP adrese ('''$1''') je {{GENDER:$3|blokirao|blokirala|blokirao}} [[User:$3|$3]].\n\nRazlog koji je naveo {{GENDER:$3|korisnik|korisnica|korisnik}} $3 je ''$2''",
     "viewpagelogs": "Pogledaj dnevnike ove stranice",
     "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}})",
     "revdelete-no-file": "Tražena datoteka ne postoji.",
     "revdelete-show-file-confirm": "Želite li da vidite obrisanu izmenu datoteke „<nowiki>$1</nowiki>“ od $2; $3?",
     "revdelete-show-file-submit": "Da",
+    "revdelete-selected-text": "{{PLURAL:$1|Izabrana izmena|Izabrane izmene}} [[:$2]]:",
+    "revdelete-selected-file": "{{PLURAL:$1|Izabrana verzija datoteke|Izabrane verzije datoteke}} [[:$2]]:",
     "logdelete-selected": "{{PLURAL:$1|Izabrana stavka u istoriji|Izabrane stavke u istoriji}}:",
     "revdelete-confirm": "Potvrdite da nameravate ovo uraditi, da razumete posledice i da to činite u skladu s [[{{MediaWiki:Policy-url}}|pravilima]].",
     "revdelete-suppress-text": "Sakrivanje izmena bi trebalo koristiti '''samo''' u sledećim slučajevima:\n* Zlonamerni ili pogrdni podaci\n* Neprikladni lični podaci\n*: ''kućna adresa i broj telefona, broj bankovne kartice itd.''",
     "revdelete-legend": "Ograničenja vidljivosti",
-    "revdelete-hide-text": "sakrij tekst izmene",
+    "revdelete-hide-text": "Tekst revizije",
     "revdelete-hide-image": "Sakrij sadržaj datoteke",
     "revdelete-hide-name": "Sakrij radnju i odredište",
     "revdelete-hide-comment": "Opis izmene",
-    "revdelete-hide-user": "sakrij ime uređivača",
+    "revdelete-hide-user": "Korisnčko ime urednika/IP adresa",
     "revdelete-hide-restricted": "Sakrij podatke od administratora i drugih korisnika",
     "revdelete-radio-same": "(ne menjaj)",
     "revdelete-radio-set": "Sakriveno",
     "preferences": "Podešavanja",
     "mypreferences": "Podešavanja",
     "prefs-edits": "Broj izmena:",
+    "prefsnologintext2": "Morate biti $1 da biste menjali svoja podešavanja.",
     "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",
     "prefs-dateformat": "Format datuma",
     "prefs-timeoffset": "Vremenska razlika",
     "prefs-advancedediting": "Glavna podešavanja",
+    "prefs-editor": "Uređivač",
+    "prefs-preview": "Pretpregled",
     "prefs-advancedrc": "Napredne postavke",
     "prefs-advancedrendering": "Napredne postavke",
     "prefs-advancedsearchoptions": "Napredne postavke",
     "right-unblockself": "odblokiraj samog sebe",
     "right-protect": "promeni nivoe zaštite i uredi stranice sa prenosivom zaštitom",
     "right-editprotected": "uredi stranice pod zaštitom „{{int:protect-level-sysop}}“",
+    "right-editsemiprotected": "uredi stranice pod zaštitom „{{int:protect-level-autoconfirmed}}“",
     "right-editinterface": "uređivanje korisničkog sučelja",
     "right-editusercssjs": "uređivanje tuđih CSS i javaskript datoteka",
     "right-editusercss": "uređivanje tuđih CSS datoteka",
     "right-edituserjs": "uređivanje tuđih javaskript datoteka",
+    "right-viewmyprivateinfo": "vidite svoje lične podatke (npr. adresu e-pošte, pravo ime)",
+    "right-editmyprivateinfo": "uredi svoje lične podatke (npr. adresu e-pošte, pravo ime)",
+    "right-editmyoptions": "uredite svoja podešavanja",
     "right-rollback": "brzo vraćanje izmena poslednjeg korisnika koji je menjao određenu stranicu",
     "right-markbotedits": "označavanje vraćenih izmena kao izmene bota",
     "right-noratelimit": "otpornost na ograničenja",
     "action-userrights-interwiki": "uređivanje korisničkih prava na drugim vikijima",
     "action-siteadmin": "zaključavanje ili otključavanje baze podataka",
     "action-sendemail": "slanje e-poruka",
+    "action-editmywatchlist": "izmeni svoj spisak nadgledanja",
     "nchanges": "$1 {{PLURAL:$1|izmena|izmene|izmena}}",
+    "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|izmena od vaše poslednje posete}}",
+    "enhancedrc-history": "istorija",
     "recentchanges": "Skorašnje izmene",
     "recentchanges-legend": "Postavke skorašnjih izmena",
     "recentchanges-summary": "Pratite skorašnje izmene na ovoj stranici.",
     "upload-permitted": "Dozvoljeni tipovi datoteka: $1.",
     "upload-preferred": "Preporučeni tipovi datoteka: $1.",
     "upload-prohibited": "Zabranjeni tipovi datoteka: $1.",
-    "uploadlog": "dnevnik otpremanja",
     "uploadlogpage": "Dnevnik otpremanja",
     "uploadlogpagetext": "Ispod je spisak skorašnjih slanja.\nPogledajte [[Special:NewFiles|galeriju novih datoteka]] za lepši pregled.",
     "filename": "Naziv datoteke",
     "filereuploadsummary": "Izmene datoteke:",
     "filestatus": "Status autorskog prava:",
     "filesource": "Izvor:",
-    "uploadedfiles": "Poslate datoteke",
     "ignorewarning": "Zanemari upozorenja i sačuvaj datoteku",
     "ignorewarnings": "Zanemari sva upozorenja",
     "minlength1": "Naziv datoteke mora imati barem jedan znak.",
     "overwroteimage": "je poslao novu verziju datoteke „[[$1]]“",
     "uploaddisabled": "Otpremanje je onemogućeno.",
     "copyuploaddisabled": "Slanje putem URL adrese je onemogućeno.",
-    "uploadfromurl-queued": "Slanje je stavljeno na spisak čekanja.",
     "uploaddisabledtext": "Otpremanje datoteka je onemogućeno.",
     "php-uploaddisabledtext": "Slanje datoteka je onemogućeno u PHP-u.\nProverite postavke file_uploads.",
     "uploadscripted": "Datoteka sadrži HTML ili skriptni kod koji može biti pogrešno protumačen od strane pregledača.",
+    "uploadscriptednamespace": "Ova SVG datoteka sadrži pogrešan imenski prostor „$1“",
     "uploadvirus": "Datoteka sadrži virus!\nDetalji: $1",
     "uploadjava": "Datoteka je formata ZIP koji sadrži java .class element.\nSlanje java datoteka nije dozvoljeno jer one mogu izazvati zaobilaženje sigurnosnih ograničenja.",
     "upload-source": "Izvorna datoteka",
     "upload-misc-error": "Nepoznata greška pri slanju datoteke",
     "upload-misc-error-text": "Nepoznata greška pri slanju datoteke.\nProverite da li je adresa ispravna i pokušajte ponovo.\nAko se problem ne reši, kontaktirajte [[Special:ListUsers/sysop|administratora]].",
     "upload-too-many-redirects": "Adresa sadrži previše preusmerenja",
-    "upload-unknown-size": "Nepoznata veličina",
     "upload-http-error": "Došlo je do HTTP greške: $1",
     "upload-copy-upload-invalid-domain": "Primerci otpremanja nisu dostupni na ovom domenu.",
     "backend-fail-stream": "Ne mogu da emitujem datoteku $1.",
     "img-auth-streaming": "Učitavanje „$1“.",
     "img-auth-public": "Svrha img_auth.php je da prosleđuje datoteke iz privatnih vikija.\nOvaj viki je postavljen kao javni.\nRadi sigurnosti, img_auth.php je onemogućen.",
     "img-auth-noread": "Korisnik nema pristup za čitanje „$1“.",
-    "img-auth-bad-query-string": "Adresa ima neispravnu nisku upita.",
     "http-invalid-url": "Neispravna adresa: $1",
     "http-invalid-scheme": "Adrese sa šemom „$1“ nisu podržane.",
     "http-request-error": "HTTP zahtev nije prošao zbog nepoznate greške.",
     "filehist-dimensions": "Dimenzije",
     "filehist-filesize": "Veličina datoteke",
     "filehist-comment": "Komentar",
-    "filehist-missing": "Datoteka nedostaje",
     "imagelinks": "Upotreba datoteke",
     "linkstoimage": "{{PLURAL:$1|Sledeća stranica koristi|$1 sledeće stranice koriste|$1 sledećih stranica koristi}} ovu datoteku:",
     "linkstoimage-more": "Više od $1 {{PLURAL:$1|stranice|stranice|stranica}} je povezano s ovom datotekom.\nSledeći spisak prikazuje samo {{PLURAL:$1|prvu stranicu povezanu|prve $1 stranice povezane|prvih $1 stranica povezanih}} s ovom datotekom.\nDostupan je i [[Special:WhatLinksHere/$2|potpuni spisak]].",
     "unusedtemplateswlh": "ostale veze",
     "randompage": "Slučajna stranica",
     "randompage-nopages": "Nema stranica u {{PLURAL:$2|sledećem imenskom prostoru|sledećim imenskim prostorima}}: $1.",
+    "randomincategory": "Slučajna stranica u kategoriji",
+    "randomincategory-selectcategory-submit": "Idi",
     "randomredirect": "Slučajno preusmerenje",
     "randomredirect-nopages": "Nema preusmerenja u imenskom prostoru „$1”.",
     "statistics": "Statistike",
     "statistics-users-active": "Aktivni korisnici",
     "statistics-users-active-desc": "Korisnici koji su izvršili bar jednu radnju {{PLURAL:$1|prethodni dan|u poslednja $1 dana|u poslednjih $1 dana}}",
     "statistics-mostpopular": "Najposećenije stranice",
+    "pageswithprop": "Strane s osobinom strane",
+    "pageswithprop-legend": "Strane s osobinom strane",
+    "pageswithprop-text": "Ova strana izlistava strane koje imaju određenu osobinu",
     "pageswithprop-prop": "Ime osobine:",
     "pageswithprop-submit": "Idi",
     "doubleredirects": "Dvostruka preusmerenja",
     "mostrevisions": "Stranice s najviše izmena",
     "prefixindex": "Sve stranice s prefiksom",
     "prefixindex-namespace": "Sve stranice s predmetkom (imenski prostor $1)",
+    "prefixindex-strip": "Sakrij prefiks u spisku",
     "shortpages": "Kratke stranice",
     "longpages": "Dugačke stranice",
     "deadendpages": "Stranice bez unutrašnjih veza",
     "emailuser-title-notarget": "Slanje e-poruke korisniku",
     "emailpage": "Slanje e-poruka",
     "emailpagetext": "Možete da koristite donji obrazac da pošaljete e-poruku {{GENDER:$1|ovom korisniku|ovoj korisnici|ovom korisniku|}}.\nE-adresa koju ste uneli u vašim [[Special:Preferences|podešavanjima]] će se prikazati u polju „Od“, tako da će primalac moći da vam odgovori direktno.",
-    "usermailererror": "Došlo je do greške pri slanju poruke:",
     "defemailsubject": "{{SITENAME}} e-adresa {{GENDER:$1|korisnika|korisnice|korisnika}} $1",
     "usermaildisabled": "Korisnička e-pošta je onemogućena",
     "usermaildisabledtext": "Ne možete da šaljete e-poruke drugim korisnicima na ovom vikiju",
     "noemailtitle": "Nema e-adrese",
     "noemailtext": "Ovaj korisnik nije naveo ispravnu e-adresu.",
-    "nowikiemailtitle": "E-pošta nije dozvoljena",
     "nowikiemailtext": "Ovaj korisnik je odlučio da ne prima e-poruke od drugih korisnika.",
     "emailnotarget": "Nepostojeće ili neispravno korisničko ime primaoca.",
     "emailtarget": "Unos korisničkog imena primaoca",
     "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",
     "watching": "Nadgledanje…",
     "unwatching": "Prekidanje nadgledanja…",
     "watcherrortext": "Došlo je do greške pri promeni postavki vašeg spiska nadgledanja za „$1“.",
-    "enotif_mailer": "{{SITENAME}} e-obaveštenje",
     "enotif_reset": "Označi sve stranice kao posećene",
     "enotif_impersonal_salutation": "{{SITENAME}} korisnik",
+    "enotif_subject_deleted": "Stranicu $1 na {{SITENAME}} {{GENDER:$2|obrisao je|obrisala je}} $2",
+    "enotif_subject_created": "Stranicu $1 na {{SITENAME}} {{GENDER:$2|napravio je|napravila je}} $2",
+    "enotif_subject_moved": "Stranicu $1 na {{SITENAME}} {{GENDER:$2|premestio je|premestila je}} $2",
+    "enotif_subject_restored": "Stranicu $1 na {{SITENAME}} {{GENDER:$2|vratio je|vratila je}} $2",
+    "enotif_subject_changed": "Stranicu $1 na {{SITENAME}} {{GENDER:$2|promenio je|promenila je}} $2",
+    "enotif_body_intro_deleted": "Stranicu $1 na {{SITENAME}} {{GENDER:$2|obrisao je|obrisala je}} $2 dana $PAGEEDITDATE. Pogledajte $3.",
+    "enotif_body_intro_created": "Stranicu $1 na {{SITENAME}} {{GENDER:$2|napravio je|napravila je|napravio je}} $2 dana $PAGEEDITDATE. Trenutna izmena nalazi se na $3.",
+    "enotif_body_intro_moved": "Stranicu $1 na {{SITENAME}} {{GENDER:$2|premestio je|premestila je}} $2 dana $PAGEEDITDATE. Trenutna izmena nalazi se na  $3.",
+    "enotif_body_intro_restored": "Stranicu $1 na {{SITENAME}} {{GENDER:$2|vratio je|vratila je|vratio je}} $2 dana $PAGEEDITDATE. Trenutna izmena nalazi se na $3.",
+    "enotif_body_intro_changed": "Stranicu $1 na {{SITENAME}} {{GENDER:$2|promenio je|promenila je|promenio je}} $2 dana $PAGEEDITDATE. Trenutna izmena nalazi se na $3.",
     "enotif_lastvisited": "Pogledajte $1 za sve izmene od vaše poslednje posete.",
     "enotif_lastdiff": "Pogledajte $1 da vidite ovu izmenu.",
     "enotif_anon_editor": "anoniman korisnik $1",
     "excontent": "sadržaj je bio: „$1“",
     "excontentauthor": "sadržaj je bio: „$1“ (a jedini urednik je bio „[[Special:Contributions/$2|$2]]“)",
     "exbeforeblank": "sadržaj pre brisanja je bio: „$1“",
-    "exblank": "stranica je bila prazna",
     "delete-confirm": "Brisanje stranice „$1“",
     "delete-legend": "Obriši",
     "historywarning": "'''Upozorenje:''' stranica koju želite da obrišete ima istoriju s približno $1 {{PLURAL:$1|izmenom|izmene|izmena}}:",
     "importunknownsource": "Nepoznata vrsta za uvoz",
     "importcantopen": "Ne mogu da otvorim datoteku za uvoz",
     "importbadinterwiki": "Neispravna međuviki veza",
-    "importnotext": "Prazno ili bez teksta",
     "importsuccess": "Uvoženje je završeno!",
-    "importhistoryconflict": "Postoji sukobljena izmena u istoriji (možda je ova stranica već uvezena ranije)",
     "importnosources": "Nije određen nijedan međuviki izvor za uvoz, tako da je otpremanje istorije onemogućeno.",
     "importnofile": "Uvozna datoteka nije poslata.",
     "importuploaderrorsize": "Ne mogu da otpremim datoteku za uvoz.\nDatoteka je veća od dozvoljene veličine.",
     "import-error-interwiki": "Ne mogu da uvezem stranicu „$1“ jer je njen naziv rezervisan za spoljno povezivanje (međuviki).",
     "import-error-special": "Ne mogu da uvezem stranicu „$1“ jer ona pripada posebnom imenskom prostoru koje ne prihvata stranice.",
     "import-error-invalid": "Ne mogu da uvezem stranicu „$1“ jer je njen naziv neispravan.",
+    "import-error-unserialize": "Verzija $2 stranice $1 ne može biti pročitana/uvezena. Zapisano je da verzija koristi $3 tip sadržaja u $4 formatu.",
     "import-options-wrong": "{{PLURAL:$2|Pogrešna opcija|Pogrešne opcije}}: <nowiki>$1</nowiki>",
     "import-rootpage-invalid": "Navedena osnovna stranica ima neispravan naslov.",
     "import-rootpage-nosubpage": "Imenski prostor „$1“ osnovne stranice ne dozvoljava podstranice.",
     "tooltip-recreate": "Ponovo napravite stranicu iako je obrisana",
     "tooltip-upload": "Započnite otpremanje",
     "tooltip-rollback": "Opcija „Vrati“ vraća izmene poslednjeg korisnika",
-    "tooltip-undo": "Vraća ovu izmenu i otvara obrazac za uređivanje.",
+    "tooltip-undo": "Poništava ovu izmenu i otvara obrazac za uređivanje.",
     "tooltip-preferences-save": "Sačuvaj postavke",
     "tooltip-summary": "Unesite kratak opis",
     "common.css": "/** CSS postavljen ovde će se odraziti na sve teme */",
     "spam_reverting": "Vraćam na poslednju izmenu koja ne sadrži veze do $1",
     "spam_blanking": "Sve izmene sadrže veze do $1. Čistim",
     "spam_deleting": "Sve izmene sadrže veze do $1. Brišem",
-    "simpleantispam-label": "Provera spama. '''NE''' popunjavaj ovo unutra!",
+    "simpleantispam-label": "Anti-spama provera. \n<strong>NE</strong> popunjavaj ovo unutra!",
     "pageinfo-title": "Podaci o „$1“",
     "pageinfo-not-current": "Nažalost, nemoguće je pribaviti ove podatke za starije izmene.",
     "pageinfo-header-basic": "Osnovni podaci",
     "minutes": "{{PLURAL:$1|$1 minut|$1 minuta|$1 minuta}}",
     "hours": "{{PLURAL:$1|$1 sat|$1 sata|$1 sati}}",
     "days": "{{PLURAL:$1|$1 dan|$1 dana|$1 dana}}",
+    "weeks": "{{PLURAL:$1|$1 sedmica}}",
+    "months": "{{PLURAL:$1|$1 mesec|$1 meseci}}",
     "years": "{{PLURAL:$1|$1 godina|$1 godine}}",
     "ago": "pre $1",
     "just-now": "upravo sad",
+    "hours-ago": "Pre $1 {{PLURAL:$1|sat|sata|sati}}",
     "minutes-ago": "Pre $1 {{PLURAL:$1|minut|minuta}}",
     "bad_image_list": "Format je sledeći:\n\nRazmatraju se samo nabrajanja (redovi koji počinju sa zvezdicom).\nPrva veza u redu mora da bude veza do neispravne datoteke.\nSve daljnje veze u istom redu smatraju se izuzecima.",
     "variantname-zh-hans": "hans",
     "semicolon-separator": ";&#32;",
     "comma-separator": ",&#32;",
     "colon-separator": ":&#32;",
-    "pipe-separator": "&#32;&#32;",
+    "pipe-separator": "&#32;|&#32;",
     "word-separator": "&#32;",
     "ellipsis": "…",
     "percent": "$1%",
index e62ff64..af91034 100644 (file)
     "currentevents": "Tentakalo tanyalo",
     "currentevents-url": "Project:Tentakalo tanyalo",
     "edithelp": "Lusito ngekuhlela",
-    "helppage": "Help:Lokucuketfwe",
     "mainpage": "Likhasi Lelikhulu",
     "mainpage-description": "Likhasi lelikhulu",
     "policy-url": "Project:Umtsetfo",
index 13513d5..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",
index fee1d32..ce1f8dd 100644 (file)
     "permalink": "Permanent länk",
     "print": "Skriv ut",
     "view": "Visa",
+    "view-foreign": "Visa på $1",
     "edit": "Redigera",
+    "edit-local": "Redigera lokal beskrivning",
     "create": "Skapa",
+    "create-local": "Lägg till en lokal beskrivning",
     "editthispage": "Redigera denna sida",
     "create-this-page": "Skapa denna sida",
     "delete": "Radera",
     "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.",
     "accountcreatedtext": "Användarkontot [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|diskussion]]) har skapats.",
     "createaccount-title": "Konto skapat på {{SITENAME}}",
     "createaccount-text": "Någon har skapat ett konto åt din e-postadress på {{SITENAME}} ($4) med namnet \"$2\" och lösenordet \"$3\". Du bör nu logga in och ändra ditt lösenord.\n\nDu kan ignorera detta meddelande om kontot skapats av misstag.",
-    "usernamehasherror": "Användarnamnet får inte innehålla #.",
     "login-throttled": "Du har gjort för många misslyckade inloggningsförsök till det här kontot.\nVänta $1 innan du försöker igen.",
     "login-abort-generic": "Din inloggning misslyckades - Avbröts",
     "loginlanguagelabel": "Språk: $1",
     "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",
     "upload-permitted": "Tillåtna filtyper: $1.",
     "upload-preferred": "Föredragna filtyper: $1.",
     "upload-prohibited": "Förbjudna filtyper: $1.",
-    "uploadlog": "uppladdningslogg",
     "uploadlogpage": "Uppladdningslogg",
     "uploadlogpagetext": "Det här är en logg över de senast uppladdade filerna.\nSe [[Special:NewFiles|galleriet över nya filer]] för en mer visuell översikt.",
     "filename": "Filnamn",
     "filereuploadsummary": "Filändringar:",
     "filestatus": "Upphovsrättslig status:",
     "filesource": "Källa:",
-    "uploadedfiles": "Uppladdade filer",
     "ignorewarning": "Ignorera varningen och spara filen ändå.",
     "ignorewarnings": "Ignorera eventuella varningar",
     "minlength1": "Filens namn måste innehålla minst ett tecken.",
     "overwroteimage": "laddade upp ny version av \"[[$1]]\"",
     "uploaddisabled": "Uppladdningsfunktionen är avstängd",
     "copyuploaddisabled": "Uppladdning med URL avstängt.",
-    "uploadfromurl-queued": "Din uppladdning har lagts i kö.",
     "uploaddisabledtext": "Uppladdning av filer är avstängd.",
     "php-uploaddisabledtext": "PHP filuppladdningar är avaktiverade. Kolla inställningarna för file_uploads.",
     "uploadscripted": "Denna fil innehåller HTML eller script som felaktigt kan komma att tolkas av webbläsare.",
     "upload-misc-error": "Okänt uppladdningsfel",
     "upload-misc-error-text": "Ett okänt fel inträffade under uppladdningen.\nKontrollera att URL:en giltig och tillgänglig och försök igen.\nOm problemet kvarstår, kontakta en [[Special:ListUsers/sysop|administratör]].",
     "upload-too-many-redirects": "URL-en innehöll för många omdirigeringar",
-    "upload-unknown-size": "Okänd storlek",
     "upload-http-error": "Ett HTTP-fel uppstod: $1",
     "upload-copy-upload-invalid-domain": "Uppladdning av kopior är inte tillgängligt från denna domän.",
     "backend-fail-stream": "Kunde inte strömma filen $1.",
     "img-auth-streaming": "Strömmar \"$1\".",
     "img-auth-public": "Funktionaliteten i img_auth.php är att skicka filer från en privat wiki.\nDenna wiki är konfigurerad som en publik wiki.\nFör optimal säkerhet, har img_auth.php blivit avaktiverad.",
     "img-auth-noread": "Användaren har inte tillåtelse att läsa \"$1\"",
-    "img-auth-bad-query-string": "URL-adressen har en ogiltig frågesträng.",
     "http-invalid-url": "Ogiltig URL: $1",
     "http-invalid-scheme": "URLer med \"$1\"-formen stöds inte",
     "http-request-error": "HTTP-begäran misslyckades på grund av okänt fel.",
     "filehist-dimensions": "Dimensioner",
     "filehist-filesize": "Filstorlek",
     "filehist-comment": "Kommentar",
-    "filehist-missing": "Fil saknas",
     "imagelinks": "Filanvändning",
     "linkstoimage": "Följande {{PLURAL:$1|sida|$1 sidor}} länkar till den här filen:",
     "linkstoimage-more": "Mer änr {{PLURAL:$1|en sida|$1 sidor}} länkar till den här filen.\nFöljande lista visar bara {{PLURAL:$1|den första sidan|de $1 första sidorna}} som länkar till filen.\nDet finns en [[Special:WhatLinksHere/$2|fullständig lista]].",
     "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",
+    "listgrouprights-namespaceprotection-header": "Namnrymdsbegränsningar",
+    "listgrouprights-namespaceprotection-namespace": "Namnrymd",
+    "listgrouprights-namespaceprotection-restrictedto": "Rättighet(er) som låter användare redigera",
     "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].",
+    "noindex-category-desc": "Sidan innehåller det magiska ordet <code><nowiki>__NOINDEX__</nowiki></code> (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 <code><nowiki>__INDEX__</nowiki></code> (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 <code>$wgMaxArticleSize</code>, därför har vissa mallar inte expanderats.",
+    "post-expand-template-argument-category-desc": "Efter att ett mallargument (något inom trippla parenteser, som <code>{{{Foo}}})</code> expanderats är denna sidan större än <code>$wgMaxArticleSize</code>.",
+    "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 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.",
+    "hidden-category-category-desc": "Detta är en kategori som innehåller <code><nowiki>__HIDDENCAT__</nowiki></code> 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",
     "emailuser-title-notarget": "E-postanvändare",
     "emailpage": "Skicka e-post till användare",
     "emailpagetext": "Du kan använda formuläret nedan för att skicka e-post till den här {{GENDER:$1|användaren}}.\nDen e-postadress du har angivit i [[Special:Preferences|dina användarinställningar]] kommer att visas som \"Från\"-adress i meddelandet, så att mottagaren har möjlighet att svara direkt till dig.",
-    "usermailererror": "Fel i hanteringen av mail:",
     "defemailsubject": "{{SITENAME}} e-post från användare \"$1\"",
     "usermaildisabled": "Användar-e-post avaktiverat",
     "usermaildisabledtext": "Du kan inte skicka e-post till andra användare på den här wikin",
     "noemailtitle": "Ingen e-postadress",
     "noemailtext": "Den här användaren har inte angivit en giltig e-postadress.",
-    "nowikiemailtitle": "Ingen e-post tillåten",
     "nowikiemailtext": "Den här användaren har valt att inte motta e-post från andra användare.",
     "emailnotarget": "Icke-existerande eller ogiltigt användarnamn för mottagaren.",
     "emailtarget": "Ange mottagarens användarnamn",
     "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",
     "watching": "Bevakar...",
     "unwatching": "Avbevakar...",
     "watcherrortext": "Ett fel inträffade när du ändrade dina bevakningsinställningarna för \"$1\".",
-    "enotif_mailer": "{{SITENAME}}s system för att få meddelanden om förändringar per e-post",
     "enotif_reset": "Markera alla sidor som besökta",
     "enotif_impersonal_salutation": "{{SITENAME}}användare",
     "enotif_subject_deleted": "{{SITENAME}}sidan $1 har raderats av {{gender:$2|$2}}",
     "excontent": "Före radering: \"$1\"",
     "excontentauthor": "innehållet var: \"$1\" (den enda som skrivit var \"[[Special:Contributions/$2|$2]]\")",
     "exbeforeblank": "innehåll före tömning var: \"$1\"",
-    "exblank": "sidan var tom",
     "delete-confirm": "Radera \"$1\"",
     "delete-legend": "Radera",
     "historywarning": "'''Varning:''' Sidan du håller på att radera har en historik med ungefär $1 {{PLURAL:$1|version|versioner}}:",
     "importunknownsource": "Okänd typ av importkälla",
     "importcantopen": "Misslyckades med att öppna importfilen.",
     "importbadinterwiki": "Felaktig interwiki-länk",
-    "importnotext": "Tom eller ingen text",
     "importsuccess": "Importen är genomförd!",
-    "importhistoryconflict": "Det föreligger en konflikt i versionshistoriken (kanske har denna sida importerats tidigare)",
     "importnosources": "Inga källor för transwiki-import har angivits, och direkt uppladdning av historik har stängts av.",
     "importnofile": "Ingen fil att importera har laddats upp.",
     "importuploaderrorsize": "Uppladdningen av importfilen misslyckades. Filen är större än vad som är tillåtet att ladda upp.",
     "print.css": "/* CSS som skrivs här kommer att påverka utskriftsversionen */",
     "noscript.css": "/* CSS som placeras här kommer att påverka användare med JavaScript inaktiverat */",
     "group-autoconfirmed.css": "/* CSS som placeras här kommer bara att påverka bekräftade användare */",
+    "group-user.css": "/* CSS som placeras här kommer bara att påverka registrerade användare */",
     "group-bot.css": "/* CSS som placeras här kommer bara att påverka robotar */",
     "group-sysop.css": "/* CSS som placeras här kommer bara att påverka administratörer */",
     "group-bureaucrat.css": "/* CSS som placeras här kommer bara att påverka byråkrater */",
     "modern.js": "/* JavaScript här kommer att laddas för dem som använder skalet Modern */",
     "vector.js": "/* JavaScript här kommer att laddas för dem som använder skalet Vector */",
     "group-autoconfirmed.js": "/* JavaScript här kommer att laddas för bekräftade användare */",
+    "group-user.js": "/* JavaScript här kommer att laddas för registrerade användare */",
     "group-bot.js": "/* JavaScript här kommer att laddas för robotar */",
     "group-sysop.js": "/* JavaScript här kommer att laddas för administratörer */",
     "group-bureaucrat.js": "/* JavaScript här kommer att laddas för byråkrater */",
index 66dfb0c..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",
index 4b50fa9..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",
index fa0da25..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": "கவனிப்புப் பட்டியலிருந்து நீக்கு",
index 2d3cbe3..1ba88a4 100644 (file)
     "pool-timeout": "తాళం కొరకు వేచివుండడానికి కాలపరిమితి అయిపోయింది",
     "pool-queuefull": "సమూహపు వరుస నిండుగా ఉంది",
     "pool-errorunknown": "తెలియని లోపం",
+    "pool-servererror": "పూల్ కౌంటర్ సేవ అందుబాటులో లేదు ($1).",
     "aboutsite": "{{SITENAME}} గురించి",
     "aboutpage": "Project:గురించి",
     "copyright": "విషయం $1 కి లోబడి లభ్యం, వేరుగా పేర్కొంటే తప్ప.",
     "accountcreatedtext": "[[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|చర్చ]])కి వాడుకరి ఖాతాను సృష్టించాం.",
     "createaccount-title": "{{SITENAME}} కోసం ఖాతా సృష్టి",
     "createaccount-text": "{{SITENAME}} ($4) లో ఎవరో మీ ఈమెయిలు చిరునామాకి \"$2\" అనే పేరుగల ఖాతాని \"$3\" అనే సంకేతపదంతో సృష్టించారు.\nమీరు లోనికి ప్రవేశించి మీ సంకేతపదాన్ని ఇప్పుడే మార్చుకోవాలి.\n\nఈ ఖాతాని పొరపాటున సృష్టిస్తే గనక, ఈ సందేశాన్ని పట్టించుకోకండి.",
-    "usernamehasherror": "వాడుకరిపేరులో హాష్ అక్షరాలు ఉండకూడదు",
     "login-throttled": "కొద్దిసేపటిగా మీరు చాలా లాగిన్ ప్రయత్నాలు చేసారు.\nమళ్ళీ ప్రయత్నించే ముందు $1 ఆగండి.",
     "login-abort-generic": "మీ లాగిన్ ప్రయత్నం విఫలమైంది - ఆగిపోయింది",
     "loginlanguagelabel": "భాష: $1",
     "prefs-skin": "రూపు",
     "skin-preview": "మునుజూడు",
     "datedefault": "ఏదైనా పరవాలేదు",
-    "prefs-beta": "బీటా సౌలభ్యాలు",
     "prefs-datetime": "తేదీ, సమయం",
     "prefs-labs": "ప్రయోగాత్మక సౌలభ్యాలు",
     "prefs-user-pages": "వాడుకరి పేజీలు",
     "upload-permitted": "అనుమతించే ఫైలు రకాలు: $1.",
     "upload-preferred": "అనుమతించే ఫైలు రకాలు: $1.",
     "upload-prohibited": "నిషేధించిన ఫైలు రకాలు: $1.",
-    "uploadlog": "ఎక్కింపుల చిట్టా",
     "uploadlogpage": "ఎక్కింపుల చిట్టా",
     "uploadlogpagetext": "ఇటీవల జరిగిన ఫైలు అప్‌లోడుల జాబితా ఇది.\nమరింత దృశ్యాత్మకంగా చూడటం కోసం [[Special:NewFiles|కొత్త ఫైళ్ళ కొలువు]]కు వెళ్ళండి.",
     "filename": "ఫైలు పేరు",
     "filereuploadsummary": "ఫైలు మార్పులు:",
     "filestatus": "కాపీహక్కు స్థితి:",
     "filesource": "మూలం:",
-    "uploadedfiles": "ఎక్కించిన ఫైళ్ళు",
     "ignorewarning": "హెచ్చరికను పట్టించుకోకుండా ఫైలును భద్రపరచు",
     "ignorewarnings": "హెచ్చరికలను పట్టించుకోవద్దు",
     "minlength1": "పైలు పేర్ల నిడివి కనీసం ఒక్క అక్షరమైనా ఉండాలి.",
     "overwroteimage": "\"[[$1]]\" యొక్క కొత్త కూర్పును ఎక్కించారు",
     "uploaddisabled": "ఎక్కింపులు అచేతనం చెయ్యబడ్డాయి.",
     "copyuploaddisabled": "URL ద్వారా ఎక్కింపుని అశక్తం చేసారు.",
-    "uploadfromurl-queued": "మీ ఎక్కింపు వరుసలో ఉంది.",
     "uploaddisabledtext": "ఫైళ్ళ ఎక్కింపులను అచేతనం చేసారు.",
     "php-uploaddisabledtext": "PHPలో ఫైలు ఎక్కింపులు అచేతనమై ఉన్నాయి.\nదయచేసి file_uploads అమరికని చూడండి.",
     "uploadscripted": "ఈ ఫైల్లో HTML కోడు గానీ స్క్రిప్టు కోడు గానీ ఉంది. వెబ్ బ్రౌజరు దాన్ని పొరపాటుగా అనువదించే అవకాశం ఉంది.",
     "upload-misc-error": "తెలియని ఎక్కింపు లోపం",
     "upload-misc-error-text": "ఎక్కిస్తూండగా ఏదో తెలియని లోపం తలెత్తింది. \nURL సరైనదేనని, అది అందుబాటులోనే ఉందని నిర్ధారించుకుని మళ్ళీ ప్రయత్నించండి. సమస్య అలాగే ఉంటే, [[Special:ListUsers/sysop|నిర్వాహకులు]] ఎవరినైనా సంప్రదించండి.",
     "upload-too-many-redirects": "ఆ URLలో చాలా దారిమార్పులు ఉన్నాయి",
-    "upload-unknown-size": "సైజు తెలియదు",
     "upload-http-error": "ఒక HTTP పొరపాటు జరిగింది: $1",
     "upload-copy-upload-invalid-domain": "ఈ డొమెయిన్ నుంచి కాపీ ఎక్కింపులు కుదరదు.",
     "backend-fail-stream": "\"$1\" ఫైలును స్ట్రీమింగు చెయ్యలేకపోయాం.",
     "img-auth-streaming": "\"$1\" ను ప్రసారిస్తున్నాం.",
     "img-auth-public": "img_auth.php యొక్క పని, గోప్యవికీలనుండి ఫైళ్ళ వివరాలను బయట పెట్టడం.\nఇది బహిరంగ వికీగా తయారుచేయబడింది.\nసరైన భద్రత కోసం, img_auth.php ను అచేతనం చేసాం.",
     "img-auth-noread": "\"$1\"ని చూడడానికి వాడుకరికి అనుమతి లేదు.",
-    "img-auth-bad-query-string": "ఈ URL లో తప్పుడు క్వెరీ స్ట్రింగు ఉంది.",
     "http-invalid-url": "చెల్లని URL: $1",
     "http-invalid-scheme": "\"$1\" ప్రణాళికలో ఉన్న URLలకు తోడ్పాటులేదు",
     "http-request-error": "తెలియని లోపం వల్ల HTTP అభ్యర్థన విఫలమైంది.",
     "filehist-dimensions": "కొలతలు",
     "filehist-filesize": "దస్త్రపు పరిమాణం",
     "filehist-comment": "వ్యాఖ్య",
-    "filehist-missing": "ఫైలు కనిపించుటలేదు",
     "imagelinks": "దస్త్రపు వాడుక",
     "linkstoimage": "కింది {{PLURAL:$1|పేజీ|$1 పేజీల}} నుండి ఈ ఫైలుకి లింకులు ఉన్నాయి:",
     "linkstoimage-more": "ఈ ఫైలుకు $1 కంటే ఎక్కువ {{PLURAL:$1|పేజీ లింకై ఉంది|పేజీలు లింకై ఉన్నాయి}}.\nఈ ఫైలుకి మాత్రమే లింకై ఉన్న {{PLURAL:$1|మొదటి పేజీని|మొదటి $1 పేజీలను}} ఈ క్రింది జాబితా చూపిస్తుంది.\n[[Special:WhatLinksHere/$2|పూర్తి జాబితా]] కూడా ఉంది.",
     "unwatchedpages": "వీక్షణలో లేని పేజీలు",
     "listredirects": "దారిమార్పుల జాబితా",
     "listduplicatedfiles": "నకళ్ళు కలిగిన ఫైళ్ళ జాబితా",
+    "listduplicatedfiles-summary": "ఇది ఒక ఫైలు యొక్క సరికొత్త సంచిక మరొక ఫైలు యొక్క సరికొత్త సంచికతో సమానంగా ఉండే నకిలీ ఫైళ్ళ జాబితా. స్థానిక ఫైళ్ళు మాత్రమే పరిగణించబడ్డాయి.",
     "listduplicatedfiles-entry": "[[:File:$1|$1]] కు [[$3|{{PLURAL:$2|ఓ నకలు ఉంది|$2 నకళ్ళున్నాయి}}]].",
     "unusedtemplates": "వాడని మూసలు",
     "unusedtemplatestext": "వేరే ఇతర పేజీలలో చేర్చని {{ns:template}} పేరుబరిలోని పేజీలన్నింటినీ ఈ పేజీ చూపిస్తుంది.\nమూసలను తొలగించే ముందు వాటికి ఉన్న ఇతర లింకుల కోసం చూడడం గుర్తుంచుకోండి.",
     "listgrouprights-addgroup-self-all": "అన్ని సమూహాలని స్వంత ఖాతాకు చేర్చుకోలగడటం",
     "listgrouprights-removegroup-self-all": "స్వంత ఖాతా నుండి అన్ని సమూహాలనూ తొలగించుకోగలగడం",
     "trackingcategories-name": "సందేశం పేరు",
+    "trackingcategories-nodesc": "వివరణ లేదు.",
     "trackingcategories-disabled": "వర్గం అచేతనమై ఉంది",
     "mailnologin": "పంపించవలసిన చిరునామా లేదు",
     "mailnologintext": "ఇతరులకు ఈ-మెయిలు పంపించాలంటే, మీరు [[Special:UserLogin|లాగిన్‌]] అయి ఉండాలి, మరియు మీ [[Special:Preferences|అభిరుచుల]]లో సరైన ఈ-మెయిలు చిరునామా ఇచ్చి ఉండాలి.",
     "emailuser-title-notarget": "వాడుకరికి ఈమెయిలు పంపించండి",
     "emailpage": "వాడుకరికి ఈ-మెయిలుని పంపించు",
     "emailpagetext": "ఈ {{GENDER:$1|వాడుకరికి}} ఈమెయిలు సందేశము పంపించుటకు క్రింది ఫారంను ఉపయోగించవచ్చు. [[Special:Preferences|మీ వాడుకరి అభిరుచుల]]లో మీరిచ్చిన ఈ-మెయిలు చిరునామా \"నుండి\" ఆ సందేశం వచ్చినట్లుగా ఉంటుంది, కనుక వేగుని అందుకునేవారు నేరుగా మీకు జవాబివ్వగలుగుతారు.",
-    "usermailererror": "మెయిలు ఆబ్జెక్టు ఈ లోపాన్ని చూపింది:",
     "defemailsubject": "వాడుకరి \"$1\" నుండి {{SITENAME}} ఈ-మెయిలు",
     "usermaildisabled": "వాడుకరి ఈమెయిలు అచేతనం చెయ్యబడింది",
     "usermaildisabledtext": "ఈ వికీలో మీరు ఇతర వాడుకరులకి ఈ-మెయిళ్ళని పంపించలేరు",
     "noemailtitle": "ఈ-మెయిలు చిరునామా లేదు",
     "noemailtext": "ఈ వాడుకరి సరైన ఈ-మెయిలు చిరునామాని ఇవ్వలేదు.",
-    "nowikiemailtitle": "ఈమెయిలుకు అనుమతి లేదు",
     "nowikiemailtext": "ఇతర వాడుకరుల నుండి ఈ-మెయిళ్ళను అందుకోడానికి ఈ వాడుకరి సుముఖంగా లేరు.",
     "emailnotarget": "గ్రహీతగా ఇచ్చిన వాడుకరిపేరు తప్పైనా కావచ్చు, లేదా అసలే ఉండి ఉండకపోవచ్చు",
     "emailtarget": "అందుకొనేవారి వాడుకరిపేరు ఇవ్వండి",
     "nowatchlist": "మీ వీక్షణ జాబితా ఖాళీగా ఉంది.",
     "watchlistanontext": "మీ వీక్షణ జాబితా లోని అంశాలను చూసేందుకు లేదా మార్చేందుకు మీరు $1.",
     "watchnologin": "లాగిన్‌ అయిలేరు",
-    "watchnologintext": "మీ వీక్షణ జాబితాను మార్చడానికి మీరు [[Special:UserLogin|లాగిన్‌]] అయి ఉండాలి.",
     "addwatch": "వీక్షణ జాబితాలో చేర్చు",
     "addedwatchtext": "\"[[:$1]]\" అనే పుట మీ [[Special:Watchlist|వీక్షణ జాబితా]]లో చేరింది.\nభవిష్యత్తులో ఈ పుటకి మరియు సంబంధిత చర్చాపుటకి జరిగే మార్పులు అక్కడ కనిపిస్తాయి.",
     "removewatch": "వీక్షణ జాబితా నుండి తొలగించు",
     "watching": "గమనిస్తున్నారు...",
     "unwatching": "గమనించడం లేదు...",
     "watcherrortext": "\"$1\" కు మీ సెట్టింగులను మార్చేటపుడు ఏదో లోపం దొర్లింది.",
-    "enotif_mailer": "{{SITENAME}} ప్రకటన మెయిలు పంపునది",
     "enotif_reset": "అన్ని పేజీలను చూసినట్లుగా గుర్తించు",
     "enotif_impersonal_salutation": "{{SITENAME}} వాడుకరి",
     "enotif_subject_deleted": "{{SITENAME}} $1 పేజీని $2 {{GENDER:$2|తొలగించారు}}",
     "excontent": "ఉన్న విషయ సంగ్రహం: '$1'",
     "excontentauthor": "ఉన్న విషయ సంగ్రహం: \"$1\" (మరియు దీని ఒకే ఒక్క రచయిత \"[[Special:Contributions/$2|$2]]\")",
     "exbeforeblank": "ఖాళీ చెయ్యకముందు పేజీలో ఉన్న విషయ సంగ్రహం: '$1'",
-    "exblank": "పేజీ ఖాళీగా ఉంది",
     "delete-confirm": "\"$1\"ని తొలగించు",
     "delete-legend": "తొలగించు",
     "historywarning": "'''హెచ్చరిక''': మీరు తొలగించబోయే పేజీకి సుమారు $1 {{PLURAL:$1|కూర్పుతో|కూర్పులతో}} చరిత్ర ఉంది:",
     "importunknownsource": "దిగుమతి చేసుకుంటున్న దాని మాతృక రకం తెలియదు",
     "importcantopen": "దిగుమతి చేయబోతున్న ఫైలును తెరవలేకపోతున్నాను",
     "importbadinterwiki": "చెడు అంతర్వికీ లింకు",
-    "importnotext": "ఖాళీ లేదా పాఠ్యం లేదు",
     "importsuccess": "దిగుమతి పూర్తయ్యింది!",
-    "importhistoryconflict": "కూర్పుల చరిత్రలో ఘర్షణ తలెత్తింది (ఈ పేజీని ఇంతకు ముందే దిగుమతి చేసుంటారు)",
     "importnosources": "No transwiki import sources have been defined and direct history uploads are disabled.\nఎటువంటి అంతర్వికీ దిగుమతి మూలాలను పేర్కొనకపోవటం వలన, ప్రత్యక్ష చరిత్ర అప్లోడులను నిలిపివేశాం.",
     "importnofile": "ఎటువంటి దిగుమతి ఫైలునూ అప్లోడుచేయలేదు.",
     "importuploaderrorsize": "దిగుమతి ఫైలు అప్లోడు ఫలించలేదు. ఈ ఫైలు అప్లోడు ఫైలుకు నిర్దేశించిన పరిమాణం కంటే పెద్దా ఉంది.",
index 49d3d33..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": "Назар кардан",
index ff6d9ca..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",
index bda8a57..970d6b6 100644 (file)
     "tog-hidepatrolled": "ซ่อนการแก้ไขที่ตรวจแล้วในหน้าปรับปรุงล่าสุด",
     "tog-newpageshidepatrolled": "ซ่อนหน้าที่ตรวจแล้วจากรายการหน้าใหม่",
     "tog-extendwatchlist": "ขยายรายการเฝ้าดูให้แสดงการเปลี่ยนแปลงทั้งหมด ไม่เพียงการเปลี่ยนแปลงล่าสุด",
-    "tog-usenewrc": "à¸\88ัà¸\94à¸\81ลุà¹\88มà¸\84วามเปลี่ยนแปลงแบ่งตามหน้าในรายการปรับปรุงล่าสุดและรายการเฝ้าดู",
+    "tog-usenewrc": "à¸\88ัà¸\94à¸\81ลุà¹\88มà¸\81ารเปลี่ยนแปลงแบ่งตามหน้าในรายการปรับปรุงล่าสุดและรายการเฝ้าดู",
     "tog-numberheadings": "ใส่เลขหัวข้อในสารบัญอัตโนมัติ",
     "tog-showtoolbar": "แสดงแถบเครื่องมือแก้ไข",
     "tog-editondblclick": "แก้ไขหน้าเมื่อดับเบิลคลิก",
-    "tog-editsectiononrightclick": "à¹\80à¸\9bิà¸\94à¹\83à¸\8aà¹\89à¸\87าà¸\99à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¹\80à¸\89à¸\9eาะสà¹\88วà¸\99à¹\82à¸\94ยà¸\84ลิà¸\81à¸\82วาà¸\97ีà¹\88หัวà¸\82à¹\89อ",
+    "tog-editsectiononrightclick": "à¹\80à¸\9bิà¸\94à¹\83à¸\8aà¹\89à¸\87าà¸\99à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¹\80à¸\89à¸\9eาะสà¹\88วà¸\99à¹\82à¸\94ยà¸\84ลิà¸\81à¸\82วาà¸\97ีà¹\88à¸\8aืà¹\88อà¹\80รืà¹\88อà¸\87à¸\82อà¸\87สà¹\88วà¸\99à¸\99ัà¹\89à¸\99",
     "tog-rememberpassword": "จำการล็อกอินของฉันในเบราว์เซอร์นี้ (สูงสุด $1 วัน)",
     "tog-watchcreations": "เพิ่มหน้าที่ฉันสร้างและไฟล์ที่ฉันอัปโหลดเข้ารายการเฝ้าดู",
     "tog-watchdefault": "เพิ่มหน้าและไฟล์ที่ฉันแก้ไขเข้ารายการเฝ้าดู",
     "tog-watchmoves": "เพิ่มและไฟล์ที่ฉันเปลี่ยนชื่อเข้ารายการเฝ้าดู",
     "tog-watchdeletion": "เพิ่มหน้าและไฟล์ที่ฉันลบเข้ารายการเฝ้าดู",
     "tog-minordefault": "กำหนดให้การแก้ไขทุกครั้งเป็นการแก้ไขเล็กน้อยโดยปริยาย",
-    "tog-previewontop": "à¹\81สà¸\94à¸\87à¸\95ัวอยà¹\88าà¸\87à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¸\81à¹\88อนกล่องแก้ไข",
+    "tog-previewontop": "à¹\81สà¸\94à¸\87à¸\95ัวอยà¹\88าà¸\87à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¸\9aนกล่องแก้ไข",
     "tog-previewonfirst": "แสดงตัวอย่างการแก้ไขสำหรับการแก้ไขครั้งแรก",
     "tog-enotifwatchlistpages": "อีเมลหาเมื่อหน้าหรือไฟล์ในรายการเฝ้าดูมีการเปลี่ยนแปลง",
     "tog-enotifusertalkpages": "อีเมลหาเมื่อหน้าคุยกับผู้ใช้ของฉันมีการเปลี่ยนแปลง",
     "tog-diffonly": "ไม่แสดงเนื้อหาใต้ส่วนต่างการแก้ไข",
     "tog-showhiddencats": "แสดงหมวดหมู่ที่ซ่อนอยู่",
     "tog-norollbackdiff": "ไม่แสดงการเปลี่ยนแปลงหลังดำเนินการย้อนกลับฉุกเฉิน",
-    "tog-useeditwarning": "เตือนฉัน เมื่อฉันกำลังจะออกจากหน้าแก้ไขโดยมีข้อมูลที่ยังไม่ได้บันทึก",
+    "tog-useeditwarning": "เตือนฉันเมื่อออกหน้าแก้ไขโดยมีการเปลี่ยนแปลงที่ยังไม่บันทึก",
     "tog-prefershttps": "ใช้การเชื่อมต่อปลอดภัยทุกครั้งเมื่อล็อกอิน",
     "underline-always": "ทุกครั้ง",
     "underline-never": "ไม่",
-    "underline-default": "à¸\84à¹\88าà¹\82à¸\94ยà¸\9bริยายของหน้าตาหรือเบราว์เซอร์",
+    "underline-default": "à¸\84à¹\88าà¸\95ัà¹\89à¸\87à¸\95à¹\89à¸\99ของหน้าตาหรือเบราว์เซอร์",
     "editfont-style": "รูปแบบชุดแบบอักษรในพื้นที่แก้ไข:",
     "editfont-default": "ค่าตั้งต้นของเบราว์เซอร์",
     "editfont-monospace": "ชุดอักษรแบบความกว้างคงที่",
     "category_header": "หน้าในหมวดหมู่ \"$1\"",
     "subcategories": "หมวดหมู่ย่อย",
     "category-media-header": "สื่อในหมวดหมู่ \"$1\"",
-    "category-empty": "''ปัจจุบันหมวดหมู่นี้ไม่มีหน้าหรือสื่อใด''",
+    "category-empty": "<em>ปัจจุบันหมวดหมู่นี้ไม่มีหน้าหรือสื่อใด</em>",
     "hidden-categories": "{{PLURAL:$1|หมวดหมู่ที่ซ่อนอยู่|หมวดหมู่ที่ซ่อนอยู่}}",
     "hidden-category-category": "หมวดหมู่ที่ซ่อนอยู่",
     "category-subcat-count": "{{PLURAL:$2|หมวดหมู่นี้มีหมวดหมู่ย่อยเพียงหมวดหมู่เดียว|หมวดหมู่นี้มี {{PLURAL:$1|หมวดหมู่ย่อย|$1 หมวดหมู่ย่อย}} จากทั้งหมด $2 หมวดหมู่}}",
     "print": "พิมพ์",
     "view": "ดู",
     "edit": "แก้ไข",
+    "edit-local": "แก้ไขคำอธิบายท้องถิ่น",
     "create": "สร้าง",
+    "create-local": "เพิ่มคำอธิบายท้องถิ่น",
     "editthispage": "แก้ไขหน้านี้",
     "create-this-page": "สร้างหน้านี้",
     "delete": "ลบ",
     "currentevents-url": "Project:เหตุการณ์ปัจจุบัน",
     "disclaimers": "ข้อปฏิเสธความรับผิดชอบ",
     "disclaimerpage": "Project:ข้อปฏิเสธความรับผิดชอบทั่วไป",
-    "edithelp": "วิà¸\98ีà¹\81à¸\81à¹\89à¹\84à¸\82หà¸\99à¹\89า",
+    "edithelp": "à¸\84ำอà¸\98ิà¸\9aายà¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82",
     "mainpage": "หน้าหลัก",
     "mainpage-description": "หน้าหลัก",
     "policy-url": "Project:นโยบาย",
     "cannotdelete": "ไม่สามารถลบหน้าหรือไฟล์ \"$1\" \nอาจมีผู้อื่นลบไปแล้ว",
     "cannotdelete-title": "ไม่สามารถลบหน้า ''$1''",
     "delete-hook-aborted": "การลบถูกฮุกยกเลิก\nโดยไม่มีคำอธิบาย",
+    "no-null-revision": "ไม่สามารถสร้างรุ่นว่างใหม่ของหน้า \"$1\"",
     "badtitle": "ใช้ชื่อเรื่องนี้ไม่ได้",
     "badtitletext": "ชื่อหน้าที่ขอไม่ถูกต้อง เป็นชื่อว่าง หรือชื่อข้ามภาษาหรือข้ามวิกิที่เชื่อมโยงไม่ถูกต้อง\nอาจมีอักขระที่ไม่สามารถใช้ในชื่อเรื่องได้",
     "perfcached": "ข้อมูลต่อไปนี้ถูกเก็บในแคช และอาจล้าสมัย มีผลการค้นหาสูงสุด $1 รายการในแคช",
     "accountcreatedtext": "บัญชีผู้ใช้สำหรับ [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|พูดคุย]]) ได้สร้างขึ้นแล้ว",
     "createaccount-title": "สร้างบัญชีสำหรับ {{SITENAME}}",
     "createaccount-text": "มีบางคนสร้างบัญชีโดยใช้ที่อยู่อีเมลของคุณบน {{SITENAME}} ($4) โดยใช้ชื่อ \"$2\" และรหัสผ่าน \"$3\" คุณควรล็อกอินเพื่อเปลี่ยนรหัสผ่านทันที\n\nคุณอาจเพิกเฉยข้อความนี้ หากการสร้างบัญชีนี้เกิดจากความผิดพลาด",
-    "usernamehasherror": "ชื่อผู้ใช้ต้องไม่มีอักขระแฮช",
     "login-throttled": "ที่ผ่านมาคุณพยายามล็อกอินมากครั้งเกินไป\nกรุณารอ $1 ก่อนลองอีกครั้ง",
     "login-abort-generic": "การเข้าสู่ระบบของคุณไม่ประสบความสำเร็จ - ล้มเลิกแล้ว",
     "loginlanguagelabel": "ภาษา: $1",
     "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 กิโลไบต์ จึงไม่สามารถบันทึกได้'''",
     "postedit-confirmation": "บันทึกการแก้ไขของคุณแล้ว",
     "edit-already-exists": "ไม่สามารถสร้างหน้าใหม่ได้\nเพราะมีหน้านี้แล้ว",
     "defaultmessagetext": "ข้อความสารโดยปริยาย",
+    "content-failed-to-parse": "แจงส่วนเนื้อหา $2 ของตัวแบบ $1 ล้มเหลว: $3",
     "invalid-content-data": "ข้อมูลเนื้อหาไม่ถูกต้อง",
     "content-not-allowed-here": "เนื้อหา \"$1\" ไม่อนุญาตในหน้า [[$2]]",
     "editwarning-warning": "การออกจากหน้านี้อาจทำให้ความเปลี่ยนแปลงที่คุณดำเนินการสูญหาย\nถ้าคุณล็อกอินแล้ว คุณสามารถปิดคำเตือนนี้ได้ที่ส่วน \"{{int:prefs-editing}}\" ในการตั้งค่าของคุณ",
     "editpage-notsupportedcontentformat-title": "รูปแบบเนื้อหาไม่ได้รับการรองรับ",
+    "editpage-notsupportedcontentformat-text": "ตัวแบบเนื้อหา $2 ไม่รองรับตัวแบบเนื้อหา $1",
     "content-model-wikitext": "ข้อความวิกิ",
     "content-model-text": "ข้อความธรรมดา",
     "content-model-javascript": "จาวาสคริปต์",
     "parser-template-loop-warning": "ตรวจพบแม่แบบกลับมาเรียกตัวเอง: [[$1]]",
     "parser-template-recursion-depth-warning": "เรียกแม่แบบซ้อนหลายชั้นเกินขีดจำกัด ($1)",
     "language-converter-depth-warning": "คำสั่งในการแปลงภาษาลึกเกิน $1 ลำดับ",
+    "expansion-depth-exceeded-category": "หน้าที่ความลึกการขยายเกิน",
+    "expansion-depth-exceeded-warning": "หน้าเกินความลึกการขยาย",
+    "parser-unstrip-loop-warning": "พบวงวน unstrip",
+    "parser-unstrip-recursion-limit": "ขีดจำกัดการเรียกซ้ำ unstrip เกิน ($1)",
     "undo-success": "การแก้ไขนี้สามารถย้อนกลับได้ กรุณาตรวจสอบข้อแตกต่างด้านล่างให้แน่ใจว่านี่คือสิ่งที่คุณต้องการทำ จากนั้นให้บันทึกการเปลี่ยนแปลงด้านล่างเพื่อเสร็จสิ้นขั้นตอน",
     "undo-failure": "การแก้ไขนี้ไม่สามารถย้อนกลับได้ เนื่องจากขัดแย้งกับการแก้ไขปัจจุบัน",
     "undo-norev": "ไม่สามารถย้อนการแก้ไขนี้ เพราะไม่มีหรือถูกลบไปแล้ว",
     "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": "หน้าผู้ใช้",
     "yourrealname": "ชื่อจริง:",
     "yourlanguage": "ภาษา:",
     "yourvariant": "อักษรต่างรูปของเนื้อหา:",
+    "prefs-help-variant": "รูปแปรหรืออักขรวิธีที่คุณเลือกให้แสดงหน้าเนื้อหาของวิกินี้",
     "yournick": "ลายเซ็น:",
     "prefs-help-signature": "ความเห็นในหน้าพูดคุยควรลงลายเซ็นด้วย \"<nowiki>~~~~</nowiki>\" ซึ่งจะถูกแปลงเป็นลายเซ็นของคุณและตราเวลา",
     "badsig": "ลายเซ็นดิบไม่ถูกต้อง ให้ตรวจสอบแท็กเอชทีเอ็มแอล",
     "prefs-dateformat": "รูปแบบวันที่และเวลา",
     "prefs-timeoffset": "ส่วนต่างเวลา",
     "prefs-advancedediting": "ตัวเลือกทั่วไป",
+    "prefs-editor": "ตัวแก้ไข",
     "prefs-preview": "การแสดงตัวอย่าง",
     "prefs-advancedrc": "ตัวเลือกขั้นสูง",
     "prefs-advancedrendering": "ตัวเลือกขั้นสูง",
     "prefs-tokenwatchlist": "โทเค็น",
     "prefs-diffs": "ผลต่าง",
     "prefs-help-prefershttps": "การตั้งค่านี้จะมีผลเมื่อคุณล็อกอินครั้งถัดไป",
+    "prefs-tabs-navigation-hint": "แนะนำ: คุณสามารถใช้แป้นลูกศรซ้ายและขวาเพื่อนำทางระหว่างแถบในรายการแถบได้",
     "email-address-validity-valid": "ที่อยู่อีเมลดูถูกต้อง",
     "email-address-validity-invalid": "ป้อนที่อยู่อีเมลที่ถูกต้อง",
     "userrights": "บริหารสิทธิผู้ใช้",
     "upload-permitted": "ชนิดไฟล์ที่อนุญาต: $1",
     "upload-preferred": "ชนิดไฟล์ที่ควรใช้: $1",
     "upload-prohibited": "ชนิดไฟล์ที่ไม่อนุญาต: $1",
-    "uploadlog": "ปูมการอัปโหลด",
     "uploadlogpage": "ปูมการอัปโหลด",
     "uploadlogpagetext": "ด้านล่างเป็นรายการการอัปโหลดไฟล์ล่าสุด\nดูภาพรวมที่ [[Special:NewFiles|แกลอรีไฟล์ใหม่]]",
     "filename": "ชื่อไฟล์",
     "filereuploadsummary": "เปลี่ยนแปลงไฟล์:",
     "filestatus": "สถานะลิขสิทธิ์:",
     "filesource": "แหล่งที่มา:",
-    "uploadedfiles": "ไฟล์ที่อัปโหลดแล้ว",
     "ignorewarning": "บันทึกไฟล์โดยละเลยคำเตือน",
     "ignorewarnings": "ละเลยคำเตือนทั้งหมด",
     "minlength1": "ชื่อไฟล์ต้องมีตัวอักษรอย่างน้อยหนึ่งตัว",
     "overwroteimage": "อัปโหลดรุ่นใหม่ของ \"[[$1]]\"",
     "uploaddisabled": "ปิดใช้งานการอัปโหลด",
     "copyuploaddisabled": "ปิดใช้งานการอัปโหลดโดยยูอาร์แอล",
-    "uploadfromurl-queued": "การอัปโหลดของคุณถูกจัดคิวแล้ว",
     "uploaddisabledtext": "ปิดใช้งานการอัปโหลดไฟล์",
     "php-uploaddisabledtext": "เปิดการใช้งานการอัปโหลดไฟล์ในพีเอชพี\nกรุณาตรวจสอบการตั้งค่า file_uploads",
     "uploadscripted": "ไฟล์นี้มีส่วนประกอบของโค้ดเอชทีเอ็มแอลหรือสคริปต์ ซึ่งอาจก่อให้เกิดความผิดพลาดในการแสดงผลของเว็บเบราว์เซอร์",
     "upload-misc-error": "เกิดความผิดพลาดในการอัปโหลดโดยไม่ทราบสาเหตุ",
     "upload-misc-error-text": "เกิดความผิดพลาดไม่ทราบสาเหตุระหว่างอัปโหลด กรุณาตรวจสอบว่ายูอาร์แอลนั้นถูกต้องและเข้าถึงได้ และลองอีกครั้ง ถ้ายังมีปัญหา ให้ติดต่อ[[Special:ListUsers/sysop|ผู้ดูแลระบบ]]",
     "upload-too-many-redirects": "ยูอาร์แอลที่ระบุมีการเปลี่ยนทางมากเกินไป",
-    "upload-unknown-size": "ไม่ทราบขนาด",
     "upload-http-error": "เกิดข้อผิดพลาดเอชทีทีพี: $1",
     "upload-copy-upload-invalid-domain": "การอัปโหลดสำเนาไม่สามารถทำได้จากโดเมนนี้",
     "backend-fail-backup": "ไม่สามารถสำรองข้อมูลไฟล์ $1.",
     "img-auth-streaming": "กำลังดึงข้อมูล \"$1\"",
     "img-auth-public": "ฟังก็ชันของ img_auth.php คือเพื่อส่งไฟล์ขาออกจากวิกิส่วนตัว\nวิกินี้ถูกกำหนดเป็นวิกิส่วนตัว\nเพื่อความปลอดภัยสูงสุด img_auth.php จึงถูกปิด",
     "img-auth-noread": "ผู้ใช้ไม่ได้รับสิทธิ์ในการอ่าน \"$1\"",
-    "img-auth-bad-query-string": "ที่อยู่ URL ดังกล่าวมีชุดข้อความสตริงก์ที่ร้องขอไม่ถูกต้อง",
     "http-invalid-url": "ยูอาร์แอลไม่ถูกต้อง: $1",
     "http-invalid-scheme": "ไม่สนับสนุนยูอาร์แอลที่มีรูปแบบ \"$1\"",
     "http-request-error": "คำขอข้อมูล HTTP ผิดพลาดโดยไม่ทราบสาเหตุ",
     "filehist-dimensions": "ขนาด",
     "filehist-filesize": "ขนาดไฟล์",
     "filehist-comment": "ความเห็น",
-    "filehist-missing": "ไฟล์หายไป",
     "imagelinks": "การใช้ไฟล์",
     "linkstoimage": "มี $1 หน้าเชื่อมโยงมายังไฟล์นี้:",
     "linkstoimage-more": "ไฟล์นี้มีหน้าเชื่อมโยงมากว่า $1 หน้า\nรายการต่อไปนี้แสดงการเชื่อมโยง $1 หน้าแรกที่มายังไฟล์นี้เท่านั้น\nดูเพิ่มได้ที่[[Special:WhatLinksHere/$2|รายการเต็ม]]",
     "listgrouprights-removegroup-self": "ลบ{{PLURAL:$2|กลุ่ม|กลุ่ม}}ออกจากบัญชี: $1",
     "listgrouprights-addgroup-self-all": "เพิ่มทุกกลุ่มเข้าไปในบัญชีนี้",
     "listgrouprights-removegroup-self-all": "นำทุกกลุ่มออกจากบัญชีนี้",
+    "hidden-category-category-desc": "นี่คือหมวดหมู่ที่ติด <code><nowiki>__HIDDENCAT__</nowiki></code> ซึ่งป้องกันมิให้แสดงในกล่องลิงก์หมวดหมู่ในหน้าโดยปริยาย",
     "mailnologin": "ไม่มีที่อยู่ส่ง",
     "mailnologintext": "คุณต้อง[[Special:UserLogin|ล็อกอิน]]และมีที่อยู่อีเมลที่สมเหตุสมผลใน[[Special:Preferences|การตั้งค่า]]ของคุณ ในการส่งอีเมลหาผู้ใช้อื่น",
     "emailuser": "ส่งอีเมลหาผู้ใช้นี้",
     "emailuser-title-notarget": "อีเมลผู้ใช้",
     "emailpage": "อีเมลผู้ใช้",
     "emailpagetext": "คุณสามารถใช้แบบด้านล่างส่งอีเมลหา{{GENDER:$1|ผู้ใช้}}นี้\nที่อยู่อีเมลที่คุณกรอกใน[[Special:Preferences|การตั้งค่าส่วนตัวของคุณ]]จะปรากฏเป็นที่อยู่ \"จาก\" ของอีเมล ซึ่งผู้รับสามารถตอบกลับคุณได้โดยตรง",
-    "usermailererror": "การส่งอีเมลผิดพลาด:",
     "defemailsubject": "อีเมล{{SITENAME}}จากผู้ใช้ \"$1\"",
     "usermaildisabled": "ปิดใช้งานการส่งอีเมลหาผู้ใช้",
     "usermaildisabledtext": "คุณไม่สามารถส่งอีเมลหาผู้ใช้อื่นบนวิกินี้",
     "noemailtitle": "ไม่มีที่อยู่อีเมล",
     "noemailtext": "ผู้ใช้คนนี้ระบุที่อยู่อีเมลไม่ถูกต้อง",
-    "nowikiemailtitle": "ไม่อนุญาตให้ใช้อีเมล",
     "nowikiemailtext": "ผู้ใช้คนนี้เลือกไม่รับอีเมลจากผู้ใช้อื่น",
     "emailnotarget": "ไม่มีชื่อผู้ใช้ของผู้รับหรือชื่อผู้ใช้ไม่ถูกต้อง",
     "emailtarget": "กรอกชื่อผู้ใช้ของผู้รับ",
     "nowatchlist": "ไม่มีรายการในรายการเฝ้าดูของคุณ",
     "watchlistanontext": "กรุณา$1เพื่อดูหรือแก้ไขรายการในรายการเฝ้าดูของคุณ",
     "watchnologin": "ยังไม่ได้ล็อกอิน",
-    "watchnologintext": "ต้อง[[Special:UserLogin|ล็อกอิน]]เพื่อแก้ไขรายการเฝ้าดูของคุณ",
     "addwatch": "เพิ่มเข้ารายการเฝ้าดู",
     "addedwatchtext": "หน้า \"[[:$1]]\" ได้เพิ่มลงใน[[Special:Watchlist|รายการเฝ้าดู]]ของคุณแล้ว การเปลี่ยนแปลงในหน้านี้หรือหน้าพูดคุยที่เกี่ยวข้องจะแสดงในรายการดังกล่าว",
     "removewatch": "นำออกจากรายการเฝ้าดู",
     "watching": "เฝ้าดู...",
     "unwatching": "เลิกเฝ้าดู...",
     "watcherrortext": "เกิดข้อผิดพลาดขณะเปลี่ยนแปลงการตั้งค่ารายการเฝ้าดูของคุณ เพราะ \"$1\"",
-    "enotif_mailer": "แจ้งการแก้ไขจาก {{SITENAME}}",
     "enotif_reset": "ทำเครื่องหมายว่าชมทุกหน้าแล้ว",
     "enotif_impersonal_salutation": "ผู้ใช้{{SITENAME}}",
     "enotif_subject_deleted": "หน้า $1 บน {{SITENAME}} ถูกลบโดย {{gender:$2|$2}}",
     "excontent": "เนื้อหาเดิม: '$1'",
     "excontentauthor": "เนื้อหาเดิม: '$1' (และมีผู้เขียนคนเดียวคือ '[[Special:Contributions/$2|$2]]')",
     "exbeforeblank": "เนื้อหาก่อนถูกทำว่างคือ: '$1'",
-    "exblank": "หน้าว่าง",
     "delete-confirm": "ลบ \"$1\"",
     "delete-legend": "ลบ",
     "historywarning": "'''คำเตือน:'''' หน้าที่คุณกำลังลบมีประวัติการแก้ไขประมาณ $1 {{PLURAL:$1|รุ่น}}:",
     "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": "หน้า:",
     "importunknownsource": "ไม่ทราบชนิดของไฟล์นำเข้า",
     "importcantopen": "ไม่สามารถเปิดไฟล์นำเข้าได้",
     "importbadinterwiki": "ลิงก์ข้ามภาษาเสีย",
-    "importnotext": "ไฟล์ว่างหรือไฟล์ไม่มีข้อความ",
     "importsuccess": "นำเข้าไฟล์สำเร็จ!",
-    "importhistoryconflict": "มีประวัติรุ่นขัดแย้งกัน (อาจเคยนำเข้าหน้านี้มาก่อน)",
     "importnosources": "ไม่มีการกำหนดแหล่งนำเข้าข้ามวิกิ และการอัปโหลดประวัติหน้าโดยตรงถูกปิดการใช้งาน",
     "importnofile": "ไฟล์นำเข้าไม่ได้ถูกอัปโหลด",
     "importuploaderrorsize": "อัปโหลดไฟล์ข้อมูลนำเข้าไม่สำเร็จ\nขนาดไฟล์ใหญ่เกินกว่าที่อนุญาตไว้",
index f740937..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",
index 0b749be..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",
index af3a128..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ı",
     "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",
index 6ba0a2e..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": "Күзәтү",
index 74280f1..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ü",
index d58831b..c2591b8 100644 (file)
     "jumptosearch": "утчан",
     "currentevents": "Выль иворъёс",
     "currentevents-url": "Project:Выль иворъёс",
-    "helppage": "Help:Валэктон",
     "mainpage": "Кутскон бам",
     "mainpage-description": "Кутскон бам",
     "portal": "Сообщество",
index dcbb42d..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": "كۆزەت تىزىملىكىدىن چىقىرىۋەت",
index 1b54494..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": "Видалити зі списку спостереження",
index 9c71cfa..f249faf 100644 (file)
@@ -1,6 +1,15 @@
 {
     "@metadata": {
-        "authors": []
+        "authors": [
+            "Abdulla",
+            "Akmalzhon",
+            "Casual",
+            "CoderSI",
+            "Lyncos",
+            "Nataev",
+            "Sociologist",
+            "Xexdof"
+        ]
     },
     "tog-underline": "Havolalarning tagiga chizish:",
     "tog-hideminor": "Yangi oʻzgarishlar roʻyxatida kichik tahrirlarni yashirish",
     "prefs-skin": "Tashqi ko‘rinishi",
     "skin-preview": "Ko‘rib chiqish",
     "datedefault": "Farqi yoʻq",
-    "prefs-beta": "Beta-imkoniyatlar",
     "prefs-datetime": "Sana va vaqt",
     "prefs-labs": "Tajribaviy imkoniyatlar",
     "prefs-user-pages": "Foydalanuvchi sahifalari",
     "recentchanges-label-plusminus": "Sahifa vazni qanchaga oʻzgargani (bayt)",
     "recentchanges-legend-heading": "'''Izoh:'''",
     "recentchanges-legend-newpage": "([[Special:NewPages|alohida roʻyxat]])",
-    "rcnotefrom": "Quyida <strong>$2</strong>dan boshlab boʻlgan oʻzgarishlar keltirilgan (<strong>$1</strong>dan koʻp boʻlmaganlari koʻrsatildi).",
-    "rclistfrom": "$1 dan boshlab yangi oʻzgarishlarni koʻrsat.",
+    "rcnotefrom": "Quyida <strong>$2</strong> dan boshlab boʻlgan oʻzgarishlar keltirilgan (<strong>$1</strong> tasi koʻrsatildi).",
+    "rclistfrom": "$3, $2 dan boshlab yangi oʻzgarishlarni koʻrsat.",
     "rcshowhideminor": "Kichik tahrirlarni $1",
     "rcshowhidebots": "Botlarni $1",
+    "rcshowhidebots-show": "koʻrsat",
+    "rcshowhidebots-hide": "yashir",
     "rcshowhideliu": "Roʻyxatdan oʻtgan foydalanuvchilarni $1",
+    "rcshowhideliu-show": "koʻrsat",
+    "rcshowhideliu-hide": "yashir",
     "rcshowhideanons": "Anonim foydalanuvchilarni $1",
+    "rcshowhideanons-show": "koʻrsat",
+    "rcshowhideanons-hide": "yashir",
     "rcshowhidepatr": "Tekshirilgan tahrirlarni $1",
     "rcshowhidemine": "Oʻz tahrirlarimni $1",
     "rclinks": "Oxirgi $2 kun ichida sodir boʻlgan $1 ta oʻzgarish koʻrsatildi<br />$3",
     "filereuploadsummary": "Fayldagi oʻzgarishlar:",
     "filestatus": "Tarqatish shartlari:",
     "filesource": "Manba:",
-    "uploadedfiles": "Yuklangan fayllar",
     "ignorewarnings": "Ogohlantirishlarga eʼtibor qilma",
     "uploadedimage": "\"[[$1]]\"ni yukladi",
     "overwroteimage": "\"[[$1]]\"ning yangi versiyasini yukladi",
     "filehist-dimensions": "Oʻlchamlari",
     "filehist-filesize": "Fayl hajmi",
     "filehist-comment": "Izoh",
-    "filehist-missing": "Fayl mavjud emas",
     "imagelinks": "Fayllarga ishoratlar",
     "linkstoimage": "Bu faylga quyidagi {{PLURAL:$1|sahifa|$1 sahifalar}} bogʻlangan:",
     "nolinkstoimage": "Bu faylga bogʻlangan sahifalar yoʻq.",
     "emailuser-title-target": "Ushbu {{GENDER:$1|foydalanuvchi}}ga maktub joʻnatish",
     "emailuser-title-notarget": "Foydalanuvchiga elektron maktub yozish",
     "emailpage": "Foydalanuvchiga maktub",
-    "usermailererror": "Elektron pochta xabarini joʻnatishda xatolik yuz berdi:",
     "defemailsubject": "{{SITENAME}} — $1 tomonidan maktub",
     "usermaildisabled": "Foydalanuvchi elektron pochtasi o‘chirilgan",
     "noemailtitle": "Elektron pochta manzili mavjud emas",
     "noemailtext": "Bu foydalanuvchi e-mail manzil koʻrsatgani yoʻq.",
-    "nowikiemailtitle": "Maktub joʻnatishga ruxsat yoʻq",
     "emailtarget": "Oluvchi ishtirokchining ismini kiriting",
     "emailusername": "Foydalanuvchi nomi:",
     "emailusernamesubmit": "Jo'natish",
     "watchlist-options": "Kuzatuv roʻyxati moslamalari",
     "watching": "Kuzatish...",
     "unwatching": "Kuzatuv ro'yxatidan o'chirish...",
-    "enotif_mailer": "{{SITENAME}} Pochta orqali e'lon qilish xizmati",
     "enotif_reset": "Hammasini koʻrib chiqilgan deb belgilash",
     "enotif_impersonal_salutation": "{{SITENAME}} ishtirokchisi",
     "enotif_subject_deleted": "{{SITENAME}} loyihasining $1 nomli sahifasi foydalanuvchi {{gender:$2|$2}} tomonidan o‘chirildi",
     "deletepage": "Sahifani o'chirish",
     "confirm": "Tasdiqlash",
     "excontent": "tarkibi: \"$1\"",
-    "exblank": "sahifa boʻsh edi",
     "delete-confirm": "$1 — oʻchirish",
     "delete-legend": "O‘chirish",
     "actioncomplete": "Bajarildi",
     "whatlinkshere-prev": "{{PLURAL:$1|oldingi}} $1",
     "whatlinkshere-next": "{{PLURAL:$1|keyingi}} $1",
     "whatlinkshere-links": "← ishoratlar",
-    "whatlinkshere-hideredirs": "$1 qayta yo'naltirishlar",
+    "whatlinkshere-hideredirs": "Qayta yoʻnaltirishlarni $1",
     "whatlinkshere-hidetrans": "$1 kiritmalar",
     "whatlinkshere-hidelinks": "$1 havolalar",
     "whatlinkshere-hideimages": "$1 fayllar uchun havolalar",
     "revertmove": "qaytarish",
     "delete_and_move": "O‘chirish va qayta nomlash",
     "delete_and_move_confirm": "Ha, ushbu sahifa o‘chirilsin",
+    "move-leave-redirect": "Qayta yoʻnaltirish qoldirish",
     "move-over-sharedrepo": "== Fayl allaqachon mavjud ==\nUmumiy omborda [[:$1]] mavjud. Faylning bu nomga qayta nomlanishi faylning umumiy omborda to‘silishiga olib keladi.",
     "export": "Sahifalar eksporti",
     "export-submit": "Eksport",
index 34c0e8a..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",
index 47ef0bb..6479d7d 100644 (file)
     "permalink": "Liên kết thường trực",
     "print": "In",
     "view": "Xem",
+    "view-foreign": "Xem trên $1",
     "edit": "Sửa đổi",
+    "edit-local": "Sửa đổi miêu tả địa phương",
     "create": "Tạo",
+    "create-local": "Thêm miêu tả địa phương",
     "editthispage": "Sửa đổi trang này",
     "create-this-page": "Tạo trang này",
     "delete": "Xóa",
     "pool-timeout": "Hết thời gian chờ đợi khóa",
     "pool-queuefull": "Đầy hàng đợi khối ứng dụng (pool queue)",
     "pool-errorunknown": "Lỗi lạ",
+    "pool-servererror": "Dịch vụ chia việc xử lý (pool counter) không có sẵn ($1).",
     "aboutsite": "Giới thiệu {{SITENAME}}",
     "aboutpage": "Project:Giới thiệu",
     "copyright": "Nội dung được phát hành theo $1, ngoại trừ khi có ghi chú khác.",
     "accountcreatedtext": "Tài khoản thành viên cho [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|thảo luận]]) đã được mở.",
     "createaccount-title": "Tài khoản mới tại {{SITENAME}}",
     "createaccount-text": "Ai đó đã tạo một tài khoản với tên $2 tại {{SITENAME}} ($4). Mật khẩu của \"$2\" là \"$3\". Bạn nên đăng nhập và đổi mật khẩu ngay bây giờ.\n\nXin hãy bỏ qua thông điệp này nếu tài khoản này không phải do bạn tạo ra.",
-    "usernamehasherror": "Tên người dùng không thể chứa dấu rào",
     "login-throttled": "Bạn đã hết quyền thử mật khẩu tài khoản này vì bạn đã nhập sai quá nhiều. Xin hãy đợi $1 rồi hãy thử lại.",
     "login-abort-generic": "Thất bại khi đăng nhập",
     "loginlanguagelabel": "Ngôn ngữ: $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",
     "upload-permitted": "Các định dạng tập tin được phép tải lên: $1.",
     "upload-preferred": "Các định dạng tập tin nên dùng: $1.",
     "upload-prohibited": "Các định dạng tập tin bị cấm: $1.",
-    "uploadlog": "nhật trình tải lên",
     "uploadlogpage": "Nhật trình tải lên",
     "uploadlogpagetext": "Dưới đây là danh sách các tập tin đã tải lên gần nhất.\nXem [[Special:NewFiles|trang trưng bày các tập tin mới]] để xem trực quan hơn.",
     "filename": "Tên tập tin",
     "filereuploadsummary": "Các thay đổi của tập tin:",
     "filestatus": "Tình trạng bản quyền:",
     "filesource": "Nguồn:",
-    "uploadedfiles": "Tập tin đã tải",
     "ignorewarning": "Bỏ qua cảnh báo và lưu tập tin",
     "ignorewarnings": "Bỏ qua cảnh báo",
     "minlength1": "Tên tập tin phải có ít nhất một ký tự.",
     "overwroteimage": "đã tải lên một phiên bản mới của “[[$1]]”",
     "uploaddisabled": "Chức năng tải lên đã bị khóa.",
     "copyuploaddisabled": "Chức năng tải lên từ địa chỉ URL đã bị tắt.",
-    "uploadfromurl-queued": "Tập tin của bạn đã được xếp vào hàng đợi tải lên.",
     "uploaddisabledtext": "Chức năng tải tập tin đã bị tắt.",
     "php-uploaddisabledtext": "Việc tải tập tin trong PHP đã bị tắt. Xin hãy kiểm tra lại thiết lập file_uploads.",
     "uploadscripted": "Tập tin này có chứa mã HTML hoặc kịch bản có thể khiến trình duyệt web thông dịch sai.",
     "upload-misc-error": "Có lỗi lạ khi tải lên",
     "upload-misc-error-text": "Có lỗi lạ khi tải lên.\nXin hãy xác nhận lại địa chỉ URL là hợp lệ và có thể truy cập được không rồi thử lại lần nữa.\nNếu vẫn còn bị lỗi, xin hãy liên hệ với một [[Special:ListUsers/sysop|bảo quản viên]].",
     "upload-too-many-redirects": "URL có quá nhiều đổi hướng",
-    "upload-unknown-size": "Không rõ kích thước",
     "upload-http-error": "Xảy ra lỗi HTTP: $1",
     "upload-copy-upload-invalid-domain": "Không có sẵn các bản sao tải lên tại tên miền này.",
     "backend-fail-stream": "Không thể gửi luồng tập tin $1.",
     "img-auth-streaming": "Đang truyền “$1”.",
     "img-auth-public": "Chức năng của img_auth.php là xuất tập tin từ wiki cá nhân.\nWiki này được cấu hình là wiki công cộng.\nVì lý do bảo mật, img_auth.php đã bị tắt.",
     "img-auth-noread": "Người dùng không đủ quyền truy cập để đọc “$1”.",
-    "img-auth-bad-query-string": "URL có một chuỗi truy vấn không hợp lệ.",
     "http-invalid-url": "URL không hợp lệ: $1",
     "http-invalid-scheme": "Không hỗ trợ các URL có mô hình “$1”",
     "http-request-error": "Có lỗi lạ khi gửi yêu cầu HTTP.",
     "filehist-dimensions": "Kích cỡ",
     "filehist-filesize": "Kích thước tập tin",
     "filehist-comment": "Miêu tả",
-    "filehist-missing": "Không thấy tập tin",
     "imagelinks": "Các trang sử dụng tập tin",
     "linkstoimage": "{{PLURAL:$1|Trang|$1 trang}} sau có liên kết đến tập tin này:",
     "linkstoimage-more": "Có hơn $1 {{PLURAL:$1|trang|trang}} liên kết đến tập tin này.\nDanh sách dưới đây chỉ hiển thị {{PLURAL:$1|liên kết đầu tiên|$1 liên kết đầu tiên}} đến tập tin này.\nCó [[Special:WhatLinksHere/$2|danh sách đầy đủ ở đây]].",
     "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.",
+    "noindex-category-desc": "Trang này không được các robot đánh chỉ mục vì trang có từ thần chú <code><nowiki>__NOINDEX__</nowiki></code> và nằm trong không gian tên cho phép từ thần chú này.",
+    "index-category-desc": "Trang này có từ thần chú <code><nowiki>__INDEX__</nowiki></code> 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á <code>$wgMaxArticleSize</code>, 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ụ <code>{{{Thí dụ}}}</code>), trang này sẽ vượt quá <code>$wgMaxArticleSize</code>.",
     "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.",
+    "hidden-category-category-desc": "Thể loại này có <code><nowiki>__HIDDENCAT__</nowiki></code>, 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ư",
     "emailuser-title-notarget": "Gửi thư cho người dùng",
     "emailpage": "Gửi thư",
     "emailpagetext": "{{GENDER:$1}}Mẫu dưới đây sẽ gửi một bức thư điện tử tới người dùng này.\nĐịa chỉ thư điện tử mà bạn đã cung cấp trong [[Special:Preferences|tùy chọn cá nhân của mình]] sẽ xuất hiện trong phần địa chỉ “Người gửi” của bức thư, do đó người nhận sẽ có thể trả lời trực tiếp cho bạn.",
-    "usermailererror": "Lỗi gửi thư:",
     "defemailsubject": "Thư của người dùng \"$1\" tại {{SITENAME}}",
     "usermaildisabled": "Chức năng gửi thư cho người dùng đã bị tắt.",
     "usermaildisabledtext": "Bạn không thể gửi thư điện tử cho những người dùng khác trên wiki này.",
     "noemailtitle": "Không có địa chỉ nhận thư",
     "noemailtext": "Người này không cung cấp một địa chỉ thư hợp lệ.",
-    "nowikiemailtitle": "Không cho phép thư điện tử",
     "nowikiemailtext": "Thành viên này quyết định không nhận thư từ các thành viên khác.",
     "emailnotarget": "Người nhận không tồn tại hoặc tên hiệu không hợp lệ.",
     "emailtarget": "Nhập tên hiệu của người nhận",
     "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",
     "watching": "Đang theo dõi…",
     "unwatching": "Đang ngừng theo dõi…",
     "watcherrortext": "Lỗi xảy ra khi theo dõi hoặc ngừng theo dõi “$1”.",
-    "enotif_mailer": "Thông báo của {{SITENAME}}",
     "enotif_reset": "Đánh dấu đã xem mọi trang",
     "enotif_impersonal_salutation": "thành viên {{SITENAME}}",
     "enotif_subject_deleted": "Trang $1 tại {{SITENAME}} đã được xóa bởi $2.",
     "excontent": "nội dung cũ: “$1”",
     "excontentauthor": "nội dung cũ: “$1” (người viết duy nhất “[[Special:Contributions/$2|$2]]”)",
     "exbeforeblank": "nội dung trước khi tẩy trống: “$1”",
-    "exblank": "trang trắng",
     "delete-confirm": "Xóa “$1”",
     "delete-legend": "Xóa",
     "historywarning": "'''Cảnh báo:''' Trang bạn sắp xóa đã có lịch sử khoảng $1 {{PLURAL:$1|phiên bản|phiên bản}}:",
     "importunknownsource": "Không hiểu nguồn trang để nhập vào",
     "importcantopen": "Không có thể mở tập tin để nhập vào",
     "importbadinterwiki": "Liên kết liên wiki sai",
-    "importnotext": "Trang trống hoặc không có nội dung",
     "importsuccess": "Nhập thành công!",
-    "importhistoryconflict": "Có mâu thuẫn trong lịch sử của các phiên bản (trang này có thể đã được nhập vào trước đó)",
     "importnosources": "Không có nguồn nhập giữa wiki và việc nhập lịch sử bị tắt.",
     "importnofile": "Không tải được tập tin nào lên.",
     "importuploaderrorsize": "Không thể tải tập tin nhập trang. Tập tin lớn hơn kích thước cho phép tải lên.",
index 8938efa..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",
index d55e0ec..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ä",
index e79017a..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",
index bb5694f..60007df 100644 (file)
     "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",
index a43965a..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": "אַראָפּנעמען פון דער אויפֿפאַסונג ליסטע",
index 93dbb48..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ó",
index e6121aa..76677a8 100644 (file)
@@ -14,7 +14,8 @@
             "William915",
             "Wong128hk",
             "Xiaomingyan",
-            "Yfdyh000"
+            "Yfdyh000",
+            "Cwek"
         ]
     },
     "tog-underline": "連結加底線:",
     "accountcreatedtext": "$1嘅戶口起好咗。",
     "createaccount-title": "響{{SITENAME}}度開個新戶口",
     "createaccount-text": "有人響{{SITENAME}}度用咗你個電郵開咗個名叫 \"$2\" 嘅新戶口 ($4),密碼係 \"$3\" 。你應該而家登入,改埋個密碼。\n\n如果個戶口係開錯咗嘅話,你可以唔埋呢篇信。",
-    "usernamehasherror": "用戶名唔可以包含切細字元",
     "login-throttled": "你已經試咗太多次登入動作。請等多一陣再試過。",
     "loginlanguagelabel": "語言:$1",
     "suspicious-userlogout": "你去登出嘅要求已經拒絕咗,因為佢可能由壞咗嘅瀏覽器或者快取代理傳送。",
     "prefs-skin": "畫面",
     "skin-preview": "預覽",
     "datedefault": "冇喜好",
-    "prefs-beta": "試緊嘅特色",
     "prefs-datetime": "日期同埋時間",
     "prefs-labs": "實驗性嘅特色",
     "prefs-personal": "用戶簡介",
     "upload-permitted": "准許嘅檔案類型: $1。",
     "upload-preferred": "建議嘅檔案類型: $1。",
     "upload-prohibited": "禁止嘅檔案類型: $1。",
-    "uploadlog": "上載日誌",
     "uploadlogpage": "上載日誌",
     "uploadlogpagetext": "以下係最近檔案上載嘅一覽表。\n睇[[Special:NewFiles|新圖像畫廊]]去睇更詳細嘅總覽。",
     "filename": "檔名",
     "filereuploadsummary": "檔案改變:",
     "filestatus": "版權狀態:",
     "filesource": "來源:",
-    "uploadedfiles": "上載檔案中",
     "ignorewarning": "總要忽略警告同埋儲存檔案",
     "ignorewarnings": "忽略任何警告",
     "minlength1": "檔名必須最少要有一個字。",
     "overwroteimage": "已經上載咗\"[[$1]]\"嘅新版本",
     "uploaddisabled": "上載已停用。",
     "copyuploaddisabled": "由URL嘅上載已經停用。",
-    "uploadfromurl-queued": "你嘅上載已經開始排隊。",
     "uploaddisabledtext": "檔案上載已經停用。",
     "php-uploaddisabledtext": "PHP 檔案上載已經停用。請檢查 file_uploads 設定。",
     "uploadscripted": "呢個檔案包含可能會誤被瀏覽器解釋執行嘅 HTML 或 script 代碼。",
     "upload-misc-error": "未知嘅上載錯誤",
     "upload-misc-error-text": "響上載時發生咗未知嘅錯誤。請確認輸入咗嘅URL係可以訪問嘅,之後再試多一次。如果重有問題嘅話,請聯絡一位[[Special:ListUsers/sysop|管理員]]。",
     "upload-too-many-redirects": "個URL有太多跳轉",
-    "upload-unknown-size": "未知嘅大細",
     "upload-http-error": "一個HTTP錯誤發生咗: $1",
     "backend-fail-notexists": "檔案$1唔存在。",
     "backend-fail-delete": "刪唔到檔案「$1」。",
     "filehist-dimensions": "尺寸",
     "filehist-filesize": "檔案大細",
     "filehist-comment": "註解",
-    "filehist-missing": "檔案遺失",
     "imagelinks": "檔案用途",
     "linkstoimage": "以下嘅$1個頁面連結到呢個檔案:",
     "linkstoimage-more": "多過$1版連過去呢個檔案。\n下面嘅表只係列示咗連去呢個檔案嘅最頭$1版。\n一個[[Special:WhatLinksHere/$2|完整嘅表]]可以提供。",
     "emailuser": "發電郵畀呢位用戶",
     "emailpage": "發電郵畀用戶",
     "emailpagetext": "你可以用下面嘅表去寄一封電郵畀呢位用戶。\n你喺[[Special:Preferences|你嘅用戶喜好設定]]入面填寫嘅電郵地址會出現喺呢封電郵「由」嘅地址度,以便收件人可以回覆到。",
-    "usermailererror": "目標郵件地址返回錯誤:",
     "defemailsubject": "{{SITENAME}} 電郵",
     "usermaildisabled": "用戶電郵已停用",
     "usermaildisabledtext": "你唔可以發送電郵到響呢個wiki度嘅其他用戶",
     "noemailtitle": "無電郵地址",
     "noemailtext": "呢個用戶重未指定一個有效嘅電郵地址。",
-    "nowikiemailtitle": "唔容許電郵",
     "nowikiemailtext": "呢位用戶揀咗唔收其他用戶畀佢嘅電郵。",
     "email-legend": "寄電郵畀另一位{{SITENAME}}用戶",
     "emailfrom": "由:",
     "nowatchlist": "你嘅監視清單度並冇任何項目。",
     "watchlistanontext": "請先$1去睇或者改響你監視清單度嘅項目。",
     "watchnologin": "未登入",
-    "watchnologintext": "你必須先[[Special:UserLogin|登入]]至可以更改你嘅監視清單。",
     "addedwatchtext": "頁面「[[:$1]]」已加入到你嘅[[Special:Watchlist|監視清單]]度。\n呢個頁面以及佢個討論頁以後嘅修改都會列喺嗰度,佢喺[[Special:RecentChanges|最近更改清單]]度會以'''粗體'''顯示,等你可以容易啲睇到佢。",
     "removedwatchtext": "頁面「[[:$1]]」已經喺[[Special:Watchlist|你嘅監視清單]]度刪除。",
     "watch": "監視",
     "watchlist-options": "監視清單選項",
     "watching": "監視緊...",
     "unwatching": "唔再監視緊...",
-    "enotif_mailer": "{{SITENAME}}通知郵遞員",
     "enotif_reset": "將所有頁面標成已視察",
     "enotif_impersonal_salutation": "{{SITENAME}}用戶",
     "enotif_lastvisited": "你上次視察以嚟嘅修改請睇$1。",
     "excontent": "內容係:「$1」",
     "excontentauthor": "內容係:「$1」 (而且唯一嘅貢獻者係「[[Special:Contributions/$2|$2]]」)",
     "exbeforeblank": "喺清空之前嘅內容係:「$1」",
-    "exblank": "頁面之前係空嘅",
     "delete-confirm": "刪除\"$1\"",
     "delete-legend": "刪除",
     "historywarning": "警告:你要刪除嘅頁面有大約$1次嘅修訂:",
     "ipblocklist-submit": "搵",
     "ipblocklist-localblock": "本地封鎖",
     "ipblocklist-otherblocks": "其他{{PLURAL:$1|封鎖|封鎖}}",
-    "infiniteblock": "不設期限",
+    "infiniteblock": "期限",
     "expiringblock": "$1 $2 期滿",
     "anononlyblock": "只限匿名",
     "noautoblockblock": "自動封鎖已經停用",
     "importunknownsource": "不明嘅倒入來源類型",
     "importcantopen": "唔能夠開個倒入檔案",
     "importbadinterwiki": "壞嘅跨 wiki 連結",
-    "importnotext": "空白或者唔係文字",
     "importsuccess": "已經完成倒入!",
-    "importhistoryconflict": "存在有衝突嘅歷史版本(之前可能曾經倒入過呢頁)",
     "importnosources": "未定義 transwiki 嘅匯入來源,同埋歷史嘅直接上載已經停用。",
     "importnofile": "冇上載到任何要倒入嘅檔案。",
     "importuploaderrorsize": "上載要倒入嘅檔案失敗。個檔案大過可以容許嘅上載大細。",
index 1b9f7c3..3405680 100644 (file)
     "disclaimers": "gangjmingz mienxcwz",
     "disclaimerpage": "Project:Itbuen mienxcwz",
     "edithelp": "Caeuq mungz san-zonz",
-    "helppage": "Help:moegloeg",
     "mainpage": "Yiebdaeuz",
     "mainpage-description": "Yiebdeauz",
     "policy-url": "Project:fuengcim",
diff --git a/languages/i18n/zh-cn.json b/languages/i18n/zh-cn.json
deleted file mode 100644 (file)
index 3eef3dc..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Liangent",
-            "PhiLiP",
-            "Shizhao",
-            "Wong128hk",
-            "Xiaomingyan"
-        ]
-    },
-    "tog-norollbackdiff": "进行回退后略过差异比较",
-    "mytalk": "我的讨论页",
-    "portal": "社区专页",
-    "editing": "正在编辑 $1"
-}
index be3db6a..68188eb 100644 (file)
     "tog-shownumberswatching": "显示监视用户数",
     "tog-oldsig": "当前签名:",
     "tog-fancysig": "将签名视为维基文本(不自动生成链接)",
-    "tog-uselivepreview": "使用实时预览(实验中)",
+    "tog-uselivepreview": "使用实时预览(测试)",
     "tog-forceeditsummary": "未输入编辑摘要时提醒我",
     "tog-watchlisthideown": "隐藏监视列表中的我的编辑",
     "tog-watchlisthidebots": "隐藏监视列表中的机器人编辑",
     "permalink": "永久链接",
     "print": "打印",
     "view": "查看",
+    "view-foreign": "在$1查看",
     "edit": "编辑",
+    "edit-local": "编辑本地说明",
     "create": "创建",
+    "create-local": "加入本地说明",
     "editthispage": "编辑本页",
     "create-this-page": "创建本页",
     "delete": "删除",
     "privacypage": "Project:隐私权政策",
     "badaccess": "权限错误",
     "badaccess-group0": "你被禁止执行你刚才请求的操作。",
-    "badaccess-groups": "你刚才请求的操作只对属于{{PLURAL:$2|该用户组|这些用户组}}的用户开放:$1",
+    "badaccess-groups": "您刚才请求的操作只对以下$2个用户组开放:$1。",
     "versionrequired": "需要$1版本的MediaWiki",
     "versionrequiredtext": "使用本页需要$1版本的MediaWiki。请见[[Special:Version|版本页面]]。",
     "ok": "确定",
     "sort-descending": "降序",
     "sort-ascending": "升序",
     "nstab-main": "页面",
-    "nstab-user": "用户页",
+    "nstab-user": "用户页",
     "nstab-media": "媒体文件页面",
     "nstab-special": "特殊页面",
     "nstab-project": "项目页面",
     "virus-badscanner": "错误的配置:未知的病毒扫描程序:''$1''",
     "virus-scanfailed": "扫描失败(代码 $1)",
     "virus-unknownscanner": "未知的反病毒软件:",
-    "logouttext": "<strong>你现在已经退出登录。</strong>\n\n请注意,某些页面可能在你清除你的浏览器缓存之前,继续显示你处于登录状态。",
+    "logouttext": "<strong>您现在已经退出登录。</strong>\n\n请注意一些页面可能仍然显示您处于登录状态,直到您清空浏览器缓存为止。",
     "welcomeuser": "欢迎,$1!",
     "welcomecreation-msg": "你的账户已创建。请不要忘记更改你的[[Special:Preferences|{{SITENAME}}设置]]。",
     "yourname": "用户名:",
     "userlogin-resetlink": "忘记你的登录信息?",
     "userlogin-resetpassword-link": "忘记密码?",
     "userlogin-helplink2": "登录帮助",
-    "userlogin-loggedin": "æ\82¨å·²ç»\8f以{{GENDER:$1|$1}}ç\9a\84身份ç\99»å½\95ã\80\82使ç\94¨ä»¥ä¸\8b表格以其他用户的身份登录。",
+    "userlogin-loggedin": "æ\82¨å·²ç»\8f以{{GENDER:$1|$1}}ç\9a\84身份ç\99»å½\95ã\80\82使ç\94¨ä¸\8bé\9d¢ç\9a\84表格以其他用户的身份登录。",
     "userlogin-createanother": "创建另一个账户",
     "createacct-join": "请在下面输入你的信息。",
     "createacct-another-join": "在下方输入新帐户信息。",
     "throttled-mailpassword": "密码提醒已在最近$1小时内发送。为了安全起见,在每$1小时内只能发送一个密码提醒。",
     "mailerror": "发送邮件错误:$1",
     "acct_creation_throttle_hit": "使用你的IP地址访问本wiki的访客在过去24小时中创建了{{PLURAL:$1|$1个账户}},达到了这段时间所允许的最大值。因此,使用该IP地址的访客现在不能再创建账户。",
-    "emailauthenticated": "的电子邮件地址已于$2 $3确认。",
+    "emailauthenticated": "的电子邮件地址已于$2 $3确认。",
     "emailnotauthenticated": "您的邮件地址尚未确认。\n您将不会收到以下任何功能的邮件。",
     "noemailprefs": "指定一个电子邮箱地址以使用此功能。",
     "emailconfirmlink": "确认您的邮箱地址",
     "accountcreatedtext": "[[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|talk]])的账户已创建。",
     "createaccount-title": "在{{SITENAME}}中创建新账户",
     "createaccount-text": "有人在{{SITENAME}}中利用您的邮箱创建了一个名为 \"$2\" 的新帐户($4),密码是 \"$3\" 。您应该立即登录并更改密码。\n\n如果该账户创建错误的话,您可以忽略此信息。",
-    "usernamehasherror": "用户名中不可包含哈希(hash)字符",
     "login-throttled": "你最近尝试登录的次数过多。请等待$1后再试。",
     "login-abort-generic": "登录失败 - 已终止",
     "loginlanguagelabel": "语言:$1",
     "subject-preview": "标题预览:",
     "blockedtitle": "用户被封禁",
     "blockedtext": "'''你的用户名或IP地址已被封禁。'''\n\n执行封禁的管理员是$1。封禁原因是''$2''。\n\n* 开始时间:$8\n* 到期时间:$6\n* 目标用户:$7\n\n你可以联系$1或其他[[{{MediaWiki:Grouppage-sysop}}|管理员]]讨论该封禁。只有当你在[[Special:Preferences|系统设置]]确认了电子邮件地址且未被禁止使用“电邮联系”功能时,才可以使用它。你当前的IP地址是$3,该封禁ID是#$5。请在你的询问中包含上面的所有信息。",
-    "autoblockedtext": "你的IP地址因曾被一位被$1封禁的用户使用而被自动封禁。封禁原因:\n\n:''$2''\n\n* 开始时间:$8\n* 到期时间:$6\n* 目标用户:$7\n\n你可以联系$1或其他[[{{MediaWiki:Grouppage-sysop}}|管理员]]讨论该封禁。\n\n请注意,只有当你在[[Special:Preferences|系统设置]]确认了电子邮件地址且未被禁止使用“电邮联系”功能时,才可以使用它。\n\n你当前的IP地址是$3,该封禁ID是#$5。请在你的询问中包含上面的所有信息。",
+    "autoblockedtext": "您的IP地址因曾被一位被$1封禁的用户使用而被自动封禁。封禁原因:\n\n:$2\n\n* 开始时间:$8\n* 到期时间:$6\n* 目标用户:$7\n\n您可以联系$1或其他[[{{MediaWiki:Grouppage-sysop}}|管理员]]申诉该封禁。\n\n请注意,只有当您已在[[Special:Preferences|系统设置]]确认了电子邮件地址且未被禁止使用“电邮联系”功能时,才能发送电子邮件联系管理员。\n\n您当前的IP地址为$3,该封禁ID为#$5。\n请您在申诉内容中说明以上所有信息。",
     "blockednoreason": "未给出原因",
     "whitelistedittext": "您必须先$1才可编辑页面。",
     "confirmedittext": "你必须确认你的电子邮件地址才能编辑页面。请通过[[Special:Preferences|系统设置]]设置并确认你的电子邮件地址。",
     "userpage-userdoesnotexist": "用户账户“$1”没有注册。请在创建/编辑本页前检查。",
     "userpage-userdoesnotexist-view": "用户账户“$1”未曾创建。",
     "blocked-notice-logextract": "这位用户目前已被封禁。以下提供最近的封禁日志以供参考:",
-    "clearyourcache": "'''注意:'''在保存之后,你可能需要清除你的浏览器的缓存以查看更改。\n* '''Firefox/Safari:'''按住“Shift”的同时单击“刷新”,或按“Ctrl-F5”或“Ctrl-R”(Mac为“⌘-R”)\n* '''Google Chrome:'''按“Ctrl-Shift-R”(Mac为“⌘-Shift-R”)\n* '''Internet Explorer:'''按住“Ctrl”的同时单击“刷新”,或按“Ctrl-F5”\n* '''Opera:'''在“工具→首选项”中清除缓存",
+    "clearyourcache": "'''注意:'''在保存之后,您可能需要清除浏览器缓存才能看到所作出的变更的影响。\n* '''Firefox/Safari:'''按住“Shift”的同时单击“刷新”,或按“Ctrl-F5”或“Ctrl-R”(Mac为“⌘-R”)\n* '''Google Chrome:'''按“Ctrl-Shift-R”(Mac为“⌘-Shift-R”)\n* '''Internet Explorer:'''按住“Ctrl”的同时单击“刷新”,或按“Ctrl-F5”\n* '''Opera:'''在“工具→首选项”中清除缓存",
     "usercssyoucanpreview": "'''提示:''' 在保存前请用“{{int:showpreview}}”按钮来测试您新的 CSS 。",
     "userjsyoucanpreview": "'''提示:''' 在保存前请用“{{int:showpreview}}”按钮来测试您新的 JavaScript 。",
     "usercsspreview": "'''请记住你现在只是在预览你的用户CSS。它尚未保存!'''",
     "prefs-skin": "皮肤",
     "skin-preview": "预览",
     "datedefault": "默认格式",
-    "prefs-beta": "测试功能",
     "prefs-datetime": "日期时间",
     "prefs-labs": "实验室特性",
-    "prefs-user-pages": "用户页",
+    "prefs-user-pages": "用户页",
     "prefs-personal": "用户资料",
     "prefs-rc": "最近更改",
     "prefs-watchlist": "监视列表",
     "rows": "行数:",
     "columns": "列数:",
     "searchresultshead": "搜索",
-    "stub-threshold": "<a href=\"#\" class=\"stub\">ç\9f­é¡µé\9d¢é\93¾æ\8e¥</a>æ ¼å¼\8fé\98\88å\80¼ï¼\88å­\97è\8a\82ï¼\89ï¼\9a",
+    "stub-threshold": "<a href=\"#\" class=\"stub\">短链接</a>格式阈值(字节):",
     "stub-threshold-disabled": "停用",
     "recentchangesdays": "最近更改中显示的天数:",
     "recentchangesdays-max": "最多$1天",
     "recentchangescount": "默认显示的编辑数:",
     "prefs-help-recentchangescount": "这包括最近更改、页面历史和日志。",
-    "prefs-help-watchlist-token2": "这是你的监视列表的网络feed的密钥。任何知道它的人均可以阅读你的监视列表,因此请不要分享它。如果需要,[[Special:ResetTokens|你可以重置它]]。",
-    "savedprefs": "的系统设置已保存。",
+    "prefs-help-watchlist-token2": "这是您的监视列表的网络feed密钥。\n任何拥有者均可以浏览您的监视列表,因此不要公开该密钥。\n如果有需要,[[Special:ResetTokens|您可以重置密钥]]。",
+    "savedprefs": "的系统设置已保存。",
     "timezonelegend": "时区:",
     "localtime": "当地时间:",
     "timezoneuseserverdefault": "使用wiki默认值($1)",
     "prefs-memberingroups": "{{GENDER:$2|用户}}{{PLURAL:$1|组}}:",
     "prefs-registration": "注册时间:",
     "yourrealname": "真实姓名:",
-    "yourlanguage": "语言:",
+    "yourlanguage": "界面语言:",
     "yourvariant": "内容语言变种:",
-    "prefs-help-variant": "你希望用于显示该wiki的内容页面的语言变种或正字法。",
+    "prefs-help-variant": "您希望用于显示该本站内容的语言变体。",
     "yournick": "新签名:",
-    "prefs-help-signature": "讨论页面上的评论应该使用“<nowiki>~~~~</nowiki>”签名,它会自动转换为你的签名及时间戳。",
+    "prefs-help-signature": "讨论页上留言应该使用“<nowiki>~~~~</nowiki>”签名,它会自动转换为您的签名及时间戳。",
     "badsig": "错误的原始签名。请检查HTML标签。",
     "badsiglength": "签名过长。请不超过$1个字符。",
-    "yourgender": "希望使用什么性别称呼?",
+    "yourgender": "希望使用什么性别称呼?",
     "gender-unknown": "我不愿意指明(被称为“他/她”)",
     "gender-male": "他",
     "gender-female": "她",
-    "prefs-help-gender": "该设置为可选项目。软件根据它的值在称呼你及对他人提及你时使用适当的语法性别。该信息会被公开。",
+    "prefs-help-gender": "该设置为可选项目。软件根据该值在称呼您及对他人提及您时使用适当的语法性别。该信息会被公开。",
     "email": "电子邮件",
     "prefs-help-realname": "真实姓名是选填项目。如果你选择提供它,它将会用于贡献署名。",
     "prefs-help-email": "电子邮件是可选项,但是在您忘记密码时很有用。",
-    "prefs-help-email-others": "你也可以选择让其他用户通过你的用户或讨论页面上的链接用电子邮件联系你。其他用户联系你时你的电子邮件地址不会显示。",
+    "prefs-help-email-others": "您也可以选择让其他用户通过您的用户页或讨论页上的链接用电子邮件联系您。其他用户联系您时您的电子邮件地址不会显示。",
     "prefs-help-email-required": "电子邮件地址是必填项目。",
     "prefs-info": "基本信息",
-    "prefs-i18n": "界面语言",
+    "prefs-i18n": "语言",
     "prefs-signature": "签名",
     "prefs-dateformat": "日期格式",
     "prefs-timeoffset": "时差",
     "prefs-displaywatchlist": "显示",
     "prefs-tokenwatchlist": "密钥",
     "prefs-diffs": "差异对比",
-    "prefs-help-prefershttps": "该设置å°\86å\9c¨ä½ ä¸\8b次ç\99»å½\95æ\97¶ç\94\9fæ\95\88ã\80\82",
+    "prefs-help-prefershttps": "该设置将在下次登录时生效。",
     "prefs-tabs-navigation-hint": "提示:您可以通过左、右箭头键在选项卡之间切换。",
     "email-address-validity-valid": "电子邮件地址有效",
     "email-address-validity-invalid": "请输入有效的电子邮件地址",
     "upload-permitted": "允许的文件类型:$1。",
     "upload-preferred": "建议的文件类型:$1。",
     "upload-prohibited": "禁止的文件类型:$1。",
-    "uploadlog": "上传日志",
     "uploadlogpage": "上传日志",
     "uploadlogpagetext": "下面是最近的文件上传的列表。图像概览请见[[Special:NewFiles|新文件图库]]。",
     "filename": "文件名",
     "filereuploadsummary": "文件更改:",
     "filestatus": "著作权状况:",
     "filesource": "来源:",
-    "uploadedfiles": "上传的文件",
     "ignorewarning": "忽略警告,继续保存文件",
     "ignorewarnings": "忽略所有警告",
     "minlength1": "文件名至少要有一个字符。",
     "overwroteimage": "上传“[[$1]]”的新版本",
     "uploaddisabled": "上传己停用。",
     "copyuploaddisabled": "URL上传已停用。",
-    "uploadfromurl-queued": "上传已被列入队列。",
     "uploaddisabledtext": "文件上传已停用。",
     "php-uploaddisabledtext": "PHP文件上传停用。请检查file_uploads设置。",
     "uploadscripted": "该文件包含可能被网络浏览器错误解释的 HTML 或脚本代码。",
     "upload-misc-error": "未知的上传错误",
     "upload-misc-error-text": "在上传时发生未知的错误。请确认您使用了正确并可访问的URL,然后进行重试。如果问题仍然存在,请与[[Special:ListUsers/sysop|管理员]]联系。",
     "upload-too-many-redirects": "在网址中有太多重新定向",
-    "upload-unknown-size": "未知大小",
     "upload-http-error": "发生HTTP错误:$1",
     "upload-copy-upload-invalid-domain": "不能从该域名上载文件副本。",
     "backend-fail-stream": "无法流传送文件$1。",
     "img-auth-streaming": "流式化“$1”中。",
     "img-auth-public": "img_auth.php的功能是从非公开wiki输出文件。本wiki已被设置为公开。为了最佳安全状况,img_auth.php已停用。",
     "img-auth-noread": "用户无权读取“$1”。",
-    "img-auth-bad-query-string": "URL 有一个无效的查询字符串。",
     "http-invalid-url": "无效URL:$1",
     "http-invalid-scheme": "不支持带有“$1”的URL",
     "http-request-error": "未知的错误令到HTTP请求失败。",
     "filehist-dimensions": "大小",
     "filehist-filesize": "文件大小",
     "filehist-comment": "备注",
-    "filehist-missing": "文件遗失",
     "imagelinks": "文件用途",
     "linkstoimage": "以下$1个页面链接至本文件:",
     "linkstoimage-more": "超过$1个页面连接到这个文件。\n此处只列出首$1个链接到该文件的页面。\n您也可以查看[[Special:WhatLinksHere/$2|完整的列表]]。",
     "speciallogtitlelabel": "目标(标题或用户):",
     "log": "日志",
     "all-logs-page": "所有公开日志",
-    "alllogstext": "所有{{SITENAME}}公开日志的联合展示。可以通过选择日志类型、输入用户名(区分大小写)或相关页面(区分大小写)筛选日志条目。",
+    "alllogstext": "所有{{SITENAME}}公开日志的联合展示。可以通过选择日志类型、输入用户名(区分大小写)或相关页面(区分大小写)筛选日志条目。",
     "logempty": "在日志中不存在匹配项。",
     "log-title-wildcard": "搜索以该文字开头的标题",
     "showhideselectedlogentries": "显示/隐藏所选日志项",
     "listgrouprights-removegroup-self": "删除自己的账户的{{PLURAL:$2|用户组}}:$1",
     "listgrouprights-addgroup-self-all": "添加所有用户组至自己的账户",
     "listgrouprights-removegroup-self-all": "删除自己的账户的所有用户组",
-    "trackingcategories": "跟踪分类",
+    "listgrouprights-namespaceprotection-header": "名字空间限制",
+    "listgrouprights-namespaceprotection-namespace": "名字空间",
+    "listgrouprights-namespaceprotection-restrictedto": "允许用户编辑的权限",
+    "trackingcategories": "追踪分类",
     "trackingcategories-summary": "本页面列举由MediaWiki软件自动添加的跟踪分类。它们的名字可通过修改{{ns:8}}名字空间对应的系统信息而变更。",
-    "trackingcategories-msg": "è·\9f踪分类",
+    "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。",
+    "noindex-category-desc": "页面中有<code><nowiki>__NOINDEX__</nowiki></code>魔术字(并且在标记允许的名字空间)且因此未被机器人索引的。",
+    "index-category-desc": "页面中有<code><nowiki>__INDEX__</nowiki></code>魔术字(并且在标记允许的名字空间)且因此被机器人索引但本不应索引的。",
+    "post-expand-template-inclusion-category-desc": "在展开了所有模板后,页面大小大于<code>$wgMaxArticleSize</code>,所以一些模板未展开。",
+    "post-expand-template-argument-category-desc": "展开了模板参数(三对花括号内,例如<code>{{{Foo}}}</code>)之后,页面大于<code>$wgMaxArticleSize</code>。",
     "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>的分类,它默认防止在页面的分类连接盒中显示。",
+    "hidden-category-category-desc": "这是有<code><nowiki>__HIDDENCAT__</nowiki></code>的分类,该魔术字阻止分类默认在页面上的分类链接框中显示。",
     "trackingcategories-nodesc": "没有说明。",
     "trackingcategories-disabled": "分类被禁用",
     "mailnologin": "无电子邮件地址",
     "emailuser-title-notarget": "电邮联系",
     "emailpage": "电邮联系",
     "emailpagetext": "你可以使用下面的表格发送电子邮件信息至该{{GENDER:$1|用户}}。你在[[Special:Preferences|系统设置]]中输入的电子邮件地址将显示为邮件的“发件人”地址,所以该用户将可以直接回复你。",
-    "usermailererror": "Mail 对象返回错误:",
     "defemailsubject": "来自{{SITENAME}}用户“$1”的电子邮件",
     "usermaildisabled": "用户电子邮件停用",
     "usermaildisabledtext": "你不能发送电子邮件至本wiki的其他用户",
     "noemailtitle": "无电子邮件地址",
     "noemailtext": "该用户还没有指定一个有效的电子邮件地址。",
-    "nowikiemailtitle": "禁止电子邮件",
     "nowikiemailtext": "该用户已经选择不接收来自其他用户的电子邮件。",
     "emailnotarget": "收件人不存在或无效的用户名。",
     "emailtarget": "输入收件人的用户名",
     "nowatchlist": "你的监视列表为空。",
     "watchlistanontext": "请$1以查看或编辑您的监视列表。",
     "watchnologin": "未登录",
-    "watchnologintext": "您必须先[[Special:UserLogin|登录]]才能更改您的监视列表。",
     "addwatch": "添加至监视列表",
-    "addedwatchtext": "页面“[[:$1]]”已添加至你的[[Special:Watchlist|监视列表]]。本页面及其讨论页面的新增更改将会列入监视列表。",
+    "addedwatchtext": "已将页面“[[:$1]]”加入您的[[Special:Watchlist|监视列表]]。此后本页面及其讨论页的若有更改将在监视列表中显示。",
     "removewatch": "从监视列表中删除",
     "removedwatchtext": "页面“[[:$1]]”已从[[Special:Watchlist|你的监视列表]]中删除。",
     "watch": "监视",
     "unwatchthispage": "停止监视",
     "notanarticle": "非内容页面",
     "notvisiblerev": "上次由不同用户所作的修订版本已经删除",
-    "watchlist-details": "不计讨论页面,你的监视列表中有$1个页面。",
+    "watchlist-details": "不计讨论页,您的监视列表中共有$1个页面。",
     "wlheader-enotif": "已启用电子邮件通知。",
-    "wlheader-showupdated": "你上次访问后更改的页面以'''粗体'''显示",
+    "wlheader-showupdated": "您上次访问后发生更改的页面'''加粗'''显示",
     "watchmethod-recent": "检查被监视页面的最近编辑",
     "watchmethod-list": "查看监视页中的最新修改",
     "watchlistcontains": "您的监视列表包含$1个页面。",
     "iteminvalidname": "页面'$1'错误,无效命名...",
-    "wlnote2": "下面是过去{{PLURAL:$1|<strong>$1</strong>小时}}的更改,截至$2 $3。",
+    "wlnote2": "下面是最近{{PLURAL:$1|<strong>$1</strong>小时}}的更改,截至$2 $3。",
     "wlshowlast": "显示过去$1小时$2天$3",
     "watchlist-options": "监视列表选项",
     "watching": "正在监视...",
     "unwatching": "正在取消监视...",
     "watcherrortext": "更改“$1”的监视列表设置时出错。",
-    "enotif_mailer": "{{SITENAME}}通知发送器",
     "enotif_reset": "标记所有页面为已访问",
     "enotif_impersonal_salutation": "{{SITENAME}}用户",
     "enotif_subject_deleted": "{{SITENAME}}页面$1已被$2删除",
     "excontent": "内容:“$1”",
     "excontentauthor": "内容:“$1”(唯一贡献者为“[[Special:Contributions/$2|$2]]”)",
     "exbeforeblank": "被清空前的内容为:“$1”",
-    "exblank": "页面为空",
     "delete-confirm": "删除“$1”",
     "delete-legend": "删除",
     "historywarning": "警告:您将要删除的页面有约$1个{{PLURAL:$1|修订}}版本的历史:",
     "protect-summary-cascade": "联锁",
     "protect-expiring": "终止于$1(UTC)",
     "protect-expiring-local": "$1到期",
-    "protect-expiry-indefinite": "限期",
+    "protect-expiry-indefinite": "限期",
     "protect-cascade": "保护本页中包含的页面(连锁保护)",
     "protect-cantedit": "您无法更改这个页面的保护等级,因为您没有权限去编辑它。",
     "protect-othertime": "其它时间:",
     "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",
     "ipbhidename": "在编辑及列表中隐藏用户名",
-    "ipbwatchuser": "监视该用户的用户页面和讨论页面",
-    "ipb-disableusertalk": "阻止用户在封禁期间编辑自己的讨论页",
+    "ipbwatchuser": "监视该用户的用户页和讨论页",
+    "ipb-disableusertalk": "阻止用户在封禁期间编辑自己的讨论页",
     "ipb-change-block": "使用这些设置重新封禁用户",
     "ipb-confirm": "确认封禁",
     "badipaddress": "无效IP地址",
     "ipblocklist-submit": "搜索",
     "ipblocklist-localblock": "本地封禁",
     "ipblocklist-otherblocks": "其他{{PLURAL:$1|封禁}}",
-    "infiniteblock": "限期",
+    "infiniteblock": "限期",
     "expiringblock": "$1 $2到期",
     "anononlyblock": "仅匿名用户",
     "noautoblockblock": "自动封禁停用",
     "createaccountblock": "账户创建停用",
     "emailblock": "电子邮件停用",
-    "blocklist-nousertalk": "不能编辑自己的讨论页",
+    "blocklist-nousertalk": "不能编辑自己的讨论页",
     "ipblocklist-empty": "封禁列表为空。",
     "ipblocklist-no-results": "请求的IP地址或用户名没有被封禁。",
     "blocklink": "封禁",
     "block-log-flags-nocreate": "账户创建停用",
     "block-log-flags-noautoblock": "自动封禁停用",
     "block-log-flags-noemail": "电子邮件停用",
-    "block-log-flags-nousertalk": "不能编辑自己的讨论页",
+    "block-log-flags-nousertalk": "不能编辑自己的讨论页",
     "block-log-flags-angry-autoblock": "已启用增强型自动封禁",
     "block-log-flags-hiddenname": "隐藏用户名",
     "range_block_disabled": "管理员执行段封禁的权限已被禁用。",
     "export-download": "另存为文件",
     "export-templates": "包含模板",
     "export-pagelinks": "包含链接页面的搜索深度:",
-    "allmessages": "系统息",
+    "allmessages": "系统息",
     "allmessagesname": "名称",
     "allmessagesdefault": "默认信息文字",
     "allmessagescurrent": "当前信息文字",
     "importunknownsource": "未知的源导入类型",
     "importcantopen": "无法打开导入文件",
     "importbadinterwiki": "无效的跨wiki链接",
-    "importnotext": "空或没有文本",
     "importsuccess": "导入完成!",
-    "importhistoryconflict": "存在冲突的修订历史(可能在之前已经导入过此页面)",
     "importnosources": "跨Wiki导入源没有定义,同时不允许直接的历史上传。",
     "importnofile": "没有上传导入文件。",
     "importuploaderrorsize": "上传导入文件失败。文件大于可以允许的上传大小。",
     "livepreview-error": "连接失败:$1“$2”。\n尝试标准预览。",
     "lag-warn-normal": "过去$1秒内的更改未必会在这个列表中显示。",
     "lag-warn-high": "由于数据库的过度延迟,过去$1秒的更改未必会在这个列表中显示。",
-    "watchlistedit-numitems": "不计讨论页面,的监视列表包含$1个标题。",
+    "watchlistedit-numitems": "不计讨论页面,的监视列表包含$1个标题。",
     "watchlistedit-noitems": "你的监视列表中没有标题。",
     "watchlistedit-normal-title": "编辑监视列表",
     "watchlistedit-normal-legend": "删除监视列表中的标题",
     "fileduplicatesearch-result-n": "文件“$1”有$2项完全相同的重复副本。",
     "fileduplicatesearch-noresults": "没有文件命名为\"$1\"发现。",
     "specialpages": "特殊页面",
-    "specialpages-note-top": "图例",
+    "specialpages-note-top": "说明",
     "specialpages-note": "*普通特殊页面。\n*<span class=\"mw-specialpagerestricted\">受限特殊页面。</span>",
     "specialpages-group-maintenance": "维护报告",
     "specialpages-group-other": "其它特殊页面",
     "limitreport-templateargumentsize": "模板参数大小",
     "limitreport-templateargumentsize-value": "$1/$2 字节",
     "limitreport-expansiondepth": "最高扩展深度",
-    "limitreport-expensivefunctioncount": "高开销函数分析器",
+    "limitreport-expensivefunctioncount": "高开销解析函数数量",
     "expandtemplates": "展开模板",
     "expand_templates_intro": "此特殊页面可以递归地展开所给文本中的模板。\n它同时还可展开诸如<nowiki>{{</nowiki>#language:...}}的解析器函数和诸如<nowiki>{{</nowiki>CURRENTDAY}}的变量。\n实际上,几乎所有在双重花括号中的内容都会被展开。",
     "expand_templates_title": "上下文标题,用于{{FULLPAGENAME}}等:",
index ff107f7..161a3d1 100644 (file)
     "permalink": "永久連結",
     "print": "列印",
     "view": "檢視",
+    "view-foreign": "於$1查閱",
     "edit": "編輯",
+    "edit-local": "編輯本地說明",
     "create": "建立",
+    "create-local": "添加本地說明",
     "editthispage": "編輯本頁",
     "create-this-page": "建立本頁",
     "delete": "刪除",
     "accountcreatedtext": "[[{{ns:User}}:$1|$1]]([[{{ns:User talk}}:$1|討論]])的賬戶已經被建立。",
     "createaccount-title": "在{{SITENAME}}中建立新賬戶",
     "createaccount-text": "有人在{{SITENAME}}中利用您的電郵創建了一個名為 \"$2\" 的新賬戶($4),密碼是 \"$3\" 。您應該立即登入並更改密碼。\n\n如果該賬戶建立錯誤的話,您可以忽略此訊息。",
-    "usernamehasherror": "用戶名稱不可以包含切細字元",
     "login-throttled": "您已經嘗試多次的登入動作。\n請稍等$1後再試。",
     "login-abort-generic": "登入錯誤 - 中止",
     "loginlanguagelabel": "語言:$1",
     "prefs-skin": "外觀",
     "skin-preview": "預覽",
     "datedefault": "預設值",
-    "prefs-beta": "測試功能",
     "prefs-datetime": "日期和時間",
     "prefs-labs": "實驗中的功能",
     "prefs-user-pages": "使用者頁面",
     "upload-permitted": "准許的檔案類型:$1。",
     "upload-preferred": "建議的檔案類型:$1。",
     "upload-prohibited": "禁止的檔案類型:$1。",
-    "uploadlog": "上傳日誌",
     "uploadlogpage": "上傳日誌",
     "uploadlogpagetext": "以下是最近上載的檔案的一覽表。\n檢視[[Special:NewFiles|新檔案畫廊]]去看更富圖片的總覽。",
     "filename": "檔案名稱",
     "filereuploadsummary": "檔案變更:",
     "filestatus": "版權狀態:",
     "filesource": "來源:",
-    "uploadedfiles": "已上載檔案",
     "ignorewarning": "忽略警告並儲存檔案",
     "ignorewarnings": "忽略所有警告",
     "minlength1": "檔案名字必須至少有一個字母。",
     "overwroteimage": "已經上傳「[[$1]]」的新版本",
     "uploaddisabled": "上傳己停用。",
     "copyuploaddisabled": "通過網址上傳功能未開通。",
-    "uploadfromurl-queued": "上傳已被列入隊列。",
     "uploaddisabledtext": "檔案上傳不可用。",
     "php-uploaddisabledtext": "PHP 檔案上載已經停用。請檢查 file_uploads 設定。",
     "uploadscripted": "該檔案包含可能被網路瀏覽器錯誤解釋的 HTML 或腳本代碼。",
     "upload-misc-error": "未知的上傳錯誤",
     "upload-misc-error-text": "在上傳時發生未知的錯誤。請驗証使用了正確並可訪問的 URL,然後進行重試。如果問題仍然存在,請與[[Special:ListUsers/sysop|管理員]]聯繫。",
     "upload-too-many-redirects": "在網址中有太多重新定向",
-    "upload-unknown-size": "未知的大小",
     "upload-http-error": "已發生一個HTTP錯誤:$1",
     "upload-copy-upload-invalid-domain": "不能從該域名上載檔案副本。",
     "backend-fail-stream": "無法流傳送文件「$1」。",
     "img-auth-streaming": "串流「$1」中。",
     "img-auth-public": "img_auth.php的功能是由一個公共wiki中輸出檔案。\n這個wiki是已經設定做一個公共wiki。\n基於保安最佳化,img_auth.php已經停用。",
     "img-auth-noread": "用戶無權讀取「$1」。",
-    "img-auth-bad-query-string": "URL有一個無效的查詢字符串",
     "http-invalid-url": "無效的URL:$1",
     "http-invalid-scheme": "不支援含有「$1」的URL。",
     "http-request-error": "未知的錯誤令到HTTP請求失敗。",
     "filehist-dimensions": "維度",
     "filehist-filesize": "檔案大小",
     "filehist-comment": "註解",
-    "filehist-missing": "檔案遺失",
     "imagelinks": "檔案使用情況",
     "linkstoimage": "以下的$1個頁面連接到本檔案:",
     "linkstoimage-more": "超過$1個頁面連接到這個檔案。\n此處只列出首$1個連接到此檔案的頁面。\n您也可以查看[[Special:WhatLinksHere/$2|完整的清單]]。",
     "listgrouprights-removegroup-self": "在自己的賬戶中移除的{{PLURAL:$2|一個|多個}}群組: $1",
     "listgrouprights-addgroup-self-all": "在自己的賬戶中加入所有群組",
     "listgrouprights-removegroup-self-all": "在自己的賬戶中移除所有群組",
+    "listgrouprights-namespaceprotection-header": "命名空間限制",
+    "listgrouprights-namespaceprotection-namespace": "命名空間",
+    "listgrouprights-namespaceprotection-restrictedto": "允許用戶編輯權限",
     "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。",
+    "noindex-category-desc": "頁面中存在<code><nowiki>__NOINDEX__</nowiki></code>魔術字(並且於標記允許名字空間)並藉此未被機械人索引。",
+    "index-category-desc": "頁面中存在<code><nowiki>__INDEX__</nowiki></code>魔術字(並且於標記允許名字空間)並藉此被機械人錯誤索引。",
+    "post-expand-template-inclusion-category-desc": "展開所有模板后,頁面大小大於<code>$wgMaxArticleSize</code>,藉此某些模板未展開。",
+    "post-expand-template-argument-category-desc": "展開模板參數(三隊花括弧內,例如<code>{{{Foo}}}</code>)後,頁面大於<code>$wgMaxArticleSize</code>。",
     "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>,它預設防止於頁面分類連接盒中顯示。",
+    "hidden-category-category-desc": "此分類帶有<code><nowiki>__HIDDENCAT__</nowiki></code>,它預設防止於頁面分類連接盒中顯示。",
     "trackingcategories-nodesc": "並無說明。",
     "trackingcategories-disabled": "分類被禁用",
     "mailnologin": "無電郵地址",
     "emailuser-title-notarget": "E-mail用戶",
     "emailpage": "E-mail用戶",
     "emailpagetext": "您可以用下面的表格去寄一封電郵給這位{{Gender:$1|用戶}}。\n您在[[Special:Preferences|您的參數設置]]中所輸入的電子郵件地址將出現在郵件「發件人」一欄中,這樣該用戶就可以回覆您。",
-    "usermailererror": "目標郵件地址返回錯誤:",
     "defemailsubject": "{{SITENAME}}來自用戶「$1」的電子郵件",
     "usermaildisabled": "用戶電郵已停用",
     "usermaildisabledtext": "您不可以發送電郵到這個wiki上的其他用戶",
     "noemailtitle": "無e-mail地址",
     "noemailtext": "該用戶還沒有指定一個有效的e-mail地址。",
-    "nowikiemailtitle": "不容許電子郵件",
     "nowikiemailtext": "這位用戶選擇不接收其他用戶的電子郵件。",
     "emailnotarget": "收件人不存在或無效的用戶名。",
     "emailtarget": "輸入收件人用戶名",
     "nowatchlist": "您的監視列表為空。",
     "watchlistanontext": "請$1以檢視或編輯您的監視列表。",
     "watchnologin": "未登入",
-    "watchnologintext": "您必須先[[Special:UserLogin|登入]],才能更改您的監視列表。",
     "addwatch": "加至監視列表",
     "addedwatchtext": "已將頁面「[[:$1]]」加入您的[[Special:Watchlist|監視列表]]。將來此頁面及其討論頁如有更動都會在那裡列出。",
     "removewatch": "停止監視",
     "watching": "正在監視...",
     "unwatching": "正在停止監視...",
     "watcherrortext": "更改「$1」的監視列表設定時發生錯誤。",
-    "enotif_mailer": "{{SITENAME}}郵件通知器",
     "enotif_reset": "將所有頁面標為已閱讀",
     "enotif_impersonal_salutation": "{{SITENAME}}用戶",
     "enotif_subject_deleted": "{{SITENAME}}的「$1」頁面被$2刪除",
     "excontent": "內容為: 「$1」",
     "excontentauthor": "內容為:「$1」(而且唯一貢獻者為「[[Special:Contributions/$2|$2]]」)",
     "exbeforeblank": "被清空前的內容為:「$1」",
-    "exblank": "頁面為空",
     "delete-confirm": "刪除「$1」",
     "delete-legend": "刪除",
     "historywarning": "'''警告: '''您將要刪除的頁內含有約$1次{{PLURAL:$1|修訂}}的歷史:",
     "importunknownsource": "未知的源匯入類型",
     "importcantopen": "無法打開匯入檔案",
     "importbadinterwiki": "損壞的內部 wiki 連結",
-    "importnotext": "空或沒有文字",
     "importsuccess": "匯入完成!",
-    "importhistoryconflict": "存在衝突的修訂歷史(可能在之前已經匯入過此頁面)",
     "importnosources": "跨Wiki匯入源沒有定義,同時不允許直接的歷史上傳。",
     "importnofile": "沒有上傳匯入檔案。",
     "importuploaderrorsize": "上載匯入檔案失敗。檔案大於可以允許的上傳大小。",
     "limitreport-templateargumentsize": "模板參數大小",
     "limitreport-templateargumentsize-value": "$1/$2 個{{PLURAL:$2|位元組}}",
     "limitreport-expansiondepth": "最高展開深度",
-    "limitreport-expensivefunctioncount": "昂貴分析器函數計數",
+    "limitreport-expensivefunctioncount": "高開銷分析函數數位",
     "expandtemplates": "展開模板",
     "expand_templates_intro": "本特殊頁面用於將一些文字中的模版展開,包括模版中引用的模版。同時也展開解譯器函數如<nowiki>{{</nowiki>#language:...}},以及變數如<nowiki>{{</nowiki>CURRENTDAY}}&mdash;實際上,幾乎所有在雙括弧中的內容都被展開。",
     "expand_templates_title": "上下文標題,用於 {{FULLPAGENAME}} 等:",
index 437c47c..cd4ce7a 100644 (file)
@@ -80,7 +80,6 @@
     "currentevents": "Izehlakalo ezimanje",
     "currentevents-url": "Project:Izehlakalo ezimanje",
     "edithelp": "Usizo ngokuhlela",
-    "helppage": "Help:Isiqikili",
     "mainpage": "Ikhasi Elikhulu",
     "mainpage-description": "Ikhasi Elikhulu",
     "portal": "Umnyango wamgwamanda",
index 4e2b919..6109535 100644 (file)
@@ -129,7 +129,7 @@ $namespaceGenderAliases = array(
        NS_USER_TALK => array(
                'male' => 'نقاش_المستخدم',
                'female' => 'نقاش_المستخدمة'
-       ), 
+       ),
 );
 
 $magicWords = array(
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 2bb7599..8b0b7b1 100644 (file)
@@ -36,7 +36,7 @@ $digitTransformTable = array(
 
 $linkTrail = "/^([a-z\x{0B00}-\x{0B7F}]+)(.*)$/sDu";
 
-/** namespace translations from translatewiki.net 
+/** namespace translations from translatewiki.net
  * @author Shijualex
  * @author Psubhashish
  */
index 8a0eb9b..aba939d 100644 (file)
@@ -96,7 +96,7 @@ $namespaceAliases = array(
 
 $namespaceGenderAliases = array(
        NS_USER => array( 'male' => 'Użytkownik', 'female' => 'Użytkowniczka' ),
-       NS_USER_TALK => array( 'male' => 'Dyskusja_użytkownika', 'female' => 'Dyskusja_użytkowniczki' ), 
+       NS_USER_TALK => array( 'male' => 'Dyskusja_użytkownika', 'female' => 'Dyskusja_użytkowniczki' ),
 );
 
 $dateFormats = array(
diff --git a/languages/utils/CLDRPluralRuleConverter.php b/languages/utils/CLDRPluralRuleConverter.php
new file mode 100644 (file)
index 0000000..65d57e0
--- /dev/null
@@ -0,0 +1,313 @@
+<?php
+
+/**
+ * @author Niklas Laxström, Tim Starling
+ *
+ * @copyright Copyright © 2010-2012, Niklas Laxström
+ * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
+ *
+ * @file
+ * @since 1.20
+ */
+
+/**
+ * Helper class for converting rules to reverse polish notation (RPN).
+ */
+class CLDRPluralRuleConverter {
+       /**
+        * The input string
+        *
+        * @var string
+        */
+       public $rule;
+
+       /**
+        * The current position
+        *
+        * @var int
+        */
+       public $pos;
+
+       /**
+        * The past-the-end position
+        *
+        * @var int
+        */
+       public $end;
+
+       /**
+        * The operator stack
+        *
+        * @var array
+        */
+       public $operators = array();
+
+       /**
+        * The operand stack
+        *
+        * @var array
+        */
+       public $operands = array();
+
+       /**
+        * Precedence levels. Note that there's no need to worry about associativity
+        * for the level 4 operators, since they return boolean and don't accept
+        * boolean inputs.
+        */
+       static $precedence = array(
+               'or' => 2,
+               'and' => 3,
+               'is' => 4,
+               'is-not' => 4,
+               'in' => 4,
+               'not-in' => 4,
+               'within' => 4,
+               'not-within' => 4,
+               'mod' => 5,
+               ',' => 6,
+               '..' => 7,
+       );
+
+       /**
+        * A character list defining whitespace, for use in strspn() etc.
+        */
+       const WHITESPACE_CLASS = " \t\r\n";
+
+       /**
+        * Same for digits. Note that the grammar given in UTS #35 doesn't allow
+        * negative numbers or decimal separators.
+        */
+       const NUMBER_CLASS = '0123456789';
+
+       /**
+        * A character list of symbolic operands.
+        */
+       const OPERAND_SYMBOLS = 'nivwft';
+
+       /**
+        * An anchored regular expression which matches a word at the current offset.
+        */
+       const WORD_REGEX = '/[a-zA-Z@]+/A';
+
+       /**
+        * Convert a rule to RPN. This is the only public entry point.
+        *
+        * @param string $rule The rule to convert
+        * @return string The RPN representation of the rule
+        */
+       public static function convert( $rule ) {
+               $parser = new self( $rule );
+               return $parser->doConvert();
+       }
+
+       /**
+        * Private constructor.
+        */
+       protected function __construct( $rule ) {
+               $this->rule = $rule;
+               $this->pos = 0;
+               $this->end = strlen( $rule );
+       }
+
+       /**
+        * Do the operation.
+        *
+        * @return string The RPN representation of the rule (e.g. "5 3 mod n is")
+        */
+       protected function doConvert() {
+               $expectOperator = true;
+
+               // Iterate through all tokens, saving the operators and operands to a
+               // stack per Dijkstra's shunting yard algorithm.
+               /** @var CLDRPluralRuleConverter_Operator $token */
+               while ( false !== ( $token = $this->nextToken() ) ) {
+                       // In this grammar, there are only binary operators, so every valid
+                       // rule string will alternate between operator and operand tokens.
+                       $expectOperator = !$expectOperator;
+
+                       if ( $token instanceof CLDRPluralRuleConverter_Expression ) {
+                               // Operand
+                               if ( $expectOperator ) {
+                                       $token->error( 'unexpected operand' );
+                               }
+                               $this->operands[] = $token;
+                               continue;
+                       } else {
+                               // Operator
+                               if ( !$expectOperator ) {
+                                       $token->error( 'unexpected operator' );
+                               }
+                               // Resolve higher precedence levels
+                               $lastOp = end( $this->operators );
+                               while ( $lastOp && self::$precedence[$token->name] <= self::$precedence[$lastOp->name] ) {
+                                       $this->doOperation( $lastOp, $this->operands );
+                                       array_pop( $this->operators );
+                                       $lastOp = end( $this->operators );
+                               }
+                               $this->operators[] = $token;
+                       }
+               }
+
+               // Finish off the stack
+               while ( $op = array_pop( $this->operators ) ) {
+                       $this->doOperation( $op, $this->operands );
+               }
+
+               // Make sure the result is sane. The first case is possible for an empty
+               // string input, the second should be unreachable.
+               if ( !count( $this->operands ) ) {
+                       $this->error( 'condition expected' );
+               } elseif ( count( $this->operands ) > 1 ) {
+                       $this->error( 'missing operator or too many operands' );
+               }
+
+               $value = $this->operands[0];
+               if ( $value->type !== 'boolean' ) {
+                       $this->error( 'the result must have a boolean type' );
+               }
+
+               return $this->operands[0]->rpn;
+       }
+
+       /**
+        * Fetch the next token from the input string.
+        *
+        * @return CLDRPluralRuleConverter_Fragment The next token
+        */
+       protected function nextToken() {
+               if ( $this->pos >= $this->end ) {
+                       return false;
+               }
+
+               // Whitespace
+               $length = strspn( $this->rule, self::WHITESPACE_CLASS, $this->pos );
+               $this->pos += $length;
+
+               if ( $this->pos >= $this->end ) {
+                       return false;
+               }
+
+               // Number
+               $length = strspn( $this->rule, self::NUMBER_CLASS, $this->pos );
+               if ( $length !== 0 ) {
+                       $token = $this->newNumber( substr( $this->rule, $this->pos, $length ), $this->pos );
+                       $this->pos += $length;
+                       return $token;
+               }
+
+               // Two-character operators
+               $op2 = substr( $this->rule, $this->pos, 2 );
+               if ( $op2 === '..' || $op2 === '!=' ) {
+                       $token = $this->newOperator( $op2, $this->pos, 2 );
+                       $this->pos += 2;
+                       return $token;
+               }
+
+               // Single-character operators
+               $op1 = $this->rule[$this->pos];
+               if ( $op1 === ',' || $op1 === '=' || $op1 === '%' ) {
+                       $token = $this->newOperator( $op1, $this->pos, 1 );
+                       $this->pos ++;
+                       return $token;
+               }
+
+               // Word
+               if ( !preg_match( self::WORD_REGEX, $this->rule, $m, 0, $this->pos ) ) {
+                       $this->error( 'unexpected character "' . $this->rule[$this->pos] . '"' );
+               }
+               $word1 = strtolower( $m[0] );
+               $word2 = '';
+               $nextTokenPos = $this->pos + strlen( $word1 );
+               if ( $word1 === 'not' || $word1 === 'is' ) {
+                       // Look ahead one word
+                       $nextTokenPos += strspn( $this->rule, self::WHITESPACE_CLASS, $nextTokenPos );
+                       if ( $nextTokenPos < $this->end
+                               && preg_match( self::WORD_REGEX, $this->rule, $m, 0, $nextTokenPos )
+                       ) {
+                               $word2 = strtolower( $m[0] );
+                               $nextTokenPos += strlen( $word2 );
+                       }
+               }
+
+               // Two-word operators like "is not" take precedence over single-word operators like "is"
+               if ( $word2 !== '' ) {
+                       $bothWords = "{$word1}-{$word2}";
+                       if ( isset( self::$precedence[$bothWords] ) ) {
+                               $token = $this->newOperator( $bothWords, $this->pos, $nextTokenPos - $this->pos );
+                               $this->pos = $nextTokenPos;
+                               return $token;
+                       }
+               }
+
+               // Single-word operators
+               if ( isset( self::$precedence[$word1] ) ) {
+                       $token = $this->newOperator( $word1, $this->pos, strlen( $word1 ) );
+                       $this->pos += strlen( $word1 );
+                       return $token;
+               }
+
+               // The single-character operand symbols
+               if ( strpos( self::OPERAND_SYMBOLS, $word1 ) !== false ) {
+                       $token = $this->newNumber( $word1, $this->pos );
+                       $this->pos ++;
+                       return $token;
+               }
+
+               // Samples
+               if ( $word1 === '@integer' || $word1 === '@decimal' ) {
+                       // Samples are like comments, they have no effect on rule evaluation.
+                       // They run from the first sample indicator to the end of the string.
+                       $this->pos = $this->end;
+                       return false;
+               }
+
+               $this->error( 'unrecognised word' );
+       }
+
+       /**
+        * For the binary operator $op, pop its operands off the stack and push
+        * a fragment with rpn and type members describing the result of that
+        * operation.
+        *
+        * @param CLDRPluralRuleConverter_Operator $op
+        */
+       protected function doOperation( $op ) {
+               if ( count( $this->operands ) < 2 ) {
+                       $op->error( 'missing operand' );
+               }
+               $right = array_pop( $this->operands );
+               $left = array_pop( $this->operands );
+               $result = $op->operate( $left, $right );
+               $this->operands[] = $result;
+       }
+
+       /**
+        * Create a numerical expression object
+        *
+        * @param string $text
+        * @param int $pos
+        * @return CLDRPluralRuleConverter_Expression The numerical expression
+        */
+       protected function newNumber( $text, $pos ) {
+               return new CLDRPluralRuleConverter_Expression( $this, 'number', $text, $pos, strlen( $text ) );
+       }
+
+       /**
+        * Create a binary operator
+        *
+        * @param string $type
+        * @param int $pos
+        * @param int $length
+        * @return CLDRPluralRuleConverter_Operator The operator
+        */
+       protected function newOperator( $type, $pos, $length ) {
+               return new CLDRPluralRuleConverter_Operator( $this, $type, $pos, $length );
+       }
+
+       /**
+        * Throw an error
+        */
+       protected function error( $message ) {
+               throw new CLDRPluralRuleError( $message );
+       }
+}
diff --git a/languages/utils/CLDRPluralRuleConverter_Expression.php b/languages/utils/CLDRPluralRuleConverter_Expression.php
new file mode 100644 (file)
index 0000000..8352e72
--- /dev/null
@@ -0,0 +1,41 @@
+<?php
+
+/**
+ * @author Niklas Laxström, Tim Starling
+ *
+ * @copyright Copyright © 2010-2012, Niklas Laxström
+ * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
+ *
+ * @file
+ * @since 1.20
+ */
+
+/**
+ * Helper for CLDRPluralRuleConverter.
+ * An expression object, representing a region of the input string (for error
+ * messages), the RPN notation used to evaluate it, and the result type for
+ * validation.
+ */
+class CLDRPluralRuleConverter_Expression extends CLDRPluralRuleConverter_Fragment {
+       /** @var string */
+       public $type;
+
+       /** @var string */
+       public $rpn;
+
+       function __construct( $parser, $type, $rpn, $pos, $length ) {
+               parent::__construct( $parser, $pos, $length );
+               $this->type = $type;
+               $this->rpn = $rpn;
+       }
+
+       public function isType( $type ) {
+               if ( $type === 'range' && ( $this->type === 'range' || $this->type === 'number' ) ) {
+                       return true;
+               }
+               if ( $type === $this->type ) {
+                       return true;
+               }
+               return false;
+       }
+}
diff --git a/languages/utils/CLDRPluralRuleConverter_Fragment.php b/languages/utils/CLDRPluralRuleConverter_Fragment.php
new file mode 100644 (file)
index 0000000..88795a0
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+
+/**
+ * @author Niklas Laxström, Tim Starling
+ *
+ * @copyright Copyright © 2010-2012, Niklas Laxström
+ * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
+ *
+ * @file
+ * @since 1.20
+ */
+
+/**
+ * Helper for CLDRPluralRuleConverter.
+ * The base class for operators and expressions, describing a region of the input string.
+ */
+class CLDRPluralRuleConverter_Fragment {
+       public $parser, $pos, $length, $end;
+
+       function __construct( $parser, $pos, $length ) {
+               $this->parser = $parser;
+               $this->pos = $pos;
+               $this->length = $length;
+               $this->end = $pos + $length;
+       }
+
+       public function error( $message ) {
+               $text = $this->getText();
+               throw new CLDRPluralRuleError( "$message at position " . ( $this->pos + 1 ) . ": \"$text\"" );
+       }
+
+       public function getText() {
+               return substr( $this->parser->rule, $this->pos, $this->length );
+       }
+}
diff --git a/languages/utils/CLDRPluralRuleConverter_Operator.php b/languages/utils/CLDRPluralRuleConverter_Operator.php
new file mode 100644 (file)
index 0000000..c42953c
--- /dev/null
@@ -0,0 +1,114 @@
+<?php
+
+/**
+ * @author Niklas Laxström, Tim Starling
+ *
+ * @copyright Copyright © 2010-2012, Niklas Laxström
+ * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
+ *
+ * @file
+ * @since 1.20
+ */
+
+/**
+ * Helper for CLDRPluralRuleConverter.
+ * An operator object, representing a region of the input string (for error
+ * messages), and the binary operator at that location.
+ */
+class CLDRPluralRuleConverter_Operator extends CLDRPluralRuleConverter_Fragment {
+       /** @var string The name */
+       public $name;
+
+       /**
+        * Each op type has three characters: left operand type, right operand type and result type
+        *
+        *   b = boolean
+        *   n = number
+        *   r = range
+        *
+        * A number is a kind of range.
+        *
+        * @var array
+        */
+       static $opTypes = array(
+               'or' => 'bbb',
+               'and' => 'bbb',
+               'is' => 'nnb',
+               'is-not' => 'nnb',
+               'in' => 'nrb',
+               'not-in' => 'nrb',
+               'within' => 'nrb',
+               'not-within' => 'nrb',
+               'mod' => 'nnn',
+               ',' => 'rrr',
+               '..' => 'nnr',
+       );
+
+       /**
+        * Map converting from the abbrevation to the full form.
+        *
+        * @var array
+        */
+       static $typeSpecMap = array(
+               'b' => 'boolean',
+               'n' => 'number',
+               'r' => 'range',
+       );
+
+       /**
+        * Map for converting the new operators introduced in Rev 33 to the old forms
+        */
+       static $aliasMap = array(
+               '%' => 'mod',
+               '!=' => 'not-in',
+               '=' => 'in'
+       );
+
+       /**
+        * Initialize a new instance of a CLDRPluralRuleConverter_Operator object
+        *
+        * @param CLDRPluralRuleConverter $parser The parser
+        * @param string $name The operator name
+        * @param int $pos The length
+        * @param int $length
+        */
+       function __construct( $parser, $name, $pos, $length ) {
+               parent::__construct( $parser, $pos, $length );
+               if ( isset( self::$aliasMap[$name] ) ) {
+                       $name = self::$aliasMap[$name];
+               }
+               $this->name = $name;
+       }
+
+       /**
+        * Compute the operation
+        *
+        * @param CLDRPluralRuleConverter_Expression $left The left part of the expression
+        * @param CLDRPluralRuleConverter_Expression $right The right part of the expression
+        * @return CLDRPluralRuleConverter_Expression The result of the operation
+        */
+       public function operate( $left, $right ) {
+               $typeSpec = self::$opTypes[$this->name];
+
+               $leftType = self::$typeSpecMap[$typeSpec[0]];
+               $rightType = self::$typeSpecMap[$typeSpec[1]];
+               $resultType = self::$typeSpecMap[$typeSpec[2]];
+
+               $start = min( $this->pos, $left->pos, $right->pos );
+               $end = max( $this->end, $left->end, $right->end );
+               $length = $end - $start;
+
+               $newExpr = new CLDRPluralRuleConverter_Expression( $this->parser, $resultType,
+                       "{$left->rpn} {$right->rpn} {$this->name}",
+                       $start, $length );
+
+               if ( !$left->isType( $leftType ) ) {
+                       $newExpr->error( "invalid type for left operand: expected $leftType, got {$left->type}" );
+               }
+
+               if ( !$right->isType( $rightType ) ) {
+                       $newExpr->error( "invalid type for right operand: expected $rightType, got {$right->type}" );
+               }
+               return $newExpr;
+       }
+}
diff --git a/languages/utils/CLDRPluralRuleError.php b/languages/utils/CLDRPluralRuleError.php
new file mode 100644 (file)
index 0000000..2ca3410
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * @author Niklas Laxström, Tim Starling
+ *
+ * @copyright Copyright © 2010-2012, Niklas Laxström
+ * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
+ *
+ * @file
+ * @since 1.20
+ */
+
+/**
+ * The exception class for all the classes in this file. This will be thrown
+ * back to the caller if there is any validation error.
+ */
+class CLDRPluralRuleError extends MWException {
+       function __construct( $message ) {
+               parent::__construct( 'CLDR plural rule error: ' . $message );
+       }
+}
\ No newline at end of file
index e420cb2..61ab947 100644 (file)
@@ -30,6 +30,7 @@
  * @file
  * @since 1.20
  */
+
 class CLDRPluralRuleEvaluator {
        /**
         * Evaluate a number against a set of plural rules. If a rule passes,
@@ -179,570 +180,3 @@ class CLDRPluralRuleEvaluator {
                }
        }
 }
-
-/**
- * Evaluator helper class representing a range list.
- */
-class CLDRPluralRuleEvaluator_Range {
-       /**
-        * The parts
-        *
-        * @var array
-        */
-       public $parts = array();
-
-       /**
-        * Initialize a new instance of CLDRPluralRuleEvaluator_Range
-        *
-        * @param int $start The start of the range
-        * @param int|bool $end The end of the range, or false if the range is not bounded.
-        */
-       function __construct( $start, $end = false ) {
-               if ( $end === false ) {
-                       $this->parts[] = $start;
-               } else {
-                       $this->parts[] = array( $start, $end );
-               }
-       }
-
-       /**
-        * Determine if the given number is inside the range.
-        *
-        * @param int $number The number to check
-        * @param bool $integerConstraint If true, also asserts the number is an integer; otherwise, number simply has to be inside the range.
-        * @return bool True if the number is inside the range; otherwise, false.
-        */
-       function isNumberIn( $number, $integerConstraint = true ) {
-               foreach ( $this->parts as $part ) {
-                       if ( is_array( $part ) ) {
-                               if ( ( !$integerConstraint || floor( $number ) === (float)$number )
-                                       && $number >= $part[0] && $number <= $part[1]
-                               ) {
-                                       return true;
-                               }
-                       } else {
-                               if ( $number == $part ) {
-                                       return true;
-                               }
-                       }
-               }
-               return false;
-       }
-
-       /**
-        * Readable alias for isNumberIn( $number, false ), and the implementation
-        * of the "within" operator.
-        *
-        * @param int $number The number to check
-        * @return bool True if the number is inside the range; otherwise, false.
-        */
-       function isNumberWithin( $number ) {
-               return $this->isNumberIn( $number, false );
-       }
-
-       /**
-        * Add another part to this range.
-        *
-        * @param CLDRPluralRuleEvaluator_Range|int $other The part to add, either
-        *   a range object itself or a single number.
-        */
-       function add( $other ) {
-               if ( $other instanceof self ) {
-                       $this->parts = array_merge( $this->parts, $other->parts );
-               } else {
-                       $this->parts[] = $other;
-               }
-       }
-
-       /**
-        * Returns the string representation of the rule evaluator range.
-        * The purpose of this method is to help debugging.
-        *
-        * @return string The string representation of the rule evaluator range
-        */
-       function __toString() {
-               $s = 'Range(';
-               foreach ( $this->parts as $i => $part ) {
-                       if ( $i ) {
-                               $s .= ', ';
-                       }
-                       if ( is_array( $part ) ) {
-                               $s .= $part[0] . '..' . $part[1];
-                       } else {
-                               $s .= $part;
-                       }
-               }
-               $s .= ')';
-               return $s;
-       }
-
-}
-
-/**
- * Helper class for converting rules to reverse polish notation (RPN).
- */
-class CLDRPluralRuleConverter {
-       /**
-        * The input string
-        *
-        * @var string
-        */
-       public $rule;
-
-       /**
-        * The current position
-        *
-        * @var int
-        */
-       public $pos;
-
-       /**
-        * The past-the-end position
-        *
-        * @var int
-        */
-       public $end;
-
-       /**
-        * The operator stack
-        *
-        * @var array
-        */
-       public $operators = array();
-
-       /**
-        * The operand stack
-        *
-        * @var array
-        */
-       public $operands = array();
-
-       /**
-        * Precedence levels. Note that there's no need to worry about associativity
-        * for the level 4 operators, since they return boolean and don't accept
-        * boolean inputs.
-        */
-       static $precedence = array(
-               'or' => 2,
-               'and' => 3,
-               'is' => 4,
-               'is-not' => 4,
-               'in' => 4,
-               'not-in' => 4,
-               'within' => 4,
-               'not-within' => 4,
-               'mod' => 5,
-               ',' => 6,
-               '..' => 7,
-       );
-
-       /**
-        * A character list defining whitespace, for use in strspn() etc.
-        */
-       const WHITESPACE_CLASS = " \t\r\n";
-
-       /**
-        * Same for digits. Note that the grammar given in UTS #35 doesn't allow
-        * negative numbers or decimal separators.
-        */
-       const NUMBER_CLASS = '0123456789';
-
-       /**
-        * A character list of symbolic operands.
-        */
-       const OPERAND_SYMBOLS = 'nivwft';
-
-       /**
-        * An anchored regular expression which matches a word at the current offset.
-        */
-       const WORD_REGEX = '/[a-zA-Z@]+/A';
-
-       /**
-        * Convert a rule to RPN. This is the only public entry point.
-        *
-        * @param string $rule The rule to convert
-        * @return string The RPN representation of the rule
-        */
-       public static function convert( $rule ) {
-               $parser = new self( $rule );
-               return $parser->doConvert();
-       }
-
-       /**
-        * Private constructor.
-        */
-       protected function __construct( $rule ) {
-               $this->rule = $rule;
-               $this->pos = 0;
-               $this->end = strlen( $rule );
-       }
-
-       /**
-        * Do the operation.
-        *
-        * @return string The RPN representation of the rule (e.g. "5 3 mod n is")
-        */
-       protected function doConvert() {
-               $expectOperator = true;
-
-               // Iterate through all tokens, saving the operators and operands to a
-               // stack per Dijkstra's shunting yard algorithm.
-               /** @var CLDRPluralRuleConverter_Operator $token */
-               while ( false !== ( $token = $this->nextToken() ) ) {
-                       // In this grammar, there are only binary operators, so every valid
-                       // rule string will alternate between operator and operand tokens.
-                       $expectOperator = !$expectOperator;
-
-                       if ( $token instanceof CLDRPluralRuleConverter_Expression ) {
-                               // Operand
-                               if ( $expectOperator ) {
-                                       $token->error( 'unexpected operand' );
-                               }
-                               $this->operands[] = $token;
-                               continue;
-                       } else {
-                               // Operator
-                               if ( !$expectOperator ) {
-                                       $token->error( 'unexpected operator' );
-                               }
-                               // Resolve higher precedence levels
-                               $lastOp = end( $this->operators );
-                               while ( $lastOp && self::$precedence[$token->name] <= self::$precedence[$lastOp->name] ) {
-                                       $this->doOperation( $lastOp, $this->operands );
-                                       array_pop( $this->operators );
-                                       $lastOp = end( $this->operators );
-                               }
-                               $this->operators[] = $token;
-                       }
-               }
-
-               // Finish off the stack
-               while ( $op = array_pop( $this->operators ) ) {
-                       $this->doOperation( $op, $this->operands );
-               }
-
-               // Make sure the result is sane. The first case is possible for an empty
-               // string input, the second should be unreachable.
-               if ( !count( $this->operands ) ) {
-                       $this->error( 'condition expected' );
-               } elseif ( count( $this->operands ) > 1 ) {
-                       $this->error( 'missing operator or too many operands' );
-               }
-
-               $value = $this->operands[0];
-               if ( $value->type !== 'boolean' ) {
-                       $this->error( 'the result must have a boolean type' );
-               }
-
-               return $this->operands[0]->rpn;
-       }
-
-       /**
-        * Fetch the next token from the input string.
-        *
-        * @return CLDRPluralRuleConverter_Fragment The next token
-        */
-       protected function nextToken() {
-               if ( $this->pos >= $this->end ) {
-                       return false;
-               }
-
-               // Whitespace
-               $length = strspn( $this->rule, self::WHITESPACE_CLASS, $this->pos );
-               $this->pos += $length;
-
-               if ( $this->pos >= $this->end ) {
-                       return false;
-               }
-
-               // Number
-               $length = strspn( $this->rule, self::NUMBER_CLASS, $this->pos );
-               if ( $length !== 0 ) {
-                       $token = $this->newNumber( substr( $this->rule, $this->pos, $length ), $this->pos );
-                       $this->pos += $length;
-                       return $token;
-               }
-
-               // Two-character operators
-               $op2 = substr( $this->rule, $this->pos, 2 );
-               if ( $op2 === '..' || $op2 === '!=' ) {
-                       $token = $this->newOperator( $op2, $this->pos, 2 );
-                       $this->pos += 2;
-                       return $token;
-               }
-
-               // Single-character operators
-               $op1 = $this->rule[$this->pos];
-               if ( $op1 === ',' || $op1 === '=' || $op1 === '%' ) {
-                       $token = $this->newOperator( $op1, $this->pos, 1 );
-                       $this->pos ++;
-                       return $token;
-               }
-
-               // Word
-               if ( !preg_match( self::WORD_REGEX, $this->rule, $m, 0, $this->pos ) ) {
-                       $this->error( 'unexpected character "' . $this->rule[$this->pos] . '"' );
-               }
-               $word1 = strtolower( $m[0] );
-               $word2 = '';
-               $nextTokenPos = $this->pos + strlen( $word1 );
-               if ( $word1 === 'not' || $word1 === 'is' ) {
-                       // Look ahead one word
-                       $nextTokenPos += strspn( $this->rule, self::WHITESPACE_CLASS, $nextTokenPos );
-                       if ( $nextTokenPos < $this->end
-                               && preg_match( self::WORD_REGEX, $this->rule, $m, 0, $nextTokenPos )
-                       ) {
-                               $word2 = strtolower( $m[0] );
-                               $nextTokenPos += strlen( $word2 );
-                       }
-               }
-
-               // Two-word operators like "is not" take precedence over single-word operators like "is"
-               if ( $word2 !== '' ) {
-                       $bothWords = "{$word1}-{$word2}";
-                       if ( isset( self::$precedence[$bothWords] ) ) {
-                               $token = $this->newOperator( $bothWords, $this->pos, $nextTokenPos - $this->pos );
-                               $this->pos = $nextTokenPos;
-                               return $token;
-                       }
-               }
-
-               // Single-word operators
-               if ( isset( self::$precedence[$word1] ) ) {
-                       $token = $this->newOperator( $word1, $this->pos, strlen( $word1 ) );
-                       $this->pos += strlen( $word1 );
-                       return $token;
-               }
-
-               // The single-character operand symbols
-               if ( strpos( self::OPERAND_SYMBOLS, $word1 ) !== false ) {
-                       $token = $this->newNumber( $word1, $this->pos );
-                       $this->pos ++;
-                       return $token;
-               }
-
-               // Samples
-               if ( $word1 === '@integer' || $word1 === '@decimal' ) {
-                       // Samples are like comments, they have no effect on rule evaluation.
-                       // They run from the first sample indicator to the end of the string.
-                       $this->pos = $this->end;
-                       return false;
-               }
-
-               $this->error( 'unrecognised word' );
-       }
-
-       /**
-        * For the binary operator $op, pop its operands off the stack and push
-        * a fragment with rpn and type members describing the result of that
-        * operation.
-        *
-        * @param CLDRPluralRuleConverter_Operator $op
-        */
-       protected function doOperation( $op ) {
-               if ( count( $this->operands ) < 2 ) {
-                       $op->error( 'missing operand' );
-               }
-               $right = array_pop( $this->operands );
-               $left = array_pop( $this->operands );
-               $result = $op->operate( $left, $right );
-               $this->operands[] = $result;
-       }
-
-       /**
-        * Create a numerical expression object
-        *
-        * @param string $text
-        * @param int $pos
-        * @return CLDRPluralRuleConverter_Expression The numerical expression
-        */
-       protected function newNumber( $text, $pos ) {
-               return new CLDRPluralRuleConverter_Expression( $this, 'number', $text, $pos, strlen( $text ) );
-       }
-
-       /**
-        * Create a binary operator
-        *
-        * @param string $type
-        * @param int $pos
-        * @param int $length
-        * @return CLDRPluralRuleConverter_Operator The operator
-        */
-       protected function newOperator( $type, $pos, $length ) {
-               return new CLDRPluralRuleConverter_Operator( $this, $type, $pos, $length );
-       }
-
-       /**
-        * Throw an error
-        */
-       protected function error( $message ) {
-               throw new CLDRPluralRuleError( $message );
-       }
-}
-
-/**
- * Helper for CLDRPluralRuleConverter.
- * The base class for operators and expressions, describing a region of the input string.
- */
-class CLDRPluralRuleConverter_Fragment {
-       public $parser, $pos, $length, $end;
-
-       function __construct( $parser, $pos, $length ) {
-               $this->parser = $parser;
-               $this->pos = $pos;
-               $this->length = $length;
-               $this->end = $pos + $length;
-       }
-
-       public function error( $message ) {
-               $text = $this->getText();
-               throw new CLDRPluralRuleError( "$message at position " . ( $this->pos + 1 ) . ": \"$text\"" );
-       }
-
-       public function getText() {
-               return substr( $this->parser->rule, $this->pos, $this->length );
-       }
-}
-
-/**
- * Helper for CLDRPluralRuleConverter.
- * An expression object, representing a region of the input string (for error
- * messages), the RPN notation used to evaluate it, and the result type for
- * validation.
- */
-class CLDRPluralRuleConverter_Expression extends CLDRPluralRuleConverter_Fragment {
-       /** @var string */
-       public $type;
-
-       /** @var string */
-       public $rpn;
-
-       function __construct( $parser, $type, $rpn, $pos, $length ) {
-               parent::__construct( $parser, $pos, $length );
-               $this->type = $type;
-               $this->rpn = $rpn;
-       }
-
-       public function isType( $type ) {
-               if ( $type === 'range' && ( $this->type === 'range' || $this->type === 'number' ) ) {
-                       return true;
-               }
-               if ( $type === $this->type ) {
-                       return true;
-               }
-               return false;
-       }
-}
-
-/**
- * Helper for CLDRPluralRuleConverter.
- * An operator object, representing a region of the input string (for error
- * messages), and the binary operator at that location.
- */
-class CLDRPluralRuleConverter_Operator extends CLDRPluralRuleConverter_Fragment {
-       /** @var string The name */
-       public $name;
-
-       /**
-        * Each op type has three characters: left operand type, right operand type and result type
-        *
-        *   b = boolean
-        *   n = number
-        *   r = range
-        *
-        * A number is a kind of range.
-        *
-        * @var array
-        */
-       static $opTypes = array(
-               'or' => 'bbb',
-               'and' => 'bbb',
-               'is' => 'nnb',
-               'is-not' => 'nnb',
-               'in' => 'nrb',
-               'not-in' => 'nrb',
-               'within' => 'nrb',
-               'not-within' => 'nrb',
-               'mod' => 'nnn',
-               ',' => 'rrr',
-               '..' => 'nnr',
-       );
-
-       /**
-        * Map converting from the abbrevation to the full form.
-        *
-        * @var array
-        */
-       static $typeSpecMap = array(
-               'b' => 'boolean',
-               'n' => 'number',
-               'r' => 'range',
-       );
-
-       /**
-        * Map for converting the new operators introduced in Rev 33 to the old forms
-        */
-       static $aliasMap = array(
-               '%' => 'mod',
-               '!=' => 'not-in',
-               '=' => 'in'
-       );
-
-       /**
-        * Initialize a new instance of a CLDRPluralRuleConverter_Operator object
-        *
-        * @param CLDRPluralRuleConverter $parser The parser
-        * @param string $name The operator name
-        * @param int $pos The length
-        * @param int $length
-        */
-       function __construct( $parser, $name, $pos, $length ) {
-               parent::__construct( $parser, $pos, $length );
-               if ( isset( self::$aliasMap[$name] ) ) {
-                       $name = self::$aliasMap[$name];
-               }
-               $this->name = $name;
-       }
-
-       /**
-        * Compute the operation
-        *
-        * @param CLDRPluralRuleConverter_Expression $left The left part of the expression
-        * @param CLDRPluralRuleConverter_Expression $right The right part of the expression
-        * @return CLDRPluralRuleConverter_Expression The result of the operation
-        */
-       public function operate( $left, $right ) {
-               $typeSpec = self::$opTypes[$this->name];
-
-               $leftType = self::$typeSpecMap[$typeSpec[0]];
-               $rightType = self::$typeSpecMap[$typeSpec[1]];
-               $resultType = self::$typeSpecMap[$typeSpec[2]];
-
-               $start = min( $this->pos, $left->pos, $right->pos );
-               $end = max( $this->end, $left->end, $right->end );
-               $length = $end - $start;
-
-               $newExpr = new CLDRPluralRuleConverter_Expression( $this->parser, $resultType,
-                       "{$left->rpn} {$right->rpn} {$this->name}",
-                       $start, $length );
-
-               if ( !$left->isType( $leftType ) ) {
-                       $newExpr->error( "invalid type for left operand: expected $leftType, got {$left->type}" );
-               }
-
-               if ( !$right->isType( $rightType ) ) {
-                       $newExpr->error( "invalid type for right operand: expected $rightType, got {$right->type}" );
-               }
-               return $newExpr;
-       }
-}
-
-/**
- * The exception class for all the classes in this file. This will be thrown
- * back to the caller if there is any validation error.
- */
-class CLDRPluralRuleError extends MWException {
-       function __construct( $message ) {
-               parent::__construct( 'CLDR plural rule error: ' . $message );
-       }
-}
diff --git a/languages/utils/CLDRPluralRuleEvaluator_Range.php b/languages/utils/CLDRPluralRuleEvaluator_Range.php
new file mode 100644 (file)
index 0000000..9732b8d
--- /dev/null
@@ -0,0 +1,108 @@
+<?php
+/**
+ * @author Niklas Laxström, Tim Starling
+ *
+ * @copyright Copyright © 2010-2012, Niklas Laxström
+ * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
+ *
+ * @file
+ * @since 1.20
+ */
+
+/**
+ * Evaluator helper class representing a range list.
+ */
+class CLDRPluralRuleEvaluator_Range {
+       /**
+        * The parts
+        *
+        * @var array
+        */
+       public $parts = array();
+
+       /**
+        * Initialize a new instance of CLDRPluralRuleEvaluator_Range
+        *
+        * @param int $start The start of the range
+        * @param int|bool $end The end of the range, or false if the range is not bounded.
+        */
+       function __construct( $start, $end = false ) {
+               if ( $end === false ) {
+                       $this->parts[] = $start;
+               } else {
+                       $this->parts[] = array( $start, $end );
+               }
+       }
+
+       /**
+        * Determine if the given number is inside the range.
+        *
+        * @param int $number The number to check
+        * @param bool $integerConstraint If true, also asserts the number is an integer; otherwise, number simply has to be inside the range.
+        * @return bool True if the number is inside the range; otherwise, false.
+        */
+       function isNumberIn( $number, $integerConstraint = true ) {
+               foreach ( $this->parts as $part ) {
+                       if ( is_array( $part ) ) {
+                               if ( ( !$integerConstraint || floor( $number ) === (float)$number )
+                                       && $number >= $part[0] && $number <= $part[1]
+                               ) {
+                                       return true;
+                               }
+                       } else {
+                               if ( $number == $part ) {
+                                       return true;
+                               }
+                       }
+               }
+               return false;
+       }
+
+       /**
+        * Readable alias for isNumberIn( $number, false ), and the implementation
+        * of the "within" operator.
+        *
+        * @param int $number The number to check
+        * @return bool True if the number is inside the range; otherwise, false.
+        */
+       function isNumberWithin( $number ) {
+               return $this->isNumberIn( $number, false );
+       }
+
+       /**
+        * Add another part to this range.
+        *
+        * @param CLDRPluralRuleEvaluator_Range|int $other The part to add, either
+        *   a range object itself or a single number.
+        */
+       function add( $other ) {
+               if ( $other instanceof self ) {
+                       $this->parts = array_merge( $this->parts, $other->parts );
+               } else {
+                       $this->parts[] = $other;
+               }
+       }
+
+       /**
+        * Returns the string representation of the rule evaluator range.
+        * The purpose of this method is to help debugging.
+        *
+        * @return string The string representation of the rule evaluator range
+        */
+       function __toString() {
+               $s = 'Range(';
+               foreach ( $this->parts as $i => $part ) {
+                       if ( $i ) {
+                               $s .= ', ';
+                       }
+                       if ( is_array( $part ) ) {
+                               $s .= $part[0] . '..' . $part[1];
+                       } else {
+                               $s .= $part;
+                       }
+               }
+               $s .= ')';
+               return $s;
+       }
+
+}
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',
index bfe04d7..9847ccc 100644 (file)
@@ -91,7 +91,7 @@ class ResetUserTokens extends Maintenance {
 
                        wfWaitForSlaves();
 
-               } while ( $max <= $maxid );
+               } while ( $min <= $maxid );
 
        }
 
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 cd657ac..dc9c763 100644 (file)
@@ -36,6 +36,7 @@ class RunJobs extends Maintenance {
                $this->addOption( 'maxtime', 'Maximum amount of wall-clock time', false, true );
                $this->addOption( 'type', 'Type of job to run', false, true );
                $this->addOption( 'procs', 'Number of processes to use', false, true );
+               $this->addOption( 'nothrottle', 'Ignore job throttling configuration', false, false );
        }
 
        public function memoryLimit() {
@@ -66,6 +67,7 @@ class RunJobs extends Maintenance {
                $type = $this->getOption( 'type', false );
                $maxJobs = $this->getOption( 'maxjobs', false );
                $maxTime = $this->getOption( 'maxtime', false );
+               $noThrottle = $this->hasOption( 'nothrottle' );
                $startTime = time();
 
                $group = JobQueueGroup::singleton();
@@ -83,10 +85,12 @@ class RunJobs extends Maintenance {
                $flags = JobQueueGroup::USE_CACHE;
                $lastTime = time(); // time since last slave check
                do {
+                       $backoffs = array_filter( $backoffs, $backoffExpireFunc );
+                       $blacklist = $noThrottle ? array() : array_keys( $backoffs );
                        if ( $type === false ) {
-                               $backoffs = array_filter( $backoffs, $backoffExpireFunc );
-                               $blacklist = array_keys( $backoffs );
                                $job = $group->pop( JobQueueGroup::TYPE_DEFAULT, $flags, $blacklist );
+                       } elseif ( in_array( $type, $blacklist ) ) {
+                               $job = false; // requested queue in backoff state
                        } else {
                                $job = $group->pop( $type ); // job from a single queue
                        }
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 6e0d717..642897c 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,194 @@ 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 +536,105 @@ 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',
-               'dependencies' => 'jquery',
+               'scripts' => 'resources/lib/jquery.effects/jquery.effects.core.js',
                '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,100 +642,100 @@ 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',
@@ -742,17 +743,17 @@ return array(
                ),
        ),
        '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',
@@ -760,12 +761,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',
@@ -774,15 +775,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',
@@ -806,28 +807,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',
@@ -836,28 +837,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',
@@ -865,7 +866,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',
@@ -873,7 +874,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',
                ),
@@ -881,11 +882,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',
@@ -895,7 +896,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',
@@ -909,7 +910,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',
@@ -918,12 +919,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',
@@ -931,7 +932,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',
@@ -939,31 +940,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'
@@ -973,17 +974,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'
                ),
@@ -1001,23 +1002,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',
@@ -1027,7 +1028,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',
                ),
@@ -1035,17 +1036,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',
@@ -1054,7 +1055,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,
@@ -1066,16 +1067,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',
@@ -1086,16 +1087,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',
@@ -1112,7 +1112,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',
@@ -1131,29 +1131,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',
                ),
@@ -1163,31 +1163,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',
@@ -1200,13 +1200,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',
@@ -1214,11 +1214,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',
@@ -1234,25 +1234,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',
@@ -1260,7 +1260,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',
@@ -1274,7 +1274,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',
@@ -1284,7 +1284,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 */
@@ -1357,8 +1357,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' ),
@@ -1366,8 +1366,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' ),
@@ -1378,20 +1378,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 30e4484..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-/**
- * 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/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..409022a
--- /dev/null
@@ -0,0 +1,17 @@
+{
+    "@metadata": {
+        "authors": [
+            "Aftab1995",
+            "Bellayet",
+            "Jayantanth",
+            "Nasir8891",
+            "Runab",
+            "Sayak Sarkar"
+        ]
+    },
+    "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/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..5381fd1
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "Sovichet"
+        ]
+    },
+    "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/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/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..9629087
--- /dev/null
@@ -0,0 +1,790 @@
+.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-fieldLayout-disabled .oo-ui-labeledElement-label {
+  color: #ccc;
+}
+
+.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;
+  border-color: rgba(0, 0, 0, 0.05);
+}
+
+.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..6e00086
--- /dev/null
@@ -0,0 +1,8239 @@
+/*!
+ * OOjs UI v0.1.0-pre (ac6848398c)
+ * 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: Wed Apr 09 2014 17:58:17 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 );
+};
+/**
+ * Modal dialog window.
+ *
+ * @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 that can be added, removed, listed and checked.
+ *
+ * A flag, when set, adds a CSS class on the `$element` by combing `oo-ui-flaggableElement-` with
+ * the flag name. Flags are primarily useful for styling.
+ *
+ * @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 tool groups.
+ *
+ * @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 ) );
+       }
+       this.field.connect( this, { 'disable': 'onFieldDisable' } );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-fieldLayout' );
+       this.$field
+               .addClass( 'oo-ui-fieldLayout-field' )
+               .toggleClass( 'oo-ui-fieldLayout-disable', this.field.isDisabled() )
+               .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 */
+
+/**
+ * Handle field disable events.
+ *
+ * @param {boolean} value Field is disabled
+ */
+OO.ui.FieldLayout.prototype.onFieldDisable = function ( value ) {
+       this.$element.toggleClass( 'oo-ui-fieldLayout-disabled', value );
+};
+
+/**
+ * Handle 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 booklet layout.
+ *
+ * @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( ', ' ) || ' ' );
+};
+/**
+ * Tool that shows a popup when selected.
+ *
+ * @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;
+};
+/**
+ * Icon widget.
+ *
+ * @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';
+/**
+ * Indicator widget.
+ *
+ * @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.
+ *
+ * Use together with OO.ui.ButtonWidget.
+ *
+ * @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 );
+/**
+ * Button widget.
+ *
+ * @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;
+};
+/**
+ * Input widget.
+ *
+ * @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;
+};
+/**
+ * Checkbox widget.
+ *
+ * @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 ) );
+       }
+};
+/**
+ * Label widget.
+ *
+ * @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 [];
+};
+/**
+ * Option widget.
+ *
+ * Use with OO.ui.SelectWidget.
+ *
+ * @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;
+};
+/**
+ * Selection of options.
+ *
+ * Use together with OO.ui.OptionWidget.
+ *
+ * @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;
+};
+/**
+ * Menu item widget.
+ *
+ * Use with OO.ui.MenuWidget.
+ *
+ * @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 );
+/**
+ * Menu widget.
+ *
+ * Use together with OO.ui.MenuItemWidget.
+ *
+ * @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.
+ *
+ * Use with OO.ui.MenuOptionWidget.
+ *
+ * @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;
+
+       if ( !item ) {
+               return;
+       }
+
+       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;
+};
+/**
+ * Menu section item widget.
+ *
+ * Use with OO.ui.MenuWidget.
+ *
+ * @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.
+ *
+ * Use with OO.ui.OutlineItemWidget.
+ *
+ * @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.
+ *
+ * Use together with OO.ui.OutlineWidget.js
+ *
+ * @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.
+ *
+ * Use with OO.ui.OutlineWidget.
+ *
+ * @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;
+};
+/**
+ * Option widget that looks like a button.
+ *
+ * Use together with OO.ui.ButtonSelectWidget.
+ *
+ * @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;
+};
+/**
+ * Select widget containing button options.
+ *
+ * Use together with OO.ui.ButtonOptionWidget.
+ *
+ * @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 );
+/**
+ * Container for content that is overlaid and positioned absolutely.
+ *
+ * @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;
+};
+/**
+ * Search widget.
+ *
+ * Combines query and results selection widgets.
+ *
+ * @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;
+};
+/**
+ * Text input widget.
+ *
+ * @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;
+};
+/**
+ * Menu for a text input widget.
+ *
+ * @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;
+};
+/**
+ * Width with on and off states.
+ *
+ * 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;
+};
+/**
+ * Button that toggles on and off.
+ *
+ * @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;
+};
+/**
+ * Switch that slides on and off.
+ *
+ * @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..b2ba750
--- /dev/null
@@ -0,0 +1,1230 @@
+/*!
+ * OOjs UI v0.1.0-pre (ac6848398c)
+ * 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: Wed Apr 09 2014 17:58:17 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 2bcc384..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 f300672..0000000
+++ /dev/null
@@ -1,352 +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'
-                       }
-               },
-               // 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/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 eb38936..0000000
+++ /dev/null
@@ -1,284 +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 ****/
-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/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 6233fd5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<?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/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 44d5587..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<?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/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 a0d217d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<?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/mediawiki/mediawiki.Title.js b/resources/mediawiki/mediawiki.Title.js
deleted file mode 100644 (file)
index 707f8d5..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
-                *
-                * 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/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 0a0b4f6..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 57f85d8..0000000
+++ /dev/null
@@ -1,2417 +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
-                                * @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/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 19d9c7e..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 00cd433..0000000
+++ /dev/null
@@ -1,782 +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-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-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-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/oojs-ui/oojs-ui.js b/resources/oojs-ui/oojs-ui.js
deleted file mode 100644 (file)
index 1565cbb..0000000
+++ /dev/null
@@ -1,8203 +0,0 @@
-/*!
- * OOjs UI v0.1.0-pre (eaa1b7f06d)
- * 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: Thu Apr 03 2014 16:56:21 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;
-       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 );
-};
-
-/* 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.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 );
-       }
-};
-
-/* 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 press
- * @param {OO.ui.OptionWidget|null} item Pressed 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.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.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.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 );
-               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( 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;
-};
-
-/**
- * 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 a7eecc1..0000000
+++ /dev/null
@@ -1,1230 +0,0 @@
-/*!
- * OOjs UI v0.1.0-pre (eaa1b7f06d)
- * 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: Thu Apr 03 2014 16:56:21 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..de05fdf
--- /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 occurred.
+        *
+        * @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..28c4731
--- /dev/null
@@ -0,0 +1,619 @@
+/**
+ * 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 ) {
+               function maybeFetch() {
+                       // 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
+                       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() );
+                               }
+                       }
+
+                       // Always update special rendering
+                       $.suggestions.special( context );
+               }
+
+               // 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();
+               }
+       },
+
+       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 occurred 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..b37e2a6
--- /dev/null
@@ -0,0 +1,384 @@
+( 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, key, formData;
+
+                       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;
+                       }
+
+                       // If multipart/form-data has been requested and emulation is possible, emulate it
+                       if (
+                               ajaxOptions.type === 'POST' &&
+                               window.FormData &&
+                               ajaxOptions.contentType === 'multipart/form-data'
+                       ) {
+
+                               formData = new FormData();
+
+                               for ( key in parameters ) {
+                                       formData.append( key, parameters[key] );
+                               }
+                               // If we extracted a token parameter, add it back in.
+                               if ( token ) {
+                                       formData.append( 'token', token );
+                               }
+
+                               ajaxOptions.data = formData;
+
+                               // Prevent jQuery from mangling our FormData object
+                               ajaxOptions.processData = false;
+                               // Prevent jQuery from overriding the Content-Type header
+                               ajaxOptions.contentType = false;
+                       } else {
+                               // 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 );
+                               }
+
+                               if ( ajaxOptions.contentType === 'multipart/form-data' ) {
+                                       // We were asked to emulate but can't, so drop the Content-Type header, otherwise
+                                       // it'll be wrong and the server will fail to decode the POST body
+                                       delete ajaxOptions.contentType;
+                               }
+                       }
+
+                       // 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..50349c3
--- /dev/null
@@ -0,0 +1,283 @@
+
+/**** 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,
+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..8ce9b58
--- /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
+                *
+                * 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..9b0711a
--- /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..32a9927
--- /dev/null
@@ -0,0 +1,1239 @@
+/*!
+* 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 ) {
+                               var fallback = parser.settings.messages.get( key );
+                               mw.log.warn( 'mediawiki.jqueryMsg: ' + key + ': ' + e.message );
+                               return $( '<span>' ).text( fallback );
+                       }
+               };
+       }
+
+       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 03f133e..3174af1 100644 (file)
@@ -91,7 +91,7 @@ relativeforfloats = window.relativeforfloats = function () {
 setrelative = window.setrelative = function ( nodes ) {
        var i = 0;
        while ( i < nodes.length ) {
-               if ( ( ( nodes[i].style.float && nodes[i].style.float !== ( 'none' ) ||
+               if ( ( ( nodes[i].style['float'] && nodes[i].style['float'] !== ( 'none' ) ||
                        ( nodes[i].align && nodes[i].align !== ( 'none' ) ) ) &&
                        ( !nodes[i].style.position || nodes[i].style.position !== 'relative' ) ) )
                {
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 00bd26b..6b052b3 100644 (file)
@@ -1208,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 9b8c41a..25ba301 100644 (file)
@@ -28,7 +28,6 @@ body {
 
 /* Content */
 div#content {
-       line-height: @content-line-height;
        margin-left: 10em;
        padding: @content-padding;
        /* Border on top, left, and bottom side */
@@ -131,7 +130,7 @@ pre, .mw-code {
 #bodyContent {
        position: relative;
        width: 100%;
-       line-height: 1.5em;
+       line-height: @content-line-height;
        font-size: @content-font-size;
 }
 
index 60792d5..91388c6 100644 (file)
@@ -1,9 +1,10 @@
-// FIXME: This size of this CSS is ridiculous. Please refactor (see bug 54604)
 @import "mediawiki.mixins.less";
 // 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;
+#content {
+       .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;
+       }
 }
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 5eb5c0a..7694d4a 100644 (file)
@@ -6,8 +6,8 @@
   },
   "devDependencies": {
     "grunt": "0.4.2",
-    "grunt-contrib-jshint": "0.8.0",
-    "grunt-contrib-watch": "0.5.3",
-    "grunt-jscs-checker": "0.4.0"
+    "grunt-contrib-jshint": "0.9.2",
+    "grunt-contrib-watch": "0.6.1",
+    "grunt-jscs-checker": "0.4.1"
   }
 }
index f67f696..4e30bdd 100644 (file)
@@ -437,11 +437,11 @@ class GlobalTest extends MediaWikiTestCase {
        }
 
        /**
-        * @param String $old: Text as it was in the database
-        * @param String $mine: Text submitted while user was editing
-        * @param String $yours: Text submitted by the user
-        * @param Boolean $expectedMergeResult Whether the merge should be a success
-        * @param String $expectedText: Text after merge has been completed
+        * @param string $old Text as it was in the database
+        * @param string $mine Text submitted while user was editing
+        * @param string $yours Text submitted by the user
+        * @param bool $expectedMergeResult Whether the merge should be a success
+        * @param string $expectedText Text after merge has been completed
         *
         * @dataProvider provideMerge()
         * @group medium
index fc23919..48a4017 100644 (file)
@@ -179,7 +179,7 @@ class RevisionTest extends MediaWikiTestCase {
         * @param string $text
         * @param string $title
         * @param string $model
-        * @param null $format
+        * @param string $format
         *
         * @return Revision
         */
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() );
+       }
 }
index 1d534ee..c0612d1 100644 (file)
@@ -96,10 +96,10 @@ class RandomImageGenerator {
        /**
         * Writes random images with random filenames to disk in the directory you specify, or current working directory
         *
-        * @param $number Integer: number of filenames to write
-        * @param $format String: optional, must be understood by ImageMagick, such as 'jpg' or 'gif'
-        * @param $dir String: directory, optional (will default to current working directory)
-        * @return Array: filenames we just wrote
+        * @param int $number number of filenames to write
+        * @param string $format optional, must be understood by ImageMagick, such as 'jpg' or 'gif'
+        * @param string $dir directory, optional (will default to current working directory)
+        * @return array filenames we just wrote
         */
        function writeImages( $number, $format = 'jpg', $dir = null ) {
                $filenames = $this->getRandomFilenames( $number, $format, $dir );
@@ -139,10 +139,10 @@ class RandomImageGenerator {
         * Return a number of randomly-generated filenames
         * Each filename uses two words randomly drawn from the dictionary, like elephantine_spatula.jpg
         *
-        * @param $number Integer: of filenames to generate
-        * @param $extension String: optional, defaults to 'jpg'
-        * @param $dir String: optional, defaults to current working directory
-        * @return Array: of filenames
+        * @param int $number Number of filenames to generate
+        * @param string $extension Optional, defaults to 'jpg'
+        * @param string $dir Optional, defaults to current working directory
+        * @return array Array of filenames
         */
        private function getRandomFilenames( $number, $extension = 'jpg', $dir = null ) {
                if ( is_null( $dir ) ) {
@@ -208,7 +208,7 @@ class RandomImageGenerator {
         * Given array( array('x' => 10, 'y' => 20), array( 'x' => 30, y=> 5 ) )
         * returns "10,20 30,5"
         * Useful for SVG and imagemagick command line arguments
-        * @param $shape: Array of arrays, each array containing x & y keys mapped to numeric values
+        * @param array $shape Array of arrays, each array containing x & y keys mapped to numeric values
         * @return string
         */
        static function shapePointsToString( $shape ) {
@@ -347,10 +347,10 @@ class RandomImageGenerator {
 
        /**
         * Given a matrix and a pair of images, return new position
-        * @param $matrix: 2x2 rotation matrix
-        * @param $x: x-coordinate number
-        * @param $y: y-coordinate number
-        * @return Array transformed with properties x, y
+        * @param array $matrix 2x2 rotation matrix
+        * @param int $x x-coordinate number
+        * @param int $y y-coordinate number
+        * @return array Transformed with properties x, y
         */
        private static function matrixMultiply2x2( $matrix, $x, $y ) {
                return array(
@@ -412,8 +412,8 @@ class RandomImageGenerator {
        /**
         * Get an array of random pairs of random words, like array( array( 'foo', 'bar' ), array( 'quux', 'baz' ) );
         *
-        * @param $number Integer: number of pairs
-        * @return Array: of two-element arrays
+        * @param int $number Number of pairs
+        * @return array two-element arrays
         */
        private function getRandomWordPairs( $number ) {
                $lines = $this->getRandomLines( $number * 2 );
index d1c214a..080ff54 100644 (file)
@@ -315,22 +315,24 @@ class DummyContentHandlerForTesting extends ContentHandler {
        }
 
        /**
-        * Serializes Content object of the type supported by this ContentHandler.
+        * @see ContentHandler::serializeContent
         *
-        * @param Content $content the Content object to serialize
-        * @param null $format the desired serialization format
-        * @return String serialized form of the content
+        * @param Content $content
+        * @param string $format
+        *
+        * @return string
         */
        public function serializeContent( Content $content, $format = null ) {
                return $content->serialize();
        }
 
        /**
-        * Unserializes a Content object of the type supported by this ContentHandler.
+        * @see ContentHandler::unserializeContent
+        *
+        * @param string $blob
+        * @param string $format Unused.
         *
-        * @param $blob String serialized form of the content
-        * @param null $format the format used for serialization
-        * @return Content the Content object created by deserializing $blob
+        * @return Content
         */
        public function unserializeContent( $blob, $format = null ) {
                $d = unserialize( $blob );
@@ -437,7 +439,7 @@ class DummyContentForTesting extends AbstractContent {
 
        /**
         * @param Title $title
-        * @param null $revId
+        * @param int $revId Unused.
         * @param null|ParserOptions $options
         * @param boolean $generateHtml whether to generate Html (default: true). If false,
         *  the result of calling getText() on the ParserOutput object returned by
index 3319490..70374dc 100644 (file)
@@ -108,8 +108,8 @@ class JobQueueTest extends MediaWikiTestCase {
                $this->assertEquals( 0, $queue->getSize(), "Queue is empty ($desc)" );
                $this->assertEquals( 0, $queue->getAcquiredCount(), "Queue is empty ($desc)" );
 
-               $this->assertTrue( $queue->push( $this->newJob() ), "Push worked ($desc)" );
-               $this->assertTrue( $queue->batchPush( array( $this->newJob() ) ), "Push worked ($desc)" );
+               $this->assertNull( $queue->push( $this->newJob() ), "Push worked ($desc)" );
+               $this->assertNull( $queue->batchPush( array( $this->newJob() ) ), "Push worked ($desc)" );
 
                $this->assertFalse( $queue->isEmpty(), "Queue is not empty ($desc)" );
 
@@ -157,7 +157,7 @@ class JobQueueTest extends MediaWikiTestCase {
                $queue->flushCaches();
                $this->assertEquals( 0, $queue->getAcquiredCount(), "Active job count ($desc)" );
 
-               $this->assertTrue( $queue->batchPush( array( $this->newJob(), $this->newJob() ) ),
+               $this->assertNull( $queue->batchPush( array( $this->newJob(), $this->newJob() ) ),
                        "Push worked ($desc)" );
                $this->assertFalse( $queue->isEmpty(), "Queue is not empty ($desc)" );
 
@@ -183,7 +183,7 @@ class JobQueueTest extends MediaWikiTestCase {
                $this->assertEquals( 0, $queue->getSize(), "Queue is empty ($desc)" );
                $this->assertEquals( 0, $queue->getAcquiredCount(), "Queue is empty ($desc)" );
 
-               $this->assertTrue(
+               $this->assertNull(
                        $queue->batchPush(
                                array( $this->newDedupedJob(), $this->newDedupedJob(), $this->newDedupedJob() )
                        ),
@@ -195,7 +195,7 @@ class JobQueueTest extends MediaWikiTestCase {
                $this->assertEquals( 1, $queue->getSize(), "Queue size is correct ($desc)" );
                $this->assertEquals( 0, $queue->getAcquiredCount(), "No jobs active ($desc)" );
 
-               $this->assertTrue(
+               $this->assertNull(
                        $queue->batchPush(
                                array( $this->newDedupedJob(), $this->newDedupedJob(), $this->newDedupedJob() )
                        ),
@@ -244,7 +244,7 @@ class JobQueueTest extends MediaWikiTestCase {
                $id = wfRandomString( 32 );
                $root1 = Job::newRootJobParams( "nulljobspam:$id" ); // task ID/timestamp
                for ( $i = 0; $i < 5; ++$i ) {
-                       $this->assertTrue( $queue->push( $this->newJob( 0, $root1 ) ), "Push worked ($desc)" );
+                       $this->assertNull( $queue->push( $this->newJob( 0, $root1 ) ), "Push worked ($desc)" );
                }
                $queue->deduplicateRootJob( $this->newJob( 0, $root1 ) );
                sleep( 1 ); // roo job timestamp will increase
@@ -252,7 +252,7 @@ class JobQueueTest extends MediaWikiTestCase {
                $this->assertNotEquals( $root1['rootJobTimestamp'], $root2['rootJobTimestamp'],
                        "Root job signatures have different timestamps." );
                for ( $i = 0; $i < 5; ++$i ) {
-                       $this->assertTrue( $queue->push( $this->newJob( 0, $root2 ) ), "Push worked ($desc)" );
+                       $this->assertNull( $queue->push( $this->newJob( 0, $root2 ) ), "Push worked ($desc)" );
                }
                $queue->deduplicateRootJob( $this->newJob( 0, $root2 ) );
 
@@ -296,7 +296,7 @@ class JobQueueTest extends MediaWikiTestCase {
                $this->assertEquals( 0, $queue->getAcquiredCount(), "Queue is empty ($desc)" );
 
                for ( $i = 0; $i < 10; ++$i ) {
-                       $this->assertTrue( $queue->push( $this->newJob( $i ) ), "Push worked ($desc)" );
+                       $this->assertNull( $queue->push( $this->newJob( $i ) ), "Push worked ($desc)" );
                }
 
                for ( $i = 0; $i < 10; ++$i ) {
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 cce1b7e..cfcc771 100644 (file)
@@ -34,6 +34,21 @@ class ResourcesTest extends MediaWikiTestCase {
                $this->assertTrue( strpos( $cssText, '@media' ) === false, 'Stylesheets should not both specify "media" and contain @media' );
        }
 
+       public function testDependencies() {
+               $data = self::getAllModules();
+               $illegalDeps = array( 'jquery', 'mediawiki' );
+
+               foreach ( $data['modules'] as $moduleName => $module ) {
+                       foreach ( $illegalDeps as $illegalDep ) {
+                               $this->assertNotContains(
+                                       $illegalDep,
+                                       $module->getDependencies(),
+                                       "Module '$moduleName' must not depend on '$illegalDep'"
+                               );
+                       }
+               }
+       }
+
        /**
         * Get all registered modules from ResouceLoader.
         */
index 31470e8..74ea58e 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' ),
        ),
@@ -94,7 +94,6 @@ return array(
                        'jquery.tabIndex',
                        'jquery.tablesorter',
                        'jquery.textSelection',
-                       'mediawiki',
                        'mediawiki.api',
                        'mediawiki.api.parse',
                        'mediawiki.api.watch',
index 73ae0e6..7dff354 100644 (file)
         * </code>
         */
        QUnit.newMwEnvironment = ( function () {
-               var log, liveConfig, liveMessages;
+               var warn, log, liveConfig, liveMessages;
 
                liveConfig = mw.config.values;
                liveMessages = mw.messages.values;
 
+               function suppressWarnings() {
+                       warn = mw.log.warn;
+                       mw.log.warn = $.noop;
+               }
+
+               function restoreWarnings() {
+                       if ( warn !== undefined ) {
+                               mw.log.warn = warn;
+                               warn = undefined;
+                       }
+               }
+
                function freshConfigCopy( custom ) {
-                       var copy, warn;
+                       var copy;
                        // Tests should mock all factors that directly influence the tested code.
                        // For backwards compatibility though we set mw.config to a fresh copy of the live
                        // config. This way any modifications made to mw.config during the test will not
                        // affect other tests, nor the global scope outside the test runner.
                        // This is a shallow copy, since overriding an array or object value via "custom"
                        // should replace it. Setting a config property means you override it, not extend it.
-                       // NOTE: It is important that we temporarily disable mw.log#warn as extend() will
-                       // trigger MWDeprecationWarning for each of the deprecated properties.
-                       warn = mw.log.warn;
-                       mw.log.warn = $.noop;
-
+                       // NOTE: It is important that we suppress warnings because extend() will also access
+                       // deprecated properties and trigger deprecation warnings from mw.log#deprecate.
+                       suppressWarnings();
                        copy = $.extend( {}, liveConfig, custom );
-
-                       mw.log.warn = warn;
+                       restoreWarnings();
 
                        return copy;
                }
                                        // Greetings, mock environment!
                                        mw.config.values = freshConfigCopy( localEnv.config );
                                        mw.messages.values = freshMessagesCopy( localEnv.messages );
+                                       this.suppressWarnings = suppressWarnings;
+                                       this.restoreWarnings = restoreWarnings;
 
                                        localEnv.setup.call( this );
                                },
                                        // Farewell, mock environment!
                                        mw.config.values = liveConfig;
                                        mw.messages.values = liveMessages;
+
+                                       // As a convenience feature, automatically restore warnings if they're
+                                       // still suppressed by the end of the test.
+                                       restoreWarnings();
                                }
                        };
                };
index e5066e0..4ee8afa 100644 (file)
                } );
        } );
 
+       QUnit.test( 'FormData support', function ( assert ) {
+               QUnit.expect( 2 );
+
+               var api = new mw.Api();
+
+               api.post( { action: 'test' }, { contentType: 'multipart/form-data' } );
+
+               this.server.respond( function ( request ) {
+                       if ( window.FormData ) {
+                               assert.ok( !request.url.match( /action=/), 'Request has no query string' );
+                               assert.ok( request.requestBody instanceof FormData, 'Request uses FormData body' );
+                       } else {
+                               assert.ok( !request.url.match( /action=test/), 'Request has no query string' );
+                               assert.equal( request.requestBody, 'action=test&format=json', 'Request uses query string body' );
+                       }
+                       request.respond( 200, { 'Content-Type': 'application/json' }, '[]' );
+               } );
+       } );
+
        QUnit.test( 'Deprecated callback methods', function ( assert ) {
                QUnit.expect( 3 );
 
                var api = new mw.Api();
 
+               this.suppressWarnings();
+
                api.get( {}, function () {
                        assert.ok( true, 'Function argument treated as success callback.' );
                } );
@@ -67,6 +88,8 @@
                        }
                } );
 
+               this.restoreWarnings();
+
                this.server.respondWith( /action=query/, function ( request ) {
                        request.respond( 200, { 'Content-Type': 'application/json' }, '[]' );
                } );
index f49be49..f5fd16d 100644 (file)
@@ -1,3 +1,4 @@
+/*jshint -W024 */
 ( function ( mw, $ ) {
        // mw.Title relies on these three config vars
        // Restore them after each test run
index b6a8a46..7a58d38 100644 (file)
@@ -1,3 +1,4 @@
+/*jshint -W024 */
 ( function ( mw, $ ) {
        QUnit.module( 'mediawiki.Uri', QUnit.newMwEnvironment( {
                setup: function () {
index a2ad50d..995c1ed 100644 (file)
 
                // Pipe trick is not supported currently, but should not parse as text either.
                mw.messages.set( 'pipe-trick', '[[Tampa, Florida|]]' );
+               this.suppressWarnings();
                assert.equal(
                        formatParse( 'pipe-trick' ),
-                       'pipe-trick: Parse error at position 0 in input: [[Tampa, Florida|]]',
-                       'Pipe trick should return error string.'
+                       '[[Tampa, Florida|]]',
+                       'Pipe trick should not be parsed.'
                );
+               this.restoreWarnings();
 
                expectedMultipleBars = '<a title="Main Page" href="/wiki/Main_Page">Main|Page</a>';
                mw.messages.set( 'multiple-bars', '[[Main Page|Main|Page]]' );
@@ -734,4 +736,25 @@ QUnit.test( 'HTML', 26, function ( assert ) {
        );
 } );
 
+       QUnit.test( 'Behavior in case of invalid wikitext', 3, function ( assert ) {
+               mw.messages.set( 'invalid-wikitext', '<b>{{FAIL}}</b>' );
+
+               this.suppressWarnings();
+               var logSpy = this.sandbox.spy( mw.log, 'warn' );
+
+               assert.equal(
+                       formatParse( 'invalid-wikitext' ),
+                       '&lt;b&gt;{{FAIL}}&lt;/b&gt;',
+                       'Invalid wikitext: \'parse\' format'
+               );
+
+               assert.equal(
+                       formatText( 'invalid-wikitext' ),
+                       '<b>{{FAIL}}</b>',
+                       'Invalid wikitext: \'text\' format'
+               );
+
+               assert.equal( logSpy.callCount, 2, 'mw.log.warn calls' );
+       } );
+
 }( mediaWiki, jQuery ) );
index 41b0cb7..f20ce67 100644 (file)
@@ -1,3 +1,4 @@
+/*jshint -W024 */
 ( function ( mw, $ ) {
        var specialCharactersPageName;
 
 
        QUnit.test( 'Initial check', 8, function ( assert ) {
                assert.ok( window.jQuery, 'jQuery defined' );
-               assert.ok( window.$, '$j defined' );
-               assert.ok( window.$j, '$j defined' );
+               assert.ok( window.$, '$ defined' );
                assert.strictEqual( window.$, window.jQuery, '$ alias to jQuery' );
+
+               this.suppressWarnings();
+               assert.ok( window.$j, '$j defined' );
                assert.strictEqual( window.$j, window.jQuery, '$j alias to jQuery' );
+               this.restoreWarnings();
 
                assert.ok( window.mediaWiki, 'mediaWiki defined' );
                assert.ok( window.mw, 'mw defined' );
index 8fd789a..4e26bdc 100644 (file)
@@ -73,7 +73,7 @@
                        'Mozilla/5.0 (Series40; NokiaX3-02/05.60; Profile/MIDP-2.1 Configuration/CLDC-1.1) Gecko/20100401 S40OviBrowser/3.2.0.0.6',
                        'Mozilla/5.0 (Series40; Nokia305/05.92; Profile/MIDP-2.1 Configuration/CLDC-1.1) Gecko/20100401 S40OviBrowser/3.7.0.0.11',
                        // Google Glass
-                       'Mozilla/5.0 (Linux; U; Android 4.0.4; en-us; Glass 1 Build/IMM76L; XE11) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30',
+                       'Mozilla/5.0 (Linux; U; Android 4.0.4; en-us; Glass 1 Build/IMM76L; XE11) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30'
                ],
                // No explicit support for or against these browsers, they're
                // given a shot at Grade A at their own risk.