Partial revert of r59446: add js2stopgap.js back in, some extensions (at least Usabil...
authorRoan Kattouw <catrope@users.mediawiki.org>
Thu, 26 Nov 2009 14:24:56 +0000 (14:24 +0000)
committerRoan Kattouw <catrope@users.mediawiki.org>
Thu, 26 Nov 2009 14:24:56 +0000 (14:24 +0000)
528 files changed:
js2/README [new file with mode: 0644]
js2/ajaxcategories.js [new file with mode: 0644]
js2/apiProxyPage.js [new file with mode: 0644]
js2/editPage.js [new file with mode: 0644]
js2/js2stopgap.js [new file with mode: 0644]
js2/js2stopgap.min.js [new file with mode: 0644]
js2/mwEmbed/README [new file with mode: 0644]
js2/mwEmbed/example_usage/Add_Media_Wizard.html [new file with mode: 0644]
js2/mwEmbed/example_usage/Firefogg_Make_Advanced.html [new file with mode: 0644]
js2/mwEmbed/example_usage/Multi_Upload.html [new file with mode: 0644]
js2/mwEmbed/example_usage/Player_Audio.html [new file with mode: 0644]
js2/mwEmbed/example_usage/Player_RelatedVideos.html [new file with mode: 0644]
js2/mwEmbed/example_usage/Player_Themable.html [new file with mode: 0644]
js2/mwEmbed/example_usage/Player_Timed_Text.html [new file with mode: 0644]
js2/mwEmbed/example_usage/Sequence_Editor.html [new file with mode: 0644]
js2/mwEmbed/example_usage/Sequence_Render.html [new file with mode: 0644]
js2/mwEmbed/example_usage/media/princess_archive_org/princess_iron_fan-cs.srt [new file with mode: 0644]
js2/mwEmbed/example_usage/media/princess_archive_org/princess_iron_fan-ru.srt [new file with mode: 0644]
js2/mwEmbed/example_usage/media/princess_archive_org/princess_iron_fan-zh-hant.srt [new file with mode: 0644]
js2/mwEmbed/example_usage/media/princess_archive_org/princess_iron_fan.srt [new file with mode: 0644]
js2/mwEmbed/example_usage/media/sample_smil.xml [new file with mode: 0644]
js2/mwEmbed/jquery/jquery-1.3.2.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery-1.3.2.min.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/AUTHORS.txt [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/GPL-LICENSE.txt [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/MIT-LICENSE.txt [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/external/bgiframe/ChangeLog.txt [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/external/bgiframe/META.json [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/external/bgiframe/docs/fonts-min.css [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/external/bgiframe/docs/index.html [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/external/bgiframe/docs/reset-min.css [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/external/bgiframe/jquery.bgiframe.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/external/bgiframe/jquery.bgiframe.min.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/external/bgiframe/jquery.bgiframe.pack.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/external/bgiframe/test/index.html [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/external/cookie/jquery.cookie.min.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/external/cookie/jquery.cookie.pack.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/external/cookie/jquery.cookie.zip [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/external/jsdiff/jsdiff.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/external/qunit/testrunner.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/external/qunit/testsuite.css [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/external/simulate/jquery.simulate.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_diagonals-thick_20_666666_40x40.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_flat_0_aaaaaa_40x100.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_glass_55_fbf9ee_1x400.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_glass_65_ffffff_1x400.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_glass_75_dadada_1x400.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_glass_75_e6e6e6_1x400.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_glass_75_ffffff_1x400.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_inset-soft_95_fef1ec_1x100.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-icons_222222_256x240.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-icons_2e83ff_256x240.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-icons_454545_256x240.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-icons_888888_256x240.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-icons_cd0a0a_256x240.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/base/jquery-ui-1.7.1.custom.css [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/base/ui.accordion.css [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/base/ui.all.css [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/base/ui.base.css [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/base/ui.core.css [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/base/ui.datepicker.css [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/base/ui.dialog.css [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/base/ui.progressbar.css [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/base/ui.resizable.css [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/base/ui.slider.css [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/base/ui.tabs.css [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/base/ui.theme.css [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-bg_flat_0_aaaaaa_40x100.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-bg_flat_55_fbec88_40x100.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-bg_glass_75_d0e5f5_1x400.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-bg_glass_85_dfeffc_1x400.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-bg_glass_95_fef1ec_1x400.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-icons_217bc0_256x240.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-icons_2e83ff_256x240.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-icons_469bdd_256x240.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-icons_6da8d5_256x240.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-icons_cd0a0a_256x240.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-icons_d8e7f3_256x240.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-icons_f9bd01_256x240.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/redmond/jquery-ui-1.7.1.custom.css [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_diagonals-thick_20_666666_40x40.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_flat_75_ffffff_40x100.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_glass_65_ffffff_1x400.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_glass_75_dadada_1x400.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-icons_222222_256x240.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-icons_2e83ff_256x240.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-icons_454545_256x240.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-icons_888888_256x240.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-icons_cd0a0a_256x240.png [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/smoothness/jquery-ui-1.7.1.custom.css [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/smoothness/ui.accordion.css [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/smoothness/ui.all.css [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/smoothness/ui.base.css [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/smoothness/ui.core.css [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/smoothness/ui.datepicker.css [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/smoothness/ui.dialog.css [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/smoothness/ui.progressbar.css [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/smoothness/ui.resizable.css [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/smoothness/ui.slider.css [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/smoothness/ui.tabs.css [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/themes/smoothness/ui.theme.css [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/effects.blind.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/effects.bounce.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/effects.clip.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/effects.core.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/effects.drop.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/effects.explode.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/effects.fold.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/effects.highlight.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/effects.pulsate.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/effects.scale.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/effects.shake.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/effects.slide.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/effects.transfer.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/jquery-ui-i18n.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-ar.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-bg.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-ca.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-cs.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-da.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-de.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-el.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-eo.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-es.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-fa.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-fi.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-fr.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-he.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-hr.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-hu.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-hy.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-id.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-is.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-it.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-ja.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-ko.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-lt.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-lv.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-ms.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-nl.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-no.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-pl.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-pt-BR.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-ro.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-ru.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-sk.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-sl.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-sq.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-sr-SR.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-sr.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-sv.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-th.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-tr.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-uk.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-zh-CN.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-zh-TW.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/jquery-ui-1.7.1.custom.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/ui.accordion.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/ui.core.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/ui.datepicker.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/ui.dialog.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/ui.draggable.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/ui.droppable.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/ui.progressbar.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/ui.resizable.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/ui.selectable.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/ui.slider.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/ui.sortable.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/ui/ui.tabs.js [new file with mode: 0644]
js2/mwEmbed/jquery/jquery.ui/version.txt [new file with mode: 0644]
js2/mwEmbed/jquery/plugins/date.js [new file with mode: 0644]
js2/mwEmbed/jquery/plugins/images/cut.png [new file with mode: 0644]
js2/mwEmbed/jquery/plugins/images/door.png [new file with mode: 0644]
js2/mwEmbed/jquery/plugins/images/page_white_copy.png [new file with mode: 0644]
js2/mwEmbed/jquery/plugins/images/page_white_delete.png [new file with mode: 0644]
js2/mwEmbed/jquery/plugins/images/page_white_edit.png [new file with mode: 0644]
js2/mwEmbed/jquery/plugins/images/page_white_paste.png [new file with mode: 0644]
js2/mwEmbed/jquery/plugins/indicator.gif [new file with mode: 0644]
js2/mwEmbed/jquery/plugins/jquery.autocomplete.css [new file with mode: 0644]
js2/mwEmbed/jquery/plugins/jquery.autocomplete.js [new file with mode: 0644]
js2/mwEmbed/jquery/plugins/jquery.bgiframe.js [new file with mode: 0644]
js2/mwEmbed/jquery/plugins/jquery.contextMenu.css [new file with mode: 0644]
js2/mwEmbed/jquery/plugins/jquery.contextMenu.js [new file with mode: 0644]
js2/mwEmbed/jquery/plugins/jquery.cookie.js [new file with mode: 0644]
js2/mwEmbed/jquery/plugins/jquery.datePicker.js [new file with mode: 0644]
js2/mwEmbed/jquery/plugins/jquery.dimensions.js [new file with mode: 0644]
js2/mwEmbed/jquery/plugins/jquery.highlight.js [new file with mode: 0644]
js2/mwEmbed/jquery/plugins/jquery.hoverIntent.js [new file with mode: 0644]
js2/mwEmbed/jquery/plugins/jquery.pngFix.js [new file with mode: 0644]
js2/mwEmbed/jquery/plugins/jquery.suggestions.js [new file with mode: 0644]
js2/mwEmbed/jquery/plugins/jquery.textSelection.js [new file with mode: 0644]
js2/mwEmbed/jquery/plugins/jquery.timers.js [new file with mode: 0644]
js2/mwEmbed/jsScriptLoader.php [new file with mode: 0644]
js2/mwEmbed/libAddMedia/dragDropFile.js [new file with mode: 0644]
js2/mwEmbed/libAddMedia/mvAdvFirefogg.js [new file with mode: 0644]
js2/mwEmbed/libAddMedia/mvBaseUploadInterface.js [new file with mode: 0644]
js2/mwEmbed/libAddMedia/mvFirefogg.js [new file with mode: 0644]
js2/mwEmbed/libAddMedia/remoteSearchDriver.js [new file with mode: 0644]
js2/mwEmbed/libAddMedia/searchLibs/archiveOrgSearch.js [new file with mode: 0644]
js2/mwEmbed/libAddMedia/searchLibs/baseRemoteSearch.js [new file with mode: 0644]
js2/mwEmbed/libAddMedia/searchLibs/flickrSearch.js [new file with mode: 0644]
js2/mwEmbed/libAddMedia/searchLibs/mediaWikiSearch.js [new file with mode: 0644]
js2/mwEmbed/libAddMedia/searchLibs/metavidSearch.js [new file with mode: 0644]
js2/mwEmbed/libAddMedia/simpleUploadForm.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/Jcrop/css/Jcrop.gif [new file with mode: 0644]
js2/mwEmbed/libClipEdit/Jcrop/css/jquery.Jcrop.css [new file with mode: 0644]
js2/mwEmbed/libClipEdit/Jcrop/js/jquery.Jcrop.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/colorpicker/css/colorpicker.css [new file with mode: 0644]
js2/mwEmbed/libClipEdit/colorpicker/css/layout.css [new file with mode: 0644]
js2/mwEmbed/libClipEdit/colorpicker/images/blank.gif [new file with mode: 0644]
js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_background.png [new file with mode: 0644]
js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_hex.png [new file with mode: 0644]
js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_hsb_b.png [new file with mode: 0644]
js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_hsb_h.png [new file with mode: 0644]
js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_hsb_s.png [new file with mode: 0644]
js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_indic.gif [new file with mode: 0644]
js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_overlay.png [new file with mode: 0644]
js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_rgb_b.png [new file with mode: 0644]
js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_rgb_g.png [new file with mode: 0644]
js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_rgb_r.png [new file with mode: 0644]
js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_select.gif [new file with mode: 0644]
js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_submit.png [new file with mode: 0644]
js2/mwEmbed/libClipEdit/colorpicker/images/custom_background.png [new file with mode: 0644]
js2/mwEmbed/libClipEdit/colorpicker/images/custom_hex.png [new file with mode: 0644]
js2/mwEmbed/libClipEdit/colorpicker/images/custom_hsb_b.png [new file with mode: 0644]
js2/mwEmbed/libClipEdit/colorpicker/images/custom_hsb_h.png [new file with mode: 0644]
js2/mwEmbed/libClipEdit/colorpicker/images/custom_hsb_s.png [new file with mode: 0644]
js2/mwEmbed/libClipEdit/colorpicker/images/custom_indic.gif [new file with mode: 0644]
js2/mwEmbed/libClipEdit/colorpicker/images/custom_rgb_b.png [new file with mode: 0644]
js2/mwEmbed/libClipEdit/colorpicker/images/custom_rgb_g.png [new file with mode: 0644]
js2/mwEmbed/libClipEdit/colorpicker/images/custom_rgb_r.png [new file with mode: 0644]
js2/mwEmbed/libClipEdit/colorpicker/images/custom_submit.png [new file with mode: 0644]
js2/mwEmbed/libClipEdit/colorpicker/images/select.png [new file with mode: 0644]
js2/mwEmbed/libClipEdit/colorpicker/images/select2.png [new file with mode: 0644]
js2/mwEmbed/libClipEdit/colorpicker/images/slider.png [new file with mode: 0644]
js2/mwEmbed/libClipEdit/colorpicker/index.html [new file with mode: 0644]
js2/mwEmbed/libClipEdit/colorpicker/js/colorpicker.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/colorpicker/js/eye.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/colorpicker/js/layout.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/colorpicker/js/utils.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/mvClipEdit.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-editor/editor.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-editor/pixastic.all.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-editor/pixastic.css [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-editor/ui.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-editor/uidata.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/actions/blend.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/actions/blur.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/actions/blurfast.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/actions/brightness.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/actions/coloradjust.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/actions/crop.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/actions/desaturate.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/actions/edges.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/actions/edges2.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/actions/emboss.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/actions/fliph.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/actions/flipv.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/actions/glow.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/actions/histogram.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/actions/hsl.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/actions/invert.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/actions/laplace.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/actions/lighten.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/actions/mosaic.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/actions/noise.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/actions/pointillize.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/actions/posterize.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/actions/removenoise.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/actions/sepia.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/actions/sharpen.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/actions/solarize.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/actions/unsharpmask.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/pixastic-editor/editor.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/pixastic-editor/pixastic.all.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/pixastic-editor/pixastic.css [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/pixastic-editor/ui.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/pixastic-editor/uidata.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/pixastic.core.js [new file with mode: 0644]
js2/mwEmbed/libClipEdit/pixastic-lib/pixastic.jquery.js [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/cortado/README [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/cortado/cortado-ovt-stripped-0.5.0.jar [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/LICENSE.txt [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/README.txt [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer-3.0.0-rc2.js [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer-3.0.0-rc2.min.js [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer-3.0.0-rc2.swf [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer-3.0.0-rc4.swf [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer-3.0.1.swf [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer.controls-3.0.0-beta5.swf [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer.controls-3.0.0-beta7.swf [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer.controls-3.0.1.swf [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer.pseudostreaming-3.0.0-beta3.swf [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/kaltura-player/README [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/kaltura-player/kdp.swf [new file with mode: 0755]
js2/mwEmbed/libEmbedVideo/binPlayers/kaltura-player/wrapper.swf [new file with mode: 0755]
js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/LICENSE.txt [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/README.txt [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/hxmdct.swf [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/omtkp.swf [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/Player.as [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/ogg/EndOfOggStreamError.as [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/ogg/LogicalOggStream.as [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/ogg/OggPacket.as [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/ogg/OggPage.as [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/ogg/UncachedUrlStream.as [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/util/BitByteArray.as [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/util/HuffmanNode.as [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/AudioPacket.as [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/CodeBook.as [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/CommentHeader.as [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/Floor.as [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/Floor0.as [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/Floor1.as [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/IdentificationHeader.as [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/Look.as [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/Mapping.as [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/Mapping0.as [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/Mdct.as [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/Mode.as [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/Residue.as [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/Residue2.as [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/SetupHeader.as [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/Util.as [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/VorbisSound.as [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/VorbisStream.as [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/haXe/build.hxml [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/haXe/org/omtk/vorbis/MdctHX.hx [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/embedVideo.js [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/flowplayerEmbed.js [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/genericEmbed.js [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/htmlEmbed.js [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/javaEmbed.js [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/kplayerEmbed.js [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/nativeEmbed.js [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/omtkEmbed.js [new file with mode: 0644]
js2/mwEmbed/libEmbedVideo/vlcEmbed.js [new file with mode: 0644]
js2/mwEmbed/libMwApi/NestedCallbackIframe.html [new file with mode: 0644]
js2/mwEmbed/libMwApi/json2.js [new file with mode: 0644]
js2/mwEmbed/libMwApi/mw.proxy.js [new file with mode: 0644]
js2/mwEmbed/libSequencer/mvFirefoggRender.js [new file with mode: 0644]
js2/mwEmbed/libSequencer/mvPlayList.js [new file with mode: 0644]
js2/mwEmbed/libSequencer/mvSequencer.js [new file with mode: 0644]
js2/mwEmbed/libSequencer/mvTimedEffectsEdit.js [new file with mode: 0644]
js2/mwEmbed/libSequencer/seqRemoteSearchDriver.js [new file with mode: 0644]
js2/mwEmbed/libTimedText/mvTextInterface.js [new file with mode: 0644]
js2/mwEmbed/libTimedText/mvTimeTextEdit.js [new file with mode: 0644]
js2/mwEmbed/mv_embed.js [new file with mode: 0644]
js2/mwEmbed/php/jsAutoloadLocalClasses.php [new file with mode: 0644]
js2/mwEmbed/php/languages/cldrConverter.php [new file with mode: 0644]
js2/mwEmbed/php/languages/mwEmbed.i18n.php [new file with mode: 0644]
js2/mwEmbed/php/maintenance/mergeJavascriptMsg.php [new file with mode: 0644]
js2/mwEmbed/php/minify/JSMin.php [new file with mode: 0644]
js2/mwEmbed/php/noMediaWikiConfig.php [new file with mode: 0644]
js2/mwEmbed/php/script-cache/README [new file with mode: 0644]
js2/mwEmbed/skins/common/remote_cp/archive_org_logo_17.png [new file with mode: 0644]
js2/mwEmbed/skins/common/remote_cp/archive_org_logo_80.png [new file with mode: 0644]
js2/mwEmbed/skins/common/remote_cp/archive_org_tab.png [new file with mode: 0644]
js2/mwEmbed/skins/common/remote_cp/combined_tab.png [new file with mode: 0644]
js2/mwEmbed/skins/common/remote_cp/flickr_tab.png [new file with mode: 0644]
js2/mwEmbed/skins/common/remote_cp/metavid_logo_17.png [new file with mode: 0644]
js2/mwEmbed/skins/common/remote_cp/metavid_tab.png [new file with mode: 0644]
js2/mwEmbed/skins/common/remote_cp/this_wiki_logo_17.png [new file with mode: 0644]
js2/mwEmbed/skins/common/remote_cp/this_wiki_tab.png [new file with mode: 0644]
js2/mwEmbed/skins/common/remote_cp/wiki_commons_logo_17.png [new file with mode: 0644]
js2/mwEmbed/skins/common/remote_cp/wiki_commons_logo_80.png [new file with mode: 0644]
js2/mwEmbed/skins/common/remote_cp/wiki_commons_tab.png [new file with mode: 0644]
js2/mwEmbed/skins/common/transition_images/fade_crossfade.png [new file with mode: 0644]
js2/mwEmbed/skins/common/transition_images/fade_fadeFromColor.png [new file with mode: 0644]
js2/mwEmbed/skins/common/transition_images/transition_wipe.png [new file with mode: 0644]
js2/mwEmbed/skins/ctrlBuilder.js [new file with mode: 0644]
js2/mwEmbed/skins/kskin/images/kaltura_open_source_video_platform.gif [new file with mode: 0644]
js2/mwEmbed/skins/kskin/images/kaltura_open_source_video_platform.png [new file with mode: 0644]
js2/mwEmbed/skins/kskin/images/ksprite.png [new file with mode: 0644]
js2/mwEmbed/skins/kskin/images/ui-bg_flat_0_aaaaaa_40x100.png [new file with mode: 0644]
js2/mwEmbed/skins/kskin/images/ui-bg_flat_75_ffffff_40x100.png [new file with mode: 0644]
js2/mwEmbed/skins/kskin/images/ui-bg_glass_55_fbf9ee_1x400.png [new file with mode: 0644]
js2/mwEmbed/skins/kskin/images/ui-bg_glass_65_ffffff_1x400.png [new file with mode: 0644]
js2/mwEmbed/skins/kskin/images/ui-bg_glass_75_dadada_1x400.png [new file with mode: 0644]
js2/mwEmbed/skins/kskin/images/ui-bg_glass_75_e6e6e6_1x400.png [new file with mode: 0644]
js2/mwEmbed/skins/kskin/images/ui-bg_glass_95_fef1ec_1x400.png [new file with mode: 0644]
js2/mwEmbed/skins/kskin/images/ui-bg_highlight-soft_75_cccccc_1x100.png [new file with mode: 0644]
js2/mwEmbed/skins/kskin/images/ui-icons_222222_256x240.png [new file with mode: 0644]
js2/mwEmbed/skins/kskin/images/ui-icons_2e83ff_256x240.png [new file with mode: 0644]
js2/mwEmbed/skins/kskin/images/ui-icons_454545_256x240.png [new file with mode: 0644]
js2/mwEmbed/skins/kskin/images/ui-icons_888888_256x240.png [new file with mode: 0644]
js2/mwEmbed/skins/kskin/images/ui-icons_cd0a0a_256x240.png [new file with mode: 0644]
js2/mwEmbed/skins/kskin/kskin.js [new file with mode: 0644]
js2/mwEmbed/skins/kskin/playerSkin.css [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/Button_add_media.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/Jcrop.gif [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/archive_org_bw.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/archive_org_color.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/box_layout_icon.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/box_layout_icon_dark.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/button_grey_left.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/button_grey_right.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/button_play.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/button_subscribe.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/button_to_clipboard.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/carousel_left.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/carousel_right.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/carousel_top_left.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/carousel_top_right.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/clip_thumb_overlay.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/embed_arrow.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/firefogg_logo.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/fish_xiph_org_bw.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/fish_xiph_org_color.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/flash_carousel.jpg [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/flash_icon_bw.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/flash_icon_color.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/flash_player.jpg [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/font_truetype.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/html_page_icon.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/ico_mail.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/ico_rss.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/image_layout_left.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/image_layout_right.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/image_thumb_overlay.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/img1.jpg [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/img2.jpg [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/kaltura_logo_sm.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/kaltura_open_source_video_platform.gif [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/kaltura_open_source_video_platform.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/ksprite.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/list_layout_icon.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/list_layout_icon_dark.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/loading_ani.gif [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/loading_bar_ani.gif [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/logo.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/logo2.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/metavid_logo_100.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/opened.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/other_results_bg.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/other_results_top.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/other_results_top2.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/pbar-ani.gif [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/pelosi.jpg [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/person1.jpg [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/player_big_play_button.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/player_bottom_left.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/player_bottom_right.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/player_button_cc.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/player_button_fullscreen.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/player_button_options.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/player_button_pause.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/player_button_play.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/player_options_bg.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/player_options_bottom.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/player_options_top.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/player_seek_bg_loaded.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/player_seek_bg_normal.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/player_seek_left.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/player_seek_right.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/player_slider.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/player_video.jpg [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/player_video_options_bg.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/player_volume_seek.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/player_volume_tag.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/player_volume_tag_off.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/plugin.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/plugin_disabled.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/plugin_edit.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/search_suggest_bg.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/search_suggest_bottom.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/search_suggest_top.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/selector.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/slider_handle.gif [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/slider_handle_green.gif [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/slider_handle_red.gif [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/sound_music_icon-60.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/sound_music_icon-80.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/sound_music_icon.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/stock-text-layer-24.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/stock-text-layer-24_over.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/stock-tool-button-crop.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/stock-tool-button-crop_over.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/stock-tool-button-scale.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/stock-tool-button-scale_over.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/stock_icon_over.xcf [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/tab-bg.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/thumb1.jpg [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/thumb2.jpg [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/thumb3.jpg [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/thumb4.jpg [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/tracker.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/transition_icon.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/transparent_bg.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/ui-bg_diagonals-thick_20_666666_40x40.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/ui-bg_flat_0_aaaaaa_40x100.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/ui-bg_flat_75_ffffff_40x100.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/ui-bg_glass_55_fbf9ee_1x400.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/ui-bg_glass_65_ffffff_1x400.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/ui-bg_glass_75_dadada_1x400.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/ui-bg_glass_75_e6e6e6_1x400.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/ui-bg_glass_95_fef1ec_1x400.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/ui-bg_highlight-soft_75_cccccc_1x100.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/ui-icons_222222_256x240.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/ui-icons_2e83ff_256x240.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/ui-icons_454545_256x240.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/ui-icons_888888_256x240.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/ui-icons_cd0a0a_256x240.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/uni_edit_bw.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/uni_edit_color.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/vid_default_thumb.jpg [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/vid_next_sm.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/vid_prev_sm.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/images/wiki_commons_logo_80.png [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/mv_sequence.css [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/mvpcf.js [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/playerSkin.css [new file with mode: 0644]
js2/mwEmbed/skins/mvpcf/styles.css [new file with mode: 0644]
js2/mwEmbed/tests/README [new file with mode: 0644]
js2/mwEmbed/tests/testApiProxy.html [new file with mode: 0644]
js2/mwEmbed/tests/testLang.html [new file with mode: 0644]
js2/mwEmbed/tests/testLang.js [new file with mode: 0644]
js2/remoteMwEmbed.js [new file with mode: 0644]
js2/uploadPage.js [new file with mode: 0644]

diff --git a/js2/README b/js2/README
new file mode 100644 (file)
index 0000000..d82b80f
--- /dev/null
@@ -0,0 +1,4 @@
+MediaWiki Javascript phase 2
+
+See Documentation on wiki: 
+http://www.mediawiki.org/wiki/JS2_Overview
\ No newline at end of file
diff --git a/js2/ajaxcategories.js b/js2/ajaxcategories.js
new file mode 100644 (file)
index 0000000..b46d8b3
--- /dev/null
@@ -0,0 +1,326 @@
+loadGM( {
+       "ajax-add-category" : "[Add Category]",
+       "ajax-add-category-submit" : "[Add]",
+       "ajax-confirm-prompt" : "[Confirmation Text]",
+       "ajax-confirm-title" : "[Confirmation Title]",
+       "ajax-confirm-save" : "[Save]",
+       "ajax-add-category-summary" : "[Add category $1]",
+       "ajax-remove-category-summary" : "[Remove category $2]",
+       "ajax-confirm-actionsummary" : "[Summary]",
+       "ajax-error-title" : "Error",
+       "ajax-error-dismiss" : "OK",
+       "ajax-remove-category-error" : "[RemoveErr]"
+} );
+
+var ajaxCategories = {
+       handleAddLink : function( e ) {
+               e.preventDefault();
+
+               // Make sure the suggestion plugin is loaded. Load everything else while we're at it
+               mvJsLoader.doLoad(
+                       ['$j.ui', '$j.ui.dialog', '$j.fn.suggestions'],
+                       function() {
+                               $j( '#mw-addcategory-prompt' ).toggle();
+
+                               $j( '#mw-addcategory-input' ).suggestions( {
+                                       'fetch':ajaxCategories.fetchSuggestions,
+                                       'cancel': function() {
+                                               var req = ajaxCategories.request;
+                                               if ( req.abort )
+                                                       req.abort();
+                                       }
+                               } );
+
+                               $j( '#mw-addcategory-input' ).suggestions();
+                       }
+               );
+       },
+
+       fetchSuggestions : function( query ) {
+               var that = this;
+               var request = $j.ajax( {
+                       url: wgScriptPath + '/api.php',
+                       data: {
+                               'action': 'query',
+                               'list': 'allpages',
+                               'apnamespace': 14,
+                               'apprefix': $j( this ).val(),
+                               'format': 'json'
+                       },
+                       dataType: 'json',
+                       success: function( data ) {
+                               // Process data.query.allpages into an array of titles
+                               var pages = data.query.allpages;
+                               var titleArr = [];
+
+                               $j.each( pages, function( i, page ) {
+                                       var title = page.title.split( ':', 2 )[1];
+                                       titleArr.push( title );
+                               } );
+
+                               $j( that ).suggestions( 'suggestions', titleArr );
+                       }
+               } );
+
+               ajaxCategories.request = request;
+       },
+
+       reloadCategoryList : function( response ) {
+               var holder = $j( '<div/>' );
+
+               holder.load(
+                       window.location.href + ' .catlinks',
+                       function() {
+                               $j( '.catlinks' ).replaceWith( holder.find( '.catlinks' ) );
+                               ajaxCategories.setupAJAXCategories();
+                               ajaxCategories.removeProgressIndicator( $j( '.catlinks' ) );
+                       }
+               );
+       },
+
+       confirmEdit : function( page, fn, actionSummary, doneFn ) {
+               // Load jQuery UI
+               mvJsLoader.doLoad(
+                       ['$j.ui', '$j.ui.dialog', '$j.fn.suggestions'],
+                       function() {
+                               // Produce a confirmation dialog
+
+                               var dialog = $j( '<div/>' );
+
+                               dialog.addClass( 'mw-ajax-confirm-dialog' );
+                               dialog.attr( 'title', gM( 'ajax-confirm-title' ) );
+
+                               // Intro text.
+                               var confirmIntro = $j( '<p/>' );
+                               confirmIntro.text( gM( 'ajax-confirm-prompt' ) );
+                               dialog.append( confirmIntro );
+
+                               // Summary of the action to be taken
+                               var summaryHolder = $j( '<p/>' );
+                               var summaryLabel = $j( '<strong/>' );
+                               summaryLabel.text( gM( 'ajax-confirm-actionsummary' ) + " " );
+                               summaryHolder.text( actionSummary );
+                               summaryHolder.prepend( summaryLabel );
+                               dialog.append( summaryHolder );
+
+                               // Reason textbox.
+                               var reasonBox = $j( '<input type="text" size="45" />' );
+                               reasonBox.addClass( 'mw-ajax-confirm-reason' );
+                               dialog.append( reasonBox );
+
+                               // Submit button
+                               var submitButton = $j( '<input type="button"/>' );
+                               submitButton.val( gM( 'ajax-confirm-save' ) );
+
+                               var submitFunction = function() {
+                                       ajaxCategories.addProgressIndicator( dialog );
+                                       ajaxCategories.doEdit(
+                                               page,
+                                               fn,
+                                               reasonBox.val(),
+                                               function() {
+                                                       doneFn();
+                                                       dialog.dialog( 'close' );
+                                                       ajaxCategories.removeProgressIndicator( dialog );
+                                               }
+                                       );
+                               };
+
+                               var buttons = { };
+                               buttons[gM( 'ajax-confirm-save' )] = submitFunction;
+                               var dialogOptions = {
+                                       'AutoOpen' : true,
+                                       'buttons' : buttons,
+                                       'width' : 450
+                               };
+
+                               $j( '#catlinks' ).prepend( dialog );
+                               dialog.dialog( dialogOptions );
+                       }
+               );
+       },
+
+       doEdit : function( page, fn, summary, doneFn ) {
+               // Get an edit token for the page.
+               var getTokenVars = {
+                       'action':'query',
+                       'prop':'info|revisions',
+                       'intoken':'edit',
+                       'titles':page,
+                       'rvprop':'content|timestamp',
+                       'format':'json'
+               };
+
+               $j.get( wgScriptPath + '/api.php', getTokenVars,
+                       function( reply ) {
+                               var infos = reply.query.pages;
+                               $j.each(
+                                       infos,
+                                       function( pageid, data ) {
+                                               var token = data.edittoken;
+                                               var timestamp = data.revisions[0].timestamp;
+                                               var oldText = data.revisions[0]['*'];
+
+                                               var newText = fn( oldText );
+
+                                               if ( newText === false ) return;
+
+                                               var postEditVars = {
+                                                       'action':'edit',
+                                                       'title':page,
+                                                       'text':newText,
+                                                       'summary':summary,
+                                                       'token':token,
+                                                       'basetimestamp':timestamp,
+                                                       'format':'json'
+                                               };
+
+                                               $j.post( wgScriptPath + '/api.php', postEditVars, doneFn,       'json' );
+                                       }
+                               );
+                       }
+               , 'json' );
+       },
+
+       addProgressIndicator : function( elem ) {
+               var indicator = $j( '<div/>' );
+
+               indicator.addClass( 'mw-ajax-loader' );
+
+               elem.append( indicator );
+       },
+
+       removeProgressIndicator : function( elem ) {
+               elem.find( '.mw-ajax-loader' ).remove();
+       },
+
+       handleCategoryAdd : function( e ) {
+               // Grab category text
+               var category = $j( '#mw-addcategory-input' ).val();
+               var appendText = "\n[[" + wgFormattedNamespaces[14] + ":" + category + "]]\n";
+               var summary = gM( 'ajax-add-category-summary', category );
+
+               ajaxCategories.confirmEdit(
+                       wgPageName,
+                       function( oldText ) { return oldText + appendText },
+                       summary,
+                       ajaxCategories.reloadCategoryList
+               );
+       },
+
+       handleDeleteLink : function( e ) {
+               e.preventDefault();
+
+               var category = $j( this ).parent().find( 'a' ).text();
+
+               // Build a regex that matches legal invocations of that category.
+
+               // In theory I should escape the aliases, but there's no JS function for it
+               //  Shouldn't have any real impact, can't be exploited or anything, so we'll
+               //  leave it for now.
+               var categoryNSFragment = '';
+               $j.each( wgNamespaceIds, function( name, id ) {
+                       if ( id == 14 ) {
+                               // Allow the first character to be any case
+                               var firstChar = name.charAt( 0 );
+                               firstChar = '[' + firstChar.toUpperCase() + firstChar.toLowerCase() + ']';
+                               categoryNSFragment += '|' + firstChar + name.substr( 1 );
+                       }
+               } );
+               categoryNSFragment = categoryNSFragment.substr( 1 ); // Remove leading |
+
+               // Build the regex
+               var titleFragment = category;
+
+               firstChar = category.charAt( 0 );
+               firstChar = '[' + firstChar.toUpperCase() + firstChar.toLowerCase() + ']';
+               titleFragment = firstChar + category.substr( 1 );
+               var categoryRegex = '\\[\\[' + categoryNSFragment + ':' + titleFragment + '(\\|[^\\]]*)?\\]\\]';
+               categoryRegex = new RegExp( categoryRegex, 'g' );
+
+               var summary = gM( 'ajax-remove-category-summary', category );
+
+               ajaxCategories.confirmEdit(
+                       wgPageName,
+                       function( oldText ) {
+                               var newText = oldText.replace( categoryRegex, '' );
+
+                               if ( newText == oldText ) {
+                                       var error = gM( 'ajax-remove-category-error' );
+                                       ajaxCategories.showError( error );
+                                       ajaxCategories.removeProgressIndicator( $j( '.mw-ajax-confirm-dialog' ) );
+                                       $j( '.mw-ajax-confirm-dialog' ).dialog( 'close' );
+                                       return false;
+                               }
+
+                               return newText;
+                       },
+                       summary, ajaxCategories.reloadCategoryList
+               );
+       },
+
+       showError : function( str ) {
+               var dialog = $j( '<div/>' );
+               dialog.text( str );
+
+               $j( '#bodyContent' ).append( dialog );
+
+               var buttons = { };
+               buttons[gM( 'ajax-error-dismiss' )] = function( e ) {
+                       dialog.dialog( 'close' );
+               };
+               var dialogOptions = {
+                       'buttons' : buttons,
+                       'AutoOpen' : true,
+                       'title' : gM( 'ajax-error-title' )
+               };
+
+               dialog.dialog( dialogOptions );
+       },
+
+       setupAJAXCategories : function() {
+               // Only do it for articles.
+               if ( !wgIsArticle ) return;
+
+               var clElement = $j( '.catlinks' );
+
+               // Unhide hidden category holders.
+               clElement.removeClass( 'catlinks-allhidden' );
+
+               var addLink = $j( '<a/>' );
+               addLink.addClass( 'mw-ajax-addcategory' );
+
+               // Create [Add Category] link
+               addLink.text( gM( 'ajax-add-category' ) );
+               addLink.attr( 'href', '#' );
+               addLink.click( ajaxCategories.handleAddLink );
+               clElement.append( addLink );
+
+               // Create add category prompt
+               var promptContainer = $j( '<div id="mw-addcategory-prompt"/>' );
+               var promptTextbox = $j( '<input type="text" size="45" id="mw-addcategory-input"/>' );
+               var addButton = $j( '<input type="button" id="mw-addcategory-button"/>' );
+               addButton.val( gM( 'ajax-add-category-submit' ) );
+
+               promptTextbox.keypress( ajaxCategories.handleCategoryInput );
+               addButton.click( ajaxCategories.handleCategoryAdd );
+
+               promptContainer.append( promptTextbox );
+               promptContainer.append( addButton );
+               promptContainer.hide();
+
+               // Create delete link for each category.
+               $j( '.catlinks div span a' ).each( function( e ) {
+                       // Create a remove link
+                       var deleteLink = $j( '<a class="mw-remove-category" href="#"/>' );
+
+                       deleteLink.click( ajaxCategories.handleDeleteLink );
+
+                       $j( this ).after( deleteLink );
+               } );
+
+               clElement.append( promptContainer );
+       }
+};
+
+js2AddOnloadHook( ajaxCategories.setupAJAXCategories );
diff --git a/js2/apiProxyPage.js b/js2/apiProxyPage.js
new file mode 100644 (file)
index 0000000..f113a5d
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+* mwProxy js2 page system.
+*
+* Invokes the apiProxy system 
+*/
+
+/*
+ * Since this is proxy server set a pre-append debug flag to know which debug msgs are coming from where
+ */
+mw.conf['debug_pre'] = 'Proxy';
+if ( !mwApiProxyConfig )
+       var mwApiProxyConfig = { };
+
+// The default mwApiProxyConfig config 
+// (presently hard coded but should read from user and site config)  
+var mwApiProxyDefaultConfig = {
+               'master_whitelist'      : [  'en.wikipedia.org', 'localhost', '127.1.1.100' ],
+               'master_blacklist'      : []
+};
+
+// User white_list should also be checked and configured at runtime.
+js2AddOnloadHook( function() {
+       // build our configuration from the default and mwApiProxyConfig vars
+       mwApiProxyConfig = $j.extend( true, mwApiProxyDefaultConfig,  mwApiProxyConfig );
+       $j.apiProxy( 'server', mwApiProxyConfig );
+} );
diff --git a/js2/editPage.js b/js2/editPage.js
new file mode 100644 (file)
index 0000000..15c47f9
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * JS2-style replacement for MediaWiki edit.js
+ * (right now it just supports the toolbar)
+ */
+
+// Setup configuration vars (if not set already)
+if ( !mwAddMediaConfig )
+       var mwAddMediaConfig = { };
+
+// The default editPage AMW config
+var defaultAddMediaConfig = {
+               'profile': 'mediawiki_edit',
+               'target_textbox': '#wpTextbox1',
+               // Note: selections in the textbox will take over the default query
+               'default_query': wgTitle,
+               'target_title': wgPageName,
+               // Here we can setup the content provider overrides
+               'enabled_cps':['wiki_commons'],
+               // The local wiki API URL:
+               'local_wiki_api_url': wgServer + wgScriptPath + '/api.php'
+};
+
+js2AddOnloadHook( function() {
+       js_log( "edit page js2AddOnloadHook::" );
+       var amwConf = $j.extend( true, defaultAddMediaConfig, mwAddMediaConfig );
+       // kind of tricky, it would be nice to use run on ready "loader" call here
+       var didWikiEditorBind = false;
+       
+       // Set-up the drag drop binding (will only work for html5 upload browsers) 
+       // $j('textarea#wpTextbox1').dragFileUpload();
+
+       // set up the add-media-wizard binding: 
+       if ( typeof $j.wikiEditor != 'undefined' ) {
+                       // the below seems to be broken :(
+                       $j( 'textarea#wpTextbox1' ).bind( 'wikiEditor-toolbar-buildSection-main',
+                   function( e, section ) {
+                       didWikiEditorBind = true;
+                       if ( typeof section.groups.insert.tools.file !== 'undefined' ) {
+                           section.groups.insert.tools.file.action = {
+                               'type': 'callback',
+                               'execute': function() {
+                                       js_log( 'click add media wiz' );
+                                       $j.addMediaWiz( amwConf );
+                               }
+                           };
+                       }
+                   }
+               );
+       }
+       // Add to old toolbar if wikiEditor did not remove '#toolbar' from the page:    
+       setTimeout( function() {
+               if ( $j( '#btn-add-media-wiz' ).length == 0 && $j( '#toolbar' ).length != 0 ) {
+                       js_log( 'Do old toolbar bind:' );
+                       didWikiEditorBind = true;
+                       $j( '#toolbar' ).append( '<img style="cursor:pointer" id="btn-add-media-wiz" src="' +
+                               mv_skin_img_path + 'Button_add_media.png">' );
+                       $j( '#btn-add-media-wiz' ).addMediaWiz(
+                               amwConf
+                       );
+               } else {
+                       // Make sure the wikieditor got binded: 
+                       if ( !didWikiEditorBind ) {
+                               js_log( 'Failed to bind via build section bind via target:' );
+                               $j( ".tool[rel='file']" ).unbind().addMediaWiz( amwConf );
+                       }
+               }
+       }, 120 )
+
+} );
diff --git a/js2/js2stopgap.js b/js2/js2stopgap.js
new file mode 100644 (file)
index 0000000..801be99
--- /dev/null
@@ -0,0 +1,9509 @@
+/*!
+ * jQuery JavaScript Library v1.3.2
+ * http://jquery.com/
+ *
+ * Copyright (c) 2009 John Resig
+ * Dual licensed under the MIT and GPL licenses.
+ * http://docs.jquery.com/License
+ *
+ * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
+ * Revision: 6246
+ */
+( function() {
+
+var
+       // Will speed up references to window, and allows munging its name.
+       window = this,
+       // Will speed up references to undefined, and allows munging its name.
+       undefined,
+       // Map over jQuery in case of overwrite
+       _jQuery = window.jQuery,
+       // Map over the $ in case of overwrite
+       _$ = window.$,
+
+       jQuery = window.jQuery = window.$ = function( selector, context ) {
+               // The jQuery object is actually just the init constructor 'enhanced'
+               return new jQuery.fn.init( selector, context );
+       },
+
+       // A simple way to check for HTML strings or ID strings
+       // (both of which we optimize for)
+       quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,
+       // Is it a simple selector
+       isSimple = / ^ .[ ^ :# \[\.,]*$/;
+
+jQuery.fn = jQuery.prototype = {
+       init: function( selector, context ) {
+               // Make sure that a selection was provided
+               selector = selector || document;
+
+               // Handle $(DOMElement)
+               if ( selector.nodeType ) {
+                       this[0] = selector;
+                       this.length = 1;
+                       this.context = selector;
+                       return this;
+               }
+               // Handle HTML strings
+               if ( typeof selector === "string" ) {
+                       // Are we dealing with HTML string or an ID?
+                       var match = quickExpr.exec( selector );
+
+                       // Verify a match, and that no context was specified for #id
+                       if ( match && ( match[1] || !context ) ) {
+
+                               // HANDLE: $(html) -> $(array)
+                               if ( match[1] )
+                                       selector = jQuery.clean( [ match[1] ], context );
+
+                               // HANDLE: $("#id")
+                               else {
+                                       var elem = document.getElementById( match[3] );
+
+                                       // Handle the case where IE and Opera return items
+                                       // by name instead of ID
+                                       if ( elem && elem.id != match[3] )
+                                               return jQuery().find( selector );
+
+                                       // Otherwise, we inject the element directly into the jQuery object
+                                       var ret = jQuery( elem || [] );
+                                       ret.context = document;
+                                       ret.selector = selector;
+                                       return ret;
+                               }
+
+                       // HANDLE: $(expr, [context])
+                       // (which is just equivalent to: $(content).find(expr)
+                       } else
+                               return jQuery( context ).find( selector );
+
+               // HANDLE: $(function)
+               // Shortcut for document ready
+               } else if ( jQuery.isFunction( selector ) )
+                       return jQuery( document ).ready( selector );
+
+               // Make sure that old selector state is passed along
+               if ( selector.selector && selector.context ) {
+                       this.selector = selector.selector;
+                       this.context = selector.context;
+               }
+
+               return this.setArray( jQuery.isArray( selector ) ?
+                       selector :
+                       jQuery.makeArray( selector ) );
+       },
+
+       // Start with an empty selector
+       selector: "",
+
+       // The current version of jQuery being used
+       jquery: "1.3.2",
+
+       // The number of elements contained in the matched element set
+       size: function() {
+               return this.length;
+       },
+
+       // 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 === undefined ?
+
+                       // Return a 'clean' array
+                       Array.prototype.slice.call( this ) :
+
+                       // Return just the object
+                       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( 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;
+       },
+
+       // Force the current matched set of elements to become
+       // the specified array of elements (destroying the stack in the process)
+       // You should use pushStack() in order to do this, but maintain the stack
+       setArray: function( elems ) {
+               // Resetting the length to 0, then using the native Array push
+               // is a super-fast way to populate an object with array-like properties
+               this.length = 0;
+               Array.prototype.push.apply( this, elems );
+
+               return this;
+       },
+
+       // 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 );
+       },
+
+       // Determine the position of an element within
+       // the matched set of elements
+       index: function( elem ) {
+               // Locate the position of the desired element
+               return jQuery.inArray(
+                       // If it receives a jQuery object, the first element is used
+                       elem && elem.jquery ? elem[0] : elem
+               , this );
+       },
+
+       attr: function( name, value, type ) {
+               var options = name;
+
+               // Look for the case where we're accessing a style value
+               if ( typeof name === "string" )
+                       if ( value === undefined )
+                               return this[0] && jQuery[ type || "attr" ]( this[0], name );
+
+                       else {
+                               options = { };
+                               options[ name ] = value;
+                       }
+
+               // Check to see if we're setting style values
+               return this.each( function( i ) {
+                       // Set all the styles
+                       for ( name in options )
+                               jQuery.attr(
+                                       type ?
+                                               this.style :
+                                               this,
+                                       name, jQuery.prop( this, options[ name ], type, i, name )
+                               );
+               } );
+       },
+
+       css: function( key, value ) {
+               // ignore negative width and height values
+               if ( ( key == 'width' || key == 'height' ) && parseFloat( value ) < 0 )
+                       value = undefined;
+               return this.attr( key, value, "curCSS" );
+       },
+
+       text: function( text ) {
+               if ( typeof text !== "object" && text != null )
+                       return this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( text ) );
+
+               var ret = "";
+
+               jQuery.each( text || this, function() {
+                       jQuery.each( this.childNodes, function() {
+                               if ( this.nodeType != 8 )
+                                       ret += this.nodeType != 1 ?
+                                               this.nodeValue :
+                                               jQuery.fn.text( [ this ] );
+                       } );
+               } );
+
+               return ret;
+       },
+
+       wrapAll: function( html ) {
+               if ( this[0] ) {
+                       // The elements to wrap the target around
+                       var wrap = jQuery( html, this[0].ownerDocument ). clone ();
+
+                       if ( this[0].parentNode )
+                               wrap.insertBefore( this[0] );
+
+                       wrap.map( function() {
+                               var elem = this;
+
+                               while ( elem.firstChild )
+                                       elem = elem.firstChild;
+
+                               return elem;
+                       } ).append( this );
+               }
+
+               return this;
+       },
+
+       wrapInner: function( html ) {
+               return this.each( function() {
+                       jQuery( this ).contents().wrapAll( html );
+               } );
+       },
+
+       wrap: function( html ) {
+               return this.each( function() {
+                       jQuery( this ).wrapAll( html );
+               } );
+       },
+
+       append: function() {
+               return this.domManip( arguments, true, function( elem ) {
+                       if ( this.nodeType == 1 )
+                               this.appendChild( elem );
+               } );
+       },
+
+       prepend: function() {
+               return this.domManip( arguments, true, function( elem ) {
+                       if ( this.nodeType == 1 )
+                               this.insertBefore( elem, this.firstChild );
+               } );
+       },
+
+       before: function() {
+               return this.domManip( arguments, false, function( elem ) {
+                       this.parentNode.insertBefore( elem, this );
+               } );
+       },
+
+       after: function() {
+               return this.domManip( arguments, false, function( elem ) {
+                       this.parentNode.insertBefore( elem, this.nextSibling );
+               } );
+       },
+
+       end: function() {
+               return this.prevObject || jQuery( [] );
+       },
+
+       // For internal use only.
+       // Behaves like an Array's method, not like a jQuery method.
+       push: [].push,
+       sort: [].sort,
+       splice: [].splice,
+
+       find: function( selector ) {
+               if ( this.length === 1 ) {
+                       var ret = this.pushStack( [], "find", selector );
+                       ret.length = 0;
+                       jQuery.find( selector, this[0], ret );
+                       return ret;
+               } else {
+                       return this.pushStack( jQuery.unique( jQuery.map( this, function( elem ) {
+                               return jQuery.find( selector, elem );
+                       } ) ), "find", selector );
+               }
+       },
+
+       clone : function( events ) {
+               // Do the clone
+               var ret = this.map( function() {
+                       if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc( this ) ) {
+                               // IE copies events bound via attachEvent when
+                               // using cloneNode. Calling detachEvent on the
+                               // clone will also remove the events from the orignal
+                               // In order to get around this, we use innerHTML.
+                               // Unfortunately, this means some modifications to
+                               // attributes in IE that are actually only stored
+                               // as properties will not be copied (such as the
+                               // the name attribute on an input).
+                               var html = this.outerHTML;
+                               if ( !html ) {
+                                       var div = this.ownerDocument.createElement( "div" );
+                                       div.appendChild( this.cloneNode( true ) );
+                                       html = div.innerHTML;
+                               }
+
+                               return jQuery.clean( [ html.replace( / jQuery\d+="(?:\d+|null)"/g, "" ).replace( /^\s*/, "" ) ] )[0];
+                       } else
+                               return this.cloneNode( true );
+               } );
+
+               // Copy the events from the original to the clone
+               if ( events === true ) {
+                       var orig = this.find( "*" ).andSelf(), i = 0;
+
+                       ret.find( "*" ).andSelf().each( function() {
+                               if ( this.nodeName !== orig[i].nodeName )
+                                       return;
+
+                               var events = jQuery.data( orig[i], "events" );
+
+                               for ( var type in events ) {
+                                       for ( var handler in events[ type ] ) {
+                                               jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
+                                       }
+                               }
+
+                               i++;
+                       } );
+               }
+
+               // Return the cloned set
+               return ret;
+       },
+
+       filter: function( selector ) {
+               return this.pushStack(
+                       jQuery.isFunction( selector ) &&
+                       jQuery.grep( this, function( elem, i ) {
+                               return selector.call( elem, i );
+                       } ) ||
+
+                       jQuery.multiFilter( selector, jQuery.grep( this, function( elem ) {
+                               return elem.nodeType === 1;
+                       } ) ), "filter", selector );
+       },
+
+       closest: function( selector ) {
+               var pos = jQuery.expr.match.POS.test( selector ) ? jQuery( selector ) : null,
+                       closer = 0;
+
+               return this.map( function() {
+                       var cur = this;
+                       while ( cur && cur.ownerDocument ) {
+                               if ( pos ? pos.index( cur ) > - 1 : jQuery( cur ).is( selector ) ) {
+                                       jQuery.data( cur, "closest", closer );
+                                       return cur;
+                               }
+                               cur = cur.parentNode;
+                               closer++;
+                       }
+               } );
+       },
+
+       not: function( selector ) {
+               if ( typeof selector === "string" )
+                       // test special case where just one selector is passed in
+                       if ( isSimple.test( selector ) )
+                               return this.pushStack( jQuery.multiFilter( selector, this, true ), "not", selector );
+                       else
+                               selector = jQuery.multiFilter( selector, this );
+
+               var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
+               return this.filter( function() {
+                       return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
+               } );
+       },
+
+       add: function( selector ) {
+               return this.pushStack( jQuery.unique( jQuery.merge(
+                       this.get(),
+                       typeof selector === "string" ?
+                               jQuery( selector ) :
+                               jQuery.makeArray( selector )
+               ) ) );
+       },
+
+       is: function( selector ) {
+               return !!selector && jQuery.multiFilter( selector, this ).length > 0;
+       },
+
+       hasClass: function( selector ) {
+               return !!selector && this.is( "." + selector );
+       },
+
+       val: function( value ) {
+               if ( value === undefined ) {
+                       var elem = this[0];
+
+                       if ( elem ) {
+                               if ( jQuery.nodeName( elem, 'option' ) )
+                                       return ( elem.attributes.value || { } ).specified ? elem.value : elem.text;
+                               
+                               // We need to handle select boxes special
+                               if ( jQuery.nodeName( elem, "select" ) ) {
+                                       var index = elem.selectedIndex,
+                                               values = [],
+                                               options = elem.options,
+                                               one = elem.type == "select-one";
+
+                                       // Nothing was selected
+                                       if ( index < 0 )
+                                               return null;
+
+                                       // Loop through all the selected options
+                                       for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
+                                               var option = options[ i ];
+
+                                               if ( option.selected ) {
+                                                       // Get the specifc 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;
+                               }
+
+                               // Everything else, we just grab the value
+                               return ( elem.value || "" ).replace( /\r/g, "" );
+
+                       }
+
+                       return undefined;
+               }
+
+               if ( typeof value === "number" )
+                       value += '';
+
+               return this.each( function() {
+                       if ( this.nodeType != 1 )
+                               return;
+
+                       if ( jQuery.isArray( value ) && / radio | checkbox / .test( this.type ) )
+                               this.checked = ( jQuery.inArray( this.value, value ) >= 0 ||
+                                       jQuery.inArray( this.name, value ) >= 0 );
+
+                       else if ( jQuery.nodeName( this, "select" ) ) {
+                               var values = jQuery.makeArray( value );
+
+                               jQuery( "option", this ).each( function() {
+                                       this.selected = ( jQuery.inArray( this.value, values ) >= 0 ||
+                                               jQuery.inArray( this.text, values ) >= 0 );
+                               } );
+
+                               if ( !values.length )
+                                       this.selectedIndex = - 1;
+
+                       } else
+                               this.value = value;
+               } );
+       },
+
+       html: function( value ) {
+               return value === undefined ?
+                       ( this[0] ?
+                               this[0].innerHTML.replace( / jQuery\d+="(?:\d+|null)"/g, "" ) :
+                               null ) :
+                       this.empty().append( value );
+       },
+
+       replaceWith: function( value ) {
+               return this.after( value ).remove();
+       },
+
+       eq: function( i ) {
+               return this.slice( i, + i + 1 );
+       },
+
+       slice: function() {
+               return this.pushStack( Array.prototype.slice.apply( this, arguments ),
+                       "slice", Array.prototype.slice.call( arguments ).join( "," ) );
+       },
+
+       map: function( callback ) {
+               return this.pushStack( jQuery.map( this, function( elem, i ) {
+                       return callback.call( elem, i, elem );
+               } ) );
+       },
+
+       andSelf: function() {
+               return this.add( this.prevObject );
+       },
+
+       domManip: function( args, table, callback ) {
+               if ( this[0] ) {
+                       var fragment = ( this[0].ownerDocument || this[0] ).createDocumentFragment(),
+                               scripts = jQuery.clean( args, ( this[0].ownerDocument || this[0] ), fragment ),
+                               first = fragment.firstChild;
+
+                       if ( first )
+                               for ( var i = 0, l = this.length; i < l; i++ )
+                                       callback.call( root( this[i], first ), this.length > 1 || i > 0 ?
+                                                       fragment.cloneNode( true ) : fragment );
+               
+                       if ( scripts )
+                               jQuery.each( scripts, evalScript );
+               }
+
+               return this;
+               
+               function root( elem, cur ) {
+                       return table && jQuery.nodeName( elem, "table" ) && jQuery.nodeName( cur, "tr" ) ?
+                               ( elem.getElementsByTagName( "tbody" )[0] ||
+                               elem.appendChild( elem.ownerDocument.createElement( "tbody" ) ) ) :
+                               elem;
+               }
+       }
+};
+
+// Give the init function the jQuery prototype for later instantiation
+jQuery.fn.init.prototype = jQuery.fn;
+
+function evalScript( i, elem ) {
+       if ( elem.src )
+               jQuery.ajax( {
+                       url: elem.src,
+                       async: false,
+                       dataType: "script"
+               } );
+
+       else
+               jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
+
+       if ( elem.parentNode )
+               elem.parentNode.removeChild( elem );
+}
+
+function now() {
+       return + new Date;
+}
+
+jQuery.extend = jQuery.fn.extend = function() {
+       // copy reference to target object
+       var target = arguments[0] || { }, i = 1, length = arguments.length, deep = false, options;
+
+       // 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 ( var name in options ) {
+                               var src = target[ name ], copy = options[ name ];
+
+                               // Prevent never-ending loop
+                               if ( target === copy )
+                                       continue;
+
+                               // Recurse if we're merging object values
+                               if ( deep && copy && typeof copy === "object" && !copy.nodeType )
+                                       target[ name ] = jQuery.extend( deep,
+                                               // Never move original objects, clone them
+                                               src || ( copy.length != null ? [ ] : { } )
+                                       , copy );
+
+                               // Don't bring in undefined values
+                               else if ( copy !== undefined )
+                                       target[ name ] = copy;
+
+                       }
+
+       // Return the modified object
+       return target;
+};
+
+// exclude the following css properties to add px
+var exclude = / z - ? index | font - ? weight | opacity | zoom | line - ? height /i,
+       // cache defaultView
+       defaultView = document.defaultView || { },
+       toString = Object.prototype.toString;
+
+jQuery.extend( {
+       noConflict: function( deep ) {
+               window.$ = _$;
+
+               if ( deep )
+                       window.jQuery = _jQuery;
+
+               return jQuery;
+       },
+
+       // 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 toString.call( obj ) === "[object Function]";
+       },
+
+       isArray: function( obj ) {
+               return toString.call( obj ) === "[object Array]";
+       },
+
+       // check if an element is in a (or is an) XML document
+       isXMLDoc: function( elem ) {
+               return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
+                       !!elem.ownerDocument && jQuery.isXMLDoc( elem.ownerDocument );
+       },
+
+       // Evalulates a script in a global context
+       globalEval: function( data ) {
+               if ( data && /\S/.test( data ) ) {
+                       // Inspired by code by Andrea Giammarchi
+                       // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
+                       var head = document.getElementsByTagName( "head" )[0] || document.documentElement,
+                               script = document.createElement( "script" );
+
+                       script.type = "text/javascript";
+                       if ( jQuery.support.scriptEval )
+                               script.appendChild( document.createTextNode( data ) );
+                       else
+                               script.text = data;
+
+                       // Use insertBefore instead of appendChild  to circumvent an IE6 bug.
+                       // This arises when a base node is used (#2709).
+                       head.insertBefore( script, head.firstChild );
+                       head.removeChild( script );
+               }
+       },
+
+       nodeName: function( elem, name ) {
+               return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
+       },
+
+       // args is for internal usage only
+       each: function( object, callback, args ) {
+               var name, i = 0, length = object.length;
+
+               if ( args ) {
+                       if ( length === undefined ) {
+                               for ( name in object )
+                                       if ( callback.apply( object[ name ], args ) === false )
+                                               break;
+                       } else
+                               for ( ; i < length; )
+                                       if ( callback.apply( object[ i++ ], args ) === false )
+                                               break;
+
+               // A special, fast, case for the most common use of each
+               } else {
+                       if ( length === undefined ) {
+                               for ( name in object )
+                                       if ( callback.call( object[ name ], name, object[ name ] ) === false )
+                                               break;
+                       } else
+                               for ( var value = object[0];
+                                       i < length && callback.call( value, i, value ) !== false; value = object[++i] ) { }
+               }
+
+               return object;
+       },
+
+       prop: function( elem, value, type, i, name ) {
+               // Handle executable functions
+               if ( jQuery.isFunction( value ) )
+                       value = value.call( elem, i );
+
+               // Handle passing in a number to a CSS property
+               return typeof value === "number" && type == "curCSS" && !exclude.test( name ) ?
+                       value + "px" :
+                       value;
+       },
+
+       className: {
+               // internal only, use addClass("class")
+               add: function( elem, classNames ) {
+                       jQuery.each( ( classNames || "" ).split( /\s+/ ), function( i, className ) {
+                               if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
+                                       elem.className += ( elem.className ? " " : "" ) + className;
+                       } );
+               },
+
+               // internal only, use removeClass("class")
+               remove: function( elem, classNames ) {
+                       if ( elem.nodeType == 1 )
+                               elem.className = classNames !== undefined ?
+                                       jQuery.grep( elem.className.split( /\s+/ ), function( className ) {
+                                               return !jQuery.className.has( classNames, className );
+                                       } ).join( " " ) :
+                                       "";
+               },
+
+               // internal only, use hasClass("class")
+               has: function( elem, className ) {
+                       return elem && jQuery.inArray( className, ( elem.className || elem ).toString().split( /\s+/ ) ) > -1;
+               }
+       },
+
+       // A method for quickly swapping in/out CSS properties to get correct calculations
+       swap: function( elem, options, callback ) {
+               var old = { };
+               // Remember the old values, and insert the new ones
+               for ( var name in options ) {
+                       old[ name ] = elem.style[ name ];
+                       elem.style[ name ] = options[ name ];
+               }
+
+               callback.call( elem );
+
+               // Revert the old values
+               for ( var name in options )
+                       elem.style[ name ] = old[ name ];
+       },
+
+       css: function( elem, name, force, extra ) {
+               if ( name == "width" || name == "height" ) {
+                       var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
+
+                       function getWH() {
+                               val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
+
+                               if ( extra === "border" )
+                                       return;
+
+                               jQuery.each( which, function() {
+                                       if ( !extra )
+                                               val -= parseFloat( jQuery.curCSS( elem, "padding" + this, true ) ) || 0;
+                                       if ( extra === "margin" )
+                                               val += parseFloat( jQuery.curCSS( elem, "margin" + this, true ) ) || 0;
+                                       else
+                                               val -= parseFloat( jQuery.curCSS( elem, "border" + this + "Width", true ) ) || 0;
+                               } );
+                       }
+
+                       if ( elem.offsetWidth !== 0 )
+                               getWH();
+                       else
+                               jQuery.swap( elem, props, getWH );
+
+                       return Math.max( 0, Math.round( val ) );
+               }
+
+               return jQuery.curCSS( elem, name, force );
+       },
+
+       curCSS: function( elem, name, force ) {
+               var ret, style = elem.style;
+
+               // We need to handle opacity special in IE
+               if ( name == "opacity" && !jQuery.support.opacity ) {
+                       ret = jQuery.attr( style, "opacity" );
+
+                       return ret == "" ?
+                               "1" :
+                               ret;
+               }
+
+               // Make sure we're using the right name for getting the float value
+               if ( name.match( / float /i ) )
+                       name = styleFloat;
+
+               if ( !force && style && style[ name ] )
+                       ret = style[ name ];
+
+               else if ( defaultView.getComputedStyle ) {
+
+                       // Only "float" is needed here
+                       if ( name.match( / float /i ) )
+                               name = "float";
+
+                       name = name.replace( / ( [A - Z] ) /g, "-$1" ).toLowerCase();
+
+                       var computedStyle = defaultView.getComputedStyle( elem, null );
+
+                       if ( computedStyle )
+                               ret = computedStyle.getPropertyValue( name );
+
+                       // We should always get a number back from opacity
+                       if ( name == "opacity" && ret == "" )
+                               ret = "1";
+
+               } else if ( elem.currentStyle ) {
+                       var camelCase = name.replace( /\-(\w)/g, function( all, letter ) {
+                               return letter.toUpperCase();
+                       } );
+
+                       ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
+
+                       // 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
+                       if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
+                               // Remember the original values
+                               var left = style.left, rsLeft = elem.runtimeStyle.left;
+
+                               // Put in the new values to get a computed value out
+                               elem.runtimeStyle.left = elem.currentStyle.left;
+                               style.left = ret || 0;
+                               ret = style.pixelLeft + "px";
+
+                               // Revert the changed values
+                               style.left = left;
+                               elem.runtimeStyle.left = rsLeft;
+                       }
+               }
+
+               return ret;
+       },
+
+       clean: function( elems, context, fragment ) {
+               context = context || document;
+
+               // !context.createElement fails in IE with an error but returns typeof 'object'
+               if ( typeof context.createElement === "undefined" )
+                       context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
+
+               // If a single string is passed in and it's a single tag
+               // just do a createElement and skip the rest
+               if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) {
+                       var match = /^<(\w+)\s*\/?>$/.exec(elems[0]);
+                       if ( match )
+                               return [ context.createElement( match[1] ) ];
+               }
+
+               var ret = [], scripts = [], div = context.createElement("div");
+
+               jQuery.each(elems, function(i, elem){
+                       if ( typeof elem === "number" )
+                               elem += '';
+
+                       if ( !elem )
+                               return;
+
+                       // Convert html string into DOM nodes
+                       if ( typeof elem === "string" ) {
+                               // Fix "XHTML"-style tags in all browsers
+                               elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
+                                       return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
+                                               all :
+                                               front + "></" + tag + ">";
+                               });
+
+                               // Trim whitespace, otherwise indexOf won't work as expected
+                               var tags = elem.replace(/^\s+/, "").substring(0, 10).toLowerCase();
+
+                               var wrap =
+                                       // option or optgroup
+                                       !tags.indexOf("<opt") &&
+                                       [ 1, "<select multiple='multiple'>", "</select>" ] ||
+
+                                       !tags.indexOf("<leg") &&
+                                       [ 1, "<fieldset>", "</fieldset>" ] ||
+
+                                       tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
+                                       [ 1, "<table>", "</table>" ] ||
+
+                                       !tags.indexOf("<tr") &&
+                                       [ 2, "<table><tbody>", "</tbody></table>" ] ||
+
+                                       // <thead> matched above
+                                       (!tags.indexOf("<td") || !tags.indexOf("<th")) &&
+                                       [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
+
+                                       !tags.indexOf("<col") &&
+                                       [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
+
+                                       // IE can't serialize <link> and <script> tags normally
+                                       !jQuery.support.htmlSerialize &&
+                                       [ 1, "div<div>", "</div>" ] ||
+
+                                       [ 0, "", "" ];
+
+                               // Go to html and back, then peel off extra wrappers
+                               div.innerHTML = wrap[1] + elem + wrap[2];
+
+                               // Move to the right depth
+                               while ( wrap[0]-- )
+                                       div = div.lastChild;
+
+                               // Remove IE's autoinserted <tbody> from table fragments
+                               if ( !jQuery.support.tbody ) {
+
+                                       // String was a <table>, *may* have spurious <tbody>
+                                       var hasBody = /<tbody/i.test(elem),
+                                               tbody = !tags.indexOf("<table") && !hasBody ?
+                                                       div.firstChild && div.firstChild.childNodes :
+
+                                               // String was a bare <thead> or <tfoot>
+                                               wrap[1] == "<table>" && !hasBody ?
+                                                       div.childNodes :
+                                                       [];
+
+                                       for ( var 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 && /^\s/.test( elem ) )
+                                       div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
+                               
+                               elem = jQuery.makeArray( div.childNodes );
+                       }
+
+                       if ( elem.nodeType )
+                               ret.push( elem );
+                       else
+                               ret = jQuery.merge( ret, elem );
+
+               });
+
+               if ( fragment ) {
+                       for ( var i = 0; ret[i]; i++ ) {
+                               if ( jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
+                                       scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
+                               } else {
+                                       if ( ret[i].nodeType === 1 )
+                                               ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
+                                       fragment.appendChild( ret[i] );
+                               }
+                       }
+                       
+                       return scripts;
+               }
+
+               return ret;
+       },
+
+       attr: function( elem, name, value ) {
+               // don't set attributes on text and comment nodes
+               if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
+                       return undefined;
+
+               var notxml = !jQuery.isXMLDoc( elem ),
+                       // Whether we are setting (or getting)
+                       set = value !== undefined;
+
+               // Try to normalize/fix the name
+               name = notxml && jQuery.props[ name ] || name;
+
+               // Only do all the following if this is a node (faster for style)
+               // IE elem.getAttribute passes even for style
+               if ( elem.tagName ) {
+
+                       // These attributes require special treatment
+                       var special = /href|src|style/.test( name );
+
+                       // Safari mis-reports the default selected property of a hidden option
+                       // Accessing the parent's selectedIndex property fixes it
+                       if ( name == "selected" && elem.parentNode )
+                               elem.parentNode.selectedIndex;
+
+                       // If applicable, access the attribute via the DOM 0 way
+                       if ( name in elem && notxml && !special ) {
+                               if ( set ){
+                                       // We can't allow the type property to be changed (since it causes problems in IE)
+                                       if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
+                                               throw "type property can't be changed";
+
+                                       elem[ name ] = value;
+                               }
+
+                               // browsers index elements by id/name on forms, give priority to attributes.
+                               if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) )
+                                       return elem.getAttributeNode( name ).nodeValue;
+
+                               // 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/
+                               if ( name == "tabIndex" ) {
+                                       var attributeNode = elem.getAttributeNode( "tabIndex" );
+                                       return attributeNode && attributeNode.specified
+                                               ? attributeNode.value
+                                               : elem.nodeName.match(/(button|input|object|select|textarea)/i)
+                                                       ? 0
+                                                       : elem.nodeName.match(/^(a|area)$/i) && elem.href
+                                                               ? 0
+                                                               : undefined;
+                               }
+
+                               return elem[ name ];
+                       }
+
+                       if ( !jQuery.support.style && notxml &&  name == "style" )
+                               return jQuery.attr( elem.style, "cssText", value );
+
+                       if ( set )
+                               // convert the value to a string (all browsers do this but IE) see #1070
+                               elem.setAttribute( name, "" + value );
+
+                       var attr = !jQuery.support.hrefNormalized && notxml && special
+                                       // Some attributes require a special call on IE
+                                       ? elem.getAttribute( name, 2 )
+                                       : elem.getAttribute( name );
+
+                       // Non-existent attributes return null, we normalize to undefined
+                       return attr === null ? undefined : attr;
+               }
+
+               // elem is actually elem.style ... set the style
+
+               // IE uses filters for opacity
+               if ( !jQuery.support.opacity && name == "opacity" ) {
+                       if ( set ) {
+                               // IE has trouble with opacity if it does not have layout
+                               // Force it by setting the zoom level
+                               elem.zoom = 1;
+
+                               // Set the alpha filter to set the opacity
+                               elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
+                                       (parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
+                       }
+
+                       return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
+                               (parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '':
+                               "";
+               }
+
+               name = name.replace(/-([a-z])/ig, function(all, letter){
+                       return letter.toUpperCase();
+               });
+
+               if ( set )
+                       elem[ name ] = value;
+
+               return elem[ name ];
+       },
+
+       trim: function( text ) {
+               return (text || "").replace( /^\s+|\s+$/g, "" );
+       },
+
+       makeArray: function( array ) {
+               var ret = [];
+
+               if( array != null ){
+                       var i = array.length;
+                       // The window, strings (and functions) also have 'length'
+                       if( i == null || typeof array === "string" || jQuery.isFunction(array) || array.setInterval )
+                               ret[0] = array;
+                       else
+                               while( i )
+                                       ret[--i] = array[i];
+               }
+
+               return ret;
+       },
+
+       inArray: function( elem, array ) {
+               for ( var i = 0, length = array.length; i < length; i++ )
+               // Use === because on IE, window == document
+                       if ( array[ i ] === elem )
+                               return i;
+
+               return -1;
+       },
+
+       merge: function( first, second ) {
+               // We have to loop this way because IE & Opera overwrite the length
+               // expando of getElementsByTagName
+               var i = 0, elem, pos = first.length;
+               // Also, we need to make sure that the correct elements are being returned
+               // (IE returns comment nodes in a '*' query)
+               if ( !jQuery.support.getAll ) {
+                       while ( (elem = second[ i++ ]) != null )
+                               if ( elem.nodeType != 8 )
+                                       first[ pos++ ] = elem;
+
+               } else
+                       while ( (elem = second[ i++ ]) != null )
+                               first[ pos++ ] = elem;
+
+               return first;
+       },
+
+       unique: function( array ) {
+               var ret = [], done = {};
+
+               try {
+
+                       for ( var i = 0, length = array.length; i < length; i++ ) {
+                               var id = jQuery.data( array[ i ] );
+
+                               if ( !done[ id ] ) {
+                                       done[ id ] = true;
+                                       ret.push( array[ i ] );
+                               }
+                       }
+
+               } catch( e ) {
+                       ret = array;
+               }
+
+               return ret;
+       },
+
+       grep: function( elems, callback, inv ) {
+               var ret = [];
+
+               // Go through the array, only saving the items
+               // that pass the validator function
+               for ( var i = 0, length = elems.length; i < length; i++ )
+                       if ( !inv != !callback( elems[ i ], i ) )
+                               ret.push( elems[ i ] );
+
+               return ret;
+       },
+
+       map: function( elems, callback ) {
+               var ret = [];
+
+               // Go through the array, translating each of the items to their
+               // new value (or values).
+               for ( var i = 0, length = elems.length; i < length; i++ ) {
+                       var value = callback( elems[ i ], i );
+
+                       if ( value != null )
+                               ret[ ret.length ] = value;
+               }
+
+               return ret.concat.apply( [], ret );
+       }
+});
+
+// Use of jQuery.browser is deprecated.
+// It's included for backwards compatibility and plugins,
+// although they should work to migrate away.
+
+var userAgent = navigator.userAgent.toLowerCase();
+
+// Figure out what browser is being used
+jQuery.browser = {
+       version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1],
+       safari: /webkit/.test( userAgent ),
+       opera: /opera/.test( userAgent ),
+       msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
+       mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
+};
+
+jQuery.each({
+       parent: function(elem){return elem.parentNode;},
+       parents: function(elem){return jQuery.dir(elem,"parentNode");},
+       next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
+       prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
+       nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
+       prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
+       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.makeArray(elem.childNodes);}
+}, function(name, fn){
+       jQuery.fn[ name ] = function( selector ) {
+               var ret = jQuery.map( this, fn );
+
+               if ( selector && typeof selector == "string" )
+                       ret = jQuery.multiFilter( selector, ret );
+
+               return this.pushStack( jQuery.unique( ret ), name, selector );
+       };
+});
+
+jQuery.each({
+       appendTo: "append",
+       prependTo: "prepend",
+       insertBefore: "before",
+       insertAfter: "after",
+       replaceAll: "replaceWith"
+}, function(name, original){
+       jQuery.fn[ name ] = function( selector ) {
+               var ret = [], insert = jQuery( selector );
+
+               for ( var i = 0, l = insert.length; i < l; i++ ) {
+                       var elems = (i > 0 ? this.clone(true) : this).get();
+                       jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
+                       ret = ret.concat( elems );
+               }
+
+               return this.pushStack( ret, name, selector );
+       };
+});
+
+jQuery.each({
+       removeAttr: function( name ) {
+               jQuery.attr( this, name, "" );
+               if (this.nodeType == 1)
+                       this.removeAttribute( name );
+       },
+
+       addClass: function( classNames ) {
+               jQuery.className.add( this, classNames );
+       },
+
+       removeClass: function( classNames ) {
+               jQuery.className.remove( this, classNames );
+       },
+
+       toggleClass: function( classNames, state ) {
+               if( typeof state !== "boolean" )
+                       state = !jQuery.className.has( this, classNames );
+               jQuery.className[ state ? "add" : "remove" ]( this, classNames );
+       },
+
+       remove: function( selector ) {
+               if ( !selector || jQuery.filter( selector, [ this ] ).length ) {
+                       // Prevent memory leaks
+                       jQuery( "*", this ).add([this]).each(function(){
+                               jQuery.event.remove(this);
+                               jQuery.removeData(this);
+                       });
+                       if (this.parentNode)
+                               this.parentNode.removeChild( this );
+               }
+       },
+
+       empty: function() {
+               // Remove element nodes and prevent memory leaks
+               jQuery(this).children().remove();
+
+               // Remove any remaining nodes
+               while ( this.firstChild )
+                       this.removeChild( this.firstChild );
+       }
+}, function(name, fn){
+       jQuery.fn[ name ] = function(){
+               return this.each( fn, arguments );
+       };
+});
+
+// Helper function used by the dimensions and offset modules
+function num(elem, prop) {
+       return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0;
+}
+var expando = "jQuery" + now(), uuid = 0, windowData = {};
+
+jQuery.extend({
+       cache: {},
+
+       data: function( elem, name, data ) {
+               elem = elem == window ?
+                       windowData :
+                       elem;
+
+               var id = elem[ expando ];
+
+               // Compute a unique ID for the element
+               if ( !id )
+                       id = elem[ expando ] = ++uuid;
+
+               // Only generate the data cache if we're
+               // trying to access or manipulate it
+               if ( name && !jQuery.cache[ id ] )
+                       jQuery.cache[ id ] = {};
+
+               // Prevent overriding the named cache with undefined values
+               if ( data !== undefined )
+                       jQuery.cache[ id ][ name ] = data;
+
+               // Return the named cache data, or the ID for the element
+               return name ?
+                       jQuery.cache[ id ][ name ] :
+                       id;
+       },
+
+       removeData: function( elem, name ) {
+               elem = elem == window ?
+                       windowData :
+                       elem;
+
+               var id = elem[ expando ];
+
+               // If we want to remove a specific section of the element's data
+               if ( name ) {
+                       if ( jQuery.cache[ id ] ) {
+                               // Remove the section of cache data
+                               delete jQuery.cache[ id ][ name ];
+
+                               // If we've removed all the data, remove the element's cache
+                               name = "";
+
+                               for ( name in jQuery.cache[ id ] )
+                                       break;
+
+                               if ( !name )
+                                       jQuery.removeData( elem );
+                       }
+
+               // Otherwise, we want to remove all of the element's data
+               } else {
+                       // Clean up the element expando
+                       try {
+                               delete elem[ expando ];
+                       } catch(e){
+                               // IE has trouble directly removing the expando
+                               // but it's ok with using removeAttribute
+                               if ( elem.removeAttribute )
+                                       elem.removeAttribute( expando );
+                       }
+
+                       // Completely remove the data cache
+                       delete jQuery.cache[ id ];
+               }
+       },
+       queue: function( elem, type, data ) {
+               if ( elem ){
+       
+                       type = (type || "fx") + "queue";
+       
+                       var q = jQuery.data( elem, type );
+       
+                       if ( !q || jQuery.isArray(data) )
+                               q = jQuery.data( elem, type, jQuery.makeArray(data) );
+                       else if( data )
+                               q.push( data );
+       
+               }
+               return q;
+       },
+
+       dequeue: function( elem, type ){
+               var queue = jQuery.queue( elem, type ),
+                       fn = queue.shift();
+               
+               if( !type || type === "fx" )
+                       fn = queue[0];
+                       
+               if( fn !== undefined )
+                       fn.call(elem);
+       }
+});
+
+jQuery.fn.extend({
+       data: function( key, value ){
+               var parts = key.split(".");
+               parts[1] = parts[1] ? "." + parts[1] : "";
+
+               if ( value === undefined ) {
+                       var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
+
+                       if ( data === undefined && this.length )
+                               data = jQuery.data( this[0], key );
+
+                       return data === undefined && parts[1] ?
+                               this.data( parts[0] ) :
+                               data;
+               } else
+                       return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
+                               jQuery.data( this, key, value );
+                       });
+       },
+
+       removeData: function( key ){
+               return this.each(function(){
+                       jQuery.removeData( this, key );
+               });
+       },
+       queue: function(type, data){
+               if ( typeof type !== "string" ) {
+                       data = type;
+                       type = "fx";
+               }
+
+               if ( data === undefined )
+                       return jQuery.queue( this[0], type );
+
+               return this.each(function(){
+                       var queue = jQuery.queue( this, type, data );
+                       
+                        if( type == "fx" && queue.length == 1 )
+                               queue[0].call(this);
+               });
+       },
+       dequeue: function(type){
+               return this.each(function(){
+                       jQuery.dequeue( this, type );
+               });
+       }
+});/*!
+ * Sizzle CSS Selector Engine - v0.9.3
+ *  Copyright 2009, The Dojo Foundation
+ *  Released under the MIT, BSD, and GPL Licenses.
+ *  More information: http://sizzlejs.com/
+ */
+(function(){
+
+var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,
+       done = 0,
+       toString = Object.prototype.toString;
+
+var Sizzle = function(selector, context, results, seed) {
+       results = results || [];
+       context = context || document;
+
+       if ( context.nodeType !== 1 && context.nodeType !== 9 )
+               return [];
+       
+       if ( !selector || typeof selector !== "string" ) {
+               return results;
+       }
+
+       var parts = [], m, set, checkSet, check, mode, extra, prune = true;
+       
+       // Reset the position of the chunker regexp (start from head)
+       chunker.lastIndex = 0;
+       
+       while ( (m = chunker.exec(selector)) !== null ) {
+               parts.push( m[1] );
+               
+               if ( m[2] ) {
+                       extra = RegExp.rightContext;
+                       break;
+               }
+       }
+
+       if ( parts.length > 1 && origPOS.exec( selector ) ) {
+               if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
+                       set = posProcess( parts[0] + parts[1], context );
+               } else {
+                       set = Expr.relative[ parts[0] ] ?
+                               [ context ] :
+                               Sizzle( parts.shift(), context );
+
+                       while ( parts.length ) {
+                               selector = parts.shift();
+
+                               if ( Expr.relative[ selector ] )
+                                       selector += parts.shift();
+
+                               set = posProcess( selector, set );
+                       }
+               }
+       } else {
+               var ret = seed ?
+                       { expr: parts.pop(), set: makeArray(seed) } :
+                       Sizzle.find( parts.pop(), parts.length === 1 && context.parentNode ? context.parentNode : context, isXML(context) );
+               set = Sizzle.filter( ret.expr, ret.set );
+
+               if ( parts.length > 0 ) {
+                       checkSet = makeArray(set);
+               } else {
+                       prune = false;
+               }
+
+               while ( parts.length ) {
+                       var cur = parts.pop(), pop = cur;
+
+                       if ( !Expr.relative[ cur ] ) {
+                               cur = "";
+                       } else {
+                               pop = parts.pop();
+                       }
+
+                       if ( pop == null ) {
+                               pop = context;
+                       }
+
+                       Expr.relative[ cur ]( checkSet, pop, isXML(context) );
+               }
+       }
+
+       if ( !checkSet ) {
+               checkSet = set;
+       }
+
+       if ( !checkSet ) {
+               throw "Syntax error, unrecognized expression: " + (cur || selector);
+       }
+
+       if ( toString.call(checkSet) === "[object Array]" ) {
+               if ( !prune ) {
+                       results.push.apply( results, checkSet );
+               } else if ( context.nodeType === 1 ) {
+                       for ( var i = 0; checkSet[i] != null; i++ ) {
+                               if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
+                                       results.push( set[i] );
+                               }
+                       }
+               } else {
+                       for ( var i = 0; checkSet[i] != null; i++ ) {
+                               if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
+                                       results.push( set[i] );
+                               }
+                       }
+               }
+       } else {
+               makeArray( checkSet, results );
+       }
+
+       if ( extra ) {
+               Sizzle( extra, context, results, seed );
+
+               if ( sortOrder ) {
+                       hasDuplicate = false;
+                       results.sort(sortOrder);
+
+                       if ( hasDuplicate ) {
+                               for ( var i = 1; i < results.length; i++ ) {
+                                       if ( results[i] === results[i-1] ) {
+                                               results.splice(i--, 1);
+                                       }
+                               }
+                       }
+               }
+       }
+
+       return results;
+};
+
+Sizzle.matches = function(expr, set){
+       return Sizzle(expr, null, null, set);
+};
+
+Sizzle.find = function(expr, context, isXML){
+       var set, match;
+
+       if ( !expr ) {
+               return [];
+       }
+
+       for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
+               var type = Expr.order[i], match;
+               
+               if ( (match = Expr.match[ type ].exec( expr )) ) {
+                       var left = RegExp.leftContext;
+
+                       if ( left.substr( left.length - 1 ) !== "\\" ) {
+                               match[1] = (match[1] || "").replace(/\\/g, "");
+                               set = Expr.find[ type ]( match, context, isXML );
+                               if ( set != null ) {
+                                       expr = expr.replace( Expr.match[ type ], "" );
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       if ( !set ) {
+               set = context.getElementsByTagName("*");
+       }
+
+       return {set: set, expr: expr};
+};
+
+Sizzle.filter = function(expr, set, inplace, not){
+       var old = expr, result = [], curLoop = set, match, anyFound,
+               isXMLFilter = set && set[0] && isXML(set[0]);
+
+       while ( expr && set.length ) {
+               for ( var type in Expr.filter ) {
+                       if ( (match = Expr.match[ type ].exec( expr )) != null ) {
+                               var filter = Expr.filter[ type ], found, item;
+                               anyFound = false;
+
+                               if ( curLoop == result ) {
+                                       result = [];
+                               }
+
+                               if ( Expr.preFilter[ type ] ) {
+                                       match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
+
+                                       if ( !match ) {
+                                               anyFound = found = true;
+                                       } else if ( match === true ) {
+                                               continue;
+                                       }
+                               }
+
+                               if ( match ) {
+                                       for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
+                                               if ( item ) {
+                                                       found = filter( item, match, i, curLoop );
+                                                       var pass = not ^ !!found;
+
+                                                       if ( inplace && found != null ) {
+                                                               if ( pass ) {
+                                                                       anyFound = true;
+                                                               } else {
+                                                                       curLoop[i] = false;
+                                                               }
+                                                       } else if ( pass ) {
+                                                               result.push( item );
+                                                               anyFound = true;
+                                                       }
+                                               }
+                                       }
+                               }
+
+                               if ( found !== undefined ) {
+                                       if ( !inplace ) {
+                                               curLoop = result;
+                                       }
+
+                                       expr = expr.replace( Expr.match[ type ], "" );
+
+                                       if ( !anyFound ) {
+                                               return [];
+                                       }
+
+                                       break;
+                               }
+                       }
+               }
+
+               // Improper expression
+               if ( expr == old ) {
+                       if ( anyFound == null ) {
+                               throw "Syntax error, unrecognized expression: " + expr;
+                       } else {
+                               break;
+                       }
+               }
+
+               old = expr;
+       }
+
+       return curLoop;
+};
+
+var Expr = Sizzle.selectors = {
+       order: [ "ID", "NAME", "TAG" ],
+       match: {
+               ID: /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
+               CLASS: /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
+               NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,
+               ATTR: /\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
+               TAG: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,
+               CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
+               POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
+               PSEUDO: /:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/
+       },
+       attrMap: {
+               "class": "className",
+               "for": "htmlFor"
+       },
+       attrHandle: {
+               href: function(elem){
+                       return elem.getAttribute("href");
+               }
+       },
+       relative: {
+               "+": function(checkSet, part, isXML){
+                       var isPartStr = typeof part === "string",
+                               isTag = isPartStr && !/\W/.test(part),
+                               isPartStrNotTag = isPartStr && !isTag;
+
+                       if ( isTag && !isXML ) {
+                               part = part.toUpperCase();
+                       }
+
+                       for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
+                               if ( (elem = checkSet[i]) ) {
+                                       while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
+
+                                       checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ?
+                                               elem || false :
+                                               elem === part;
+                               }
+                       }
+
+                       if ( isPartStrNotTag ) {
+                               Sizzle.filter( part, checkSet, true );
+                       }
+               },
+               ">": function(checkSet, part, isXML){
+                       var isPartStr = typeof part === "string";
+
+                       if ( isPartStr && !/\W/.test(part) ) {
+                               part = isXML ? part : part.toUpperCase();
+
+                               for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+                                       var elem = checkSet[i];
+                                       if ( elem ) {
+                                               var parent = elem.parentNode;
+                                               checkSet[i] = parent.nodeName === part ? parent : false;
+                                       }
+                               }
+                       } else {
+                               for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+                                       var elem = checkSet[i];
+                                       if ( elem ) {
+                                               checkSet[i] = isPartStr ?
+                                                       elem.parentNode :
+                                                       elem.parentNode === part;
+                                       }
+                               }
+
+                               if ( isPartStr ) {
+                                       Sizzle.filter( part, checkSet, true );
+                               }
+                       }
+               },
+               "": function(checkSet, part, isXML){
+                       var doneName = done++, checkFn = dirCheck;
+
+                       if ( !part.match(/\W/) ) {
+                               var nodeCheck = part = isXML ? part : part.toUpperCase();
+                               checkFn = dirNodeCheck;
+                       }
+
+                       checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
+               },
+               "~": function(checkSet, part, isXML){
+                       var doneName = done++, checkFn = dirCheck;
+
+                       if ( typeof part === "string" && !part.match(/\W/) ) {
+                               var nodeCheck = part = isXML ? part : part.toUpperCase();
+                               checkFn = dirNodeCheck;
+                       }
+
+                       checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
+               }
+       },
+       find: {
+               ID: function(match, context, isXML){
+                       if ( typeof context.getElementById !== "undefined" && !isXML ) {
+                               var m = context.getElementById(match[1]);
+                               return m ? [m] : [];
+                       }
+               },
+               NAME: function(match, context, isXML){
+                       if ( typeof context.getElementsByName !== "undefined" ) {
+                               var ret = [], results = context.getElementsByName(match[1]);
+
+                               for ( var i = 0, l = results.length; i < l; i++ ) {
+                                       if ( results[i].getAttribute("name") === match[1] ) {
+                                               ret.push( results[i] );
+                                       }
+                               }
+
+                               return ret.length === 0 ? null : ret;
+                       }
+               },
+               TAG: function(match, context){
+                       return context.getElementsByTagName(match[1]);
+               }
+       },
+       preFilter: {
+               CLASS: function(match, curLoop, inplace, result, not, isXML){
+                       match = " " + match[1].replace(/\\/g, "") + " ";
+
+                       if ( isXML ) {
+                               return match;
+                       }
+
+                       for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
+                               if ( elem ) {
+                                       if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) {
+                                               if ( !inplace )
+                                                       result.push( elem );
+                                       } else if ( inplace ) {
+                                               curLoop[i] = false;
+                                       }
+                               }
+                       }
+
+                       return false;
+               },
+               ID: function(match){
+                       return match[1].replace(/\\/g, "");
+               },
+               TAG: function(match, curLoop){
+                       for ( var i = 0; curLoop[i] === false; i++ ){}
+                       return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase();
+               },
+               CHILD: function(match){
+                       if ( match[1] == "nth" ) {
+                               // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
+                               var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
+                                       match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" ||
+                                       !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
+
+                               // calculate the numbers (first)n+(last) including if they are negative
+                               match[2] = (test[1] + (test[2] || 1)) - 0;
+                               match[3] = test[3] - 0;
+                       }
+
+                       // TODO: Move to normal caching system
+                       match[0] = done++;
+
+                       return match;
+               },
+               ATTR: function(match, curLoop, inplace, result, not, isXML){
+                       var name = match[1].replace(/\\/g, "");
+                       
+                       if ( !isXML && Expr.attrMap[name] ) {
+                               match[1] = Expr.attrMap[name];
+                       }
+
+                       if ( match[2] === "~=" ) {
+                               match[4] = " " + match[4] + " ";
+                       }
+
+                       return match;
+               },
+               PSEUDO: function(match, curLoop, inplace, result, not){
+                       if ( match[1] === "not" ) {
+                               // If we're dealing with a complex expression, or a simple one
+                               if ( match[3].match(chunker).length > 1 || /^\w/.test(match[3]) ) {
+                                       match[3] = Sizzle(match[3], null, null, curLoop);
+                               } else {
+                                       var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
+                                       if ( !inplace ) {
+                                               result.push.apply( result, ret );
+                                       }
+                                       return false;
+                               }
+                       } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
+                               return true;
+                       }
+                       
+                       return match;
+               },
+               POS: function(match){
+                       match.unshift( true );
+                       return match;
+               }
+       },
+       filters: {
+               enabled: function(elem){
+                       return elem.disabled === false && elem.type !== "hidden";
+               },
+               disabled: function(elem){
+                       return elem.disabled === true;
+               },
+               checked: function(elem){
+                       return elem.checked === true;
+               },
+               selected: function(elem){
+                       // Accessing this property makes selected-by-default
+                       // options in Safari work properly
+                       elem.parentNode.selectedIndex;
+                       return elem.selected === true;
+               },
+               parent: function(elem){
+                       return !!elem.firstChild;
+               },
+               empty: function(elem){
+                       return !elem.firstChild;
+               },
+               has: function(elem, i, match){
+                       return !!Sizzle( match[3], elem ).length;
+               },
+               header: function(elem){
+                       return /h\d/i.test( elem.nodeName );
+               },
+               text: function(elem){
+                       return "text" === elem.type;
+               },
+               radio: function(elem){
+                       return "radio" === elem.type;
+               },
+               checkbox: function(elem){
+                       return "checkbox" === elem.type;
+               },
+               file: function(elem){
+                       return "file" === elem.type;
+               },
+               password: function(elem){
+                       return "password" === elem.type;
+               },
+               submit: function(elem){
+                       return "submit" === elem.type;
+               },
+               image: function(elem){
+                       return "image" === elem.type;
+               },
+               reset: function(elem){
+                       return "reset" === elem.type;
+               },
+               button: function(elem){
+                       return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON";
+               },
+               input: function(elem){
+                       return /input|select|textarea|button/i.test(elem.nodeName);
+               }
+       },
+       setFilters: {
+               first: function(elem, i){
+                       return i === 0;
+               },
+               last: function(elem, i, match, array){
+                       return i === array.length - 1;
+               },
+               even: function(elem, i){
+                       return i % 2 === 0;
+               },
+               odd: function(elem, i){
+                       return i % 2 === 1;
+               },
+               lt: function(elem, i, match){
+                       return i < match[3] - 0;
+               },
+               gt: function(elem, i, match){
+                       return i > match[3] - 0;
+               },
+               nth: function(elem, i, match){
+                       return match[3] - 0 == i;
+               },
+               eq: function(elem, i, match){
+                       return match[3] - 0 == i;
+               }
+       },
+       filter: {
+               PSEUDO: function(elem, match, i, array){
+                       var name = match[1], filter = Expr.filters[ name ];
+
+                       if ( filter ) {
+                               return filter( elem, i, match, array );
+                       } else if ( name === "contains" ) {
+                               return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0;
+                       } else if ( name === "not" ) {
+                               var not = match[3];
+
+                               for ( var i = 0, l = not.length; i < l; i++ ) {
+                                       if ( not[i] === elem ) {
+                                               return false;
+                                       }
+                               }
+
+                               return true;
+                       }
+               },
+               CHILD: function(elem, match){
+                       var type = match[1], node = elem;
+                       switch (type) {
+                               case 'only':
+                               case 'first':
+                                       while (node = node.previousSibling)  {
+                                               if ( node.nodeType === 1 ) return false;
+                                       }
+                                       if ( type == 'first') return true;
+                                       node = elem;
+                               case 'last':
+                                       while (node = node.nextSibling)  {
+                                               if ( node.nodeType === 1 ) return false;
+                                       }
+                                       return true;
+                               case 'nth':
+                                       var first = match[2], last = match[3];
+
+                                       if ( first == 1 && last == 0 ) {
+                                               return true;
+                                       }
+                                       
+                                       var doneName = match[0],
+                                               parent = elem.parentNode;
+       
+                                       if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
+                                               var count = 0;
+                                               for ( node = parent.firstChild; node; node = node.nextSibling ) {
+                                                       if ( node.nodeType === 1 ) {
+                                                               node.nodeIndex = ++count;
+                                                       }
+                                               } 
+                                               parent.sizcache = doneName;
+                                       }
+                                       
+                                       var diff = elem.nodeIndex - last;
+                                       if ( first == 0 ) {
+                                               return diff == 0;
+                                       } else {
+                                               return ( diff % first == 0 && diff / first >= 0 );
+                                       }
+                       }
+               },
+               ID: function(elem, match){
+                       return elem.nodeType === 1 && elem.getAttribute("id") === match;
+               },
+               TAG: function(elem, match){
+                       return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;
+               },
+               CLASS: function(elem, match){
+                       return (" " + (elem.className || elem.getAttribute("class")) + " ")
+                               .indexOf( match ) > -1;
+               },
+               ATTR: function(elem, match){
+                       var name = match[1],
+                               result = Expr.attrHandle[ name ] ?
+                                       Expr.attrHandle[ name ]( elem ) :
+                                       elem[ name ] != null ?
+                                               elem[ name ] :
+                                               elem.getAttribute( name ),
+                               value = result + "",
+                               type = match[2],
+                               check = match[4];
+
+                       return result == null ?
+                               type === "!=" :
+                               type === "=" ?
+                               value === check :
+                               type === "*=" ?
+                               value.indexOf(check) >= 0 :
+                               type === "~=" ?
+                               (" " + value + " ").indexOf(check) >= 0 :
+                               !check ?
+                               value && result !== false :
+                               type === "!=" ?
+                               value != check :
+                               type === "^=" ?
+                               value.indexOf(check) === 0 :
+                               type === "$=" ?
+                               value.substr(value.length - check.length) === check :
+                               type === "|=" ?
+                               value === check || value.substr(0, check.length + 1) === check + "-" :
+                               false;
+               },
+               POS: function(elem, match, i, array){
+                       var name = match[2], filter = Expr.setFilters[ name ];
+
+                       if ( filter ) {
+                               return filter( elem, i, match, array );
+                       }
+               }
+       }
+};
+
+var origPOS = Expr.match.POS;
+
+for ( var type in Expr.match ) {
+       Expr.match[ type ] = RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
+}
+
+var makeArray = function(array, results) {
+       array = Array.prototype.slice.call( array );
+
+       if ( results ) {
+               results.push.apply( results, array );
+               return results;
+       }
+       
+       return array;
+};
+
+// Perform a simple check to determine if the browser is capable of
+// converting a NodeList to an array using builtin methods.
+try {
+       Array.prototype.slice.call( document.documentElement.childNodes );
+
+// Provide a fallback method if it does not work
+} catch(e){
+       makeArray = function(array, results) {
+               var ret = results || [];
+
+               if ( toString.call(array) === "[object Array]" ) {
+                       Array.prototype.push.apply( ret, array );
+               } else {
+                       if ( typeof array.length === "number" ) {
+                               for ( var i = 0, l = array.length; i < l; i++ ) {
+                                       ret.push( array[i] );
+                               }
+                       } else {
+                               for ( var i = 0; array[i]; i++ ) {
+                                       ret.push( array[i] );
+                               }
+                       }
+               }
+
+               return ret;
+       };
+}
+
+var sortOrder;
+
+if ( document.documentElement.compareDocumentPosition ) {
+       sortOrder = function( a, b ) {
+               var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
+               if ( ret === 0 ) {
+                       hasDuplicate = true;
+               }
+               return ret;
+       };
+} else if ( "sourceIndex" in document.documentElement ) {
+       sortOrder = function( a, b ) {
+               var ret = a.sourceIndex - b.sourceIndex;
+               if ( ret === 0 ) {
+                       hasDuplicate = true;
+               }
+               return ret;
+       };
+} else if ( document.createRange ) {
+       sortOrder = function( a, b ) {
+               var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
+               aRange.selectNode(a);
+               aRange.collapse(true);
+               bRange.selectNode(b);
+               bRange.collapse(true);
+               var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
+               if ( ret === 0 ) {
+                       hasDuplicate = true;
+               }
+               return ret;
+       };
+}
+
+// Check to see if the browser returns elements by name when
+// querying by getElementById (and provide a workaround)
+(function(){
+       // We're going to inject a fake input element with a specified name
+       var form = document.createElement("form"),
+               id = "script" + (new Date).getTime();
+       form.innerHTML = "<input name='" + id + "'/>";
+
+       // Inject it into the root element, check its status, and remove it quickly
+       var root = document.documentElement;
+       root.insertBefore( form, root.firstChild );
+
+       // The workaround has to do additional checks after a getElementById
+       // Which slows things down for other browsers (hence the branching)
+       if ( !!document.getElementById( id ) ) {
+               Expr.find.ID = function(match, context, isXML){
+                       if ( typeof context.getElementById !== "undefined" && !isXML ) {
+                               var m = context.getElementById(match[1]);
+                               return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
+                       }
+               };
+
+               Expr.filter.ID = function(elem, match){
+                       var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
+                       return elem.nodeType === 1 && node && node.nodeValue === match;
+               };
+       }
+
+       root.removeChild( form );
+})();
+
+(function(){
+       // Check to see if the browser returns only elements
+       // when doing getElementsByTagName("*")
+
+       // Create a fake element
+       var div = document.createElement("div");
+       div.appendChild( document.createComment("") );
+
+       // Make sure no comments are found
+       if ( div.getElementsByTagName("*").length > 0 ) {
+               Expr.find.TAG = function(match, context){
+                       var results = context.getElementsByTagName(match[1]);
+
+                       // Filter out possible comments
+                       if ( match[1] === "*" ) {
+                               var tmp = [];
+
+                               for ( var i = 0; results[i]; i++ ) {
+                                       if ( results[i].nodeType === 1 ) {
+                                               tmp.push( results[i] );
+                                       }
+                               }
+
+                               results = tmp;
+                       }
+
+                       return results;
+               };
+       }
+
+       // Check to see if an attribute returns normalized href attributes
+       div.innerHTML = "<a href='#'></a>";
+       if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
+                       div.firstChild.getAttribute("href") !== "#" ) {
+               Expr.attrHandle.href = function(elem){
+                       return elem.getAttribute("href", 2);
+               };
+       }
+})();
+
+if ( document.querySelectorAll ) (function(){
+       var oldSizzle = Sizzle, div = document.createElement("div");
+       div.innerHTML = "<p class='TEST'></p>";
+
+       // Safari can't handle uppercase or unicode characters when
+       // in quirks mode.
+       if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
+               return;
+       }
+       
+       Sizzle = function(query, context, extra, seed){
+               context = context || document;
+
+               // Only use querySelectorAll on non-XML documents
+               // (ID selectors don't work in non-HTML documents)
+               if ( !seed && context.nodeType === 9 && !isXML(context) ) {
+                       try {
+                               return makeArray( context.querySelectorAll(query), extra );
+                       } catch(e){}
+               }
+               
+               return oldSizzle(query, context, extra, seed);
+       };
+
+       Sizzle.find = oldSizzle.find;
+       Sizzle.filter = oldSizzle.filter;
+       Sizzle.selectors = oldSizzle.selectors;
+       Sizzle.matches = oldSizzle.matches;
+})();
+
+if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){
+       var div = document.createElement("div");
+       div.innerHTML = "<div class='test e'></div><div class='test'></div>";
+
+       // Opera can't find a second classname (in 9.6)
+       if ( div.getElementsByClassName("e").length === 0 )
+               return;
+
+       // Safari caches class attributes, doesn't catch changes (in 3.2)
+       div.lastChild.className = "e";
+
+       if ( div.getElementsByClassName("e").length === 1 )
+               return;
+
+       Expr.order.splice(1, 0, "CLASS");
+       Expr.find.CLASS = function(match, context, isXML) {
+               if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
+                       return context.getElementsByClassName(match[1]);
+               }
+       };
+})();
+
+function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+       var sibDir = dir == "previousSibling" && !isXML;
+       for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+               var elem = checkSet[i];
+               if ( elem ) {
+                       if ( sibDir && elem.nodeType === 1 ){
+                               elem.sizcache = doneName;
+                               elem.sizset = i;
+                       }
+                       elem = elem[dir];
+                       var match = false;
+
+                       while ( elem ) {
+                               if ( elem.sizcache === doneName ) {
+                                       match = checkSet[elem.sizset];
+                                       break;
+                               }
+
+                               if ( elem.nodeType === 1 && !isXML ){
+                                       elem.sizcache = doneName;
+                                       elem.sizset = i;
+                               }
+
+                               if ( elem.nodeName === cur ) {
+                                       match = elem;
+                                       break;
+                               }
+
+                               elem = elem[dir];
+                       }
+
+                       checkSet[i] = match;
+               }
+       }
+}
+
+function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+       var sibDir = dir == "previousSibling" && !isXML;
+       for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+               var elem = checkSet[i];
+               if ( elem ) {
+                       if ( sibDir && elem.nodeType === 1 ) {
+                               elem.sizcache = doneName;
+                               elem.sizset = i;
+                       }
+                       elem = elem[dir];
+                       var match = false;
+
+                       while ( elem ) {
+                               if ( elem.sizcache === doneName ) {
+                                       match = checkSet[elem.sizset];
+                                       break;
+                               }
+
+                               if ( elem.nodeType === 1 ) {
+                                       if ( !isXML ) {
+                                               elem.sizcache = doneName;
+                                               elem.sizset = i;
+                                       }
+                                       if ( typeof cur !== "string" ) {
+                                               if ( elem === cur ) {
+                                                       match = true;
+                                                       break;
+                                               }
+
+                                       } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
+                                               match = elem;
+                                               break;
+                                       }
+                               }
+
+                               elem = elem[dir];
+                       }
+
+                       checkSet[i] = match;
+               }
+       }
+}
+
+var contains = document.compareDocumentPosition ?  function(a, b){
+       return a.compareDocumentPosition(b) & 16;
+} : function(a, b){
+       return a !== b && (a.contains ? a.contains(b) : true);
+};
+
+var isXML = function(elem){
+       return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
+               !!elem.ownerDocument && isXML( elem.ownerDocument );
+};
+
+var posProcess = function(selector, context){
+       var tmpSet = [], later = "", match,
+               root = context.nodeType ? [context] : context;
+
+       // Position selectors must be done after the filter
+       // And so must :not(positional) so we move all PSEUDOs to the end
+       while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
+               later += match[0];
+               selector = selector.replace( Expr.match.PSEUDO, "" );
+       }
+
+       selector = Expr.relative[selector] ? selector + "*" : selector;
+
+       for ( var i = 0, l = root.length; i < l; i++ ) {
+               Sizzle( selector, root[i], tmpSet );
+       }
+
+       return Sizzle.filter( later, tmpSet );
+};
+
+// EXPOSE
+jQuery.find = Sizzle;
+jQuery.filter = Sizzle.filter;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.filters;
+
+Sizzle.selectors.filters.hidden = function(elem){
+       return elem.offsetWidth === 0 || elem.offsetHeight === 0;
+};
+
+Sizzle.selectors.filters.visible = function(elem){
+       return elem.offsetWidth > 0 || elem.offsetHeight > 0;
+};
+
+Sizzle.selectors.filters.animated = function(elem){
+       return jQuery.grep(jQuery.timers, function(fn){
+               return elem === fn.elem;
+       }).length;
+};
+
+jQuery.multiFilter = function( expr, elems, not ) {
+       if ( not ) {
+               expr = ":not(" + expr + ")";
+       }
+
+       return Sizzle.matches(expr, elems);
+};
+
+jQuery.dir = function( elem, dir ){
+       var matched = [], cur = elem[dir];
+       while ( cur && cur != document ) {
+               if ( cur.nodeType == 1 )
+                       matched.push( cur );
+               cur = cur[dir];
+       }
+       return matched;
+};
+
+jQuery.nth = function(cur, result, dir, elem){
+       result = result || 1;
+       var num = 0;
+
+       for ( ; cur; cur = cur[dir] )
+               if ( cur.nodeType == 1 && ++num == result )
+                       break;
+
+       return cur;
+};
+
+jQuery.sibling = function(n, elem){
+       var r = [];
+
+       for ( ; n; n = n.nextSibling ) {
+               if ( n.nodeType == 1 && n != elem )
+                       r.push( n );
+       }
+
+       return r;
+};
+
+return;
+
+window.Sizzle = Sizzle;
+
+})();
+/*
+ * A number of helper functions used for managing events.
+ * Many of the ideas behind this code originated from
+ * Dean Edwards' addEvent library.
+ */
+jQuery.event = {
+
+       // Bind an event to an element
+       // Original by Dean Edwards
+       add: function(elem, types, handler, data) {
+               if ( elem.nodeType == 3 || elem.nodeType == 8 )
+                       return;
+
+               // For whatever reason, IE has trouble passing the window object
+               // around, causing it to be cloned in the process
+               if ( elem.setInterval && elem != window )
+                       elem = window;
+
+               // Make sure that the function being executed has a unique ID
+               if ( !handler.guid )
+                       handler.guid = this.guid++;
+
+               // if data is passed, bind to handler
+               if ( data !== undefined ) {
+                       // Create temporary function pointer to original handler
+                       var fn = handler;
+
+                       // Create unique handler function, wrapped around original handler
+                       handler = this.proxy( fn );
+
+                       // Store data in unique handler
+                       handler.data = data;
+               }
+
+               // Init the element's event structure
+               var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
+                       handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
+                               // Handle the second event of a trigger and when
+                               // an event is called after a page has unloaded
+                               return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
+                                       jQuery.event.handle.apply(arguments.callee.elem, arguments) :
+                                       undefined;
+                       });
+               // Add elem as a property of the handle function
+               // This is to prevent a memory leak with non-native
+               // event in IE.
+               handle.elem = elem;
+
+               // Handle multiple events separated by a space
+               // jQuery(...).bind("mouseover mouseout", fn);
+               jQuery.each(types.split(/\s+/), function(index, type) {
+                       // Namespaced event handlers
+                       var namespaces = type.split(".");
+                       type = namespaces.shift();
+                       handler.type = namespaces.slice().sort().join(".");
+
+                       // Get the current list of functions bound to this event
+                       var handlers = events[type];
+                       
+                       if ( jQuery.event.specialAll[type] )
+                               jQuery.event.specialAll[type].setup.call(elem, data, namespaces);
+
+                       // Init the event handler queue
+                       if (!handlers) {
+                               handlers = events[type] = {};
+
+                               // Check for a special event handler
+                               // Only use addEventListener/attachEvent if the special
+                               // events handler returns false
+                               if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem, data, namespaces) === false ) {
+                                       // Bind the global event handler to the element
+                                       if (elem.addEventListener)
+                                               elem.addEventListener(type, handle, false);
+                                       else if (elem.attachEvent)
+                                               elem.attachEvent("on" + type, handle);
+                               }
+                       }
+
+                       // Add the function to the element's handler list
+                       handlers[handler.guid] = handler;
+
+                       // Keep track of which events have been used, for global triggering
+                       jQuery.event.global[type] = true;
+               });
+
+               // Nullify elem to prevent memory leaks in IE
+               elem = null;
+       },
+
+       guid: 1,
+       global: {},
+
+       // Detach an event or set of events from an element
+       remove: function(elem, types, handler) {
+               // don't do events on text and comment nodes
+               if ( elem.nodeType == 3 || elem.nodeType == 8 )
+                       return;
+
+               var events = jQuery.data(elem, "events"), ret, index;
+
+               if ( events ) {
+                       // Unbind all events for the element
+                       if ( types === undefined || (typeof types === "string" && types.charAt(0) == ".") )
+                               for ( var type in events )
+                                       this.remove( elem, type + (types || "") );
+                       else {
+                               // types is actually an event object here
+                               if ( types.type ) {
+                                       handler = types.handler;
+                                       types = types.type;
+                               }
+
+                               // Handle multiple events seperated by a space
+                               // jQuery(...).unbind("mouseover mouseout", fn);
+                               jQuery.each(types.split(/\s+/), function(index, type){
+                                       // Namespaced event handlers
+                                       var namespaces = type.split(".");
+                                       type = namespaces.shift();
+                                       var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
+
+                                       if ( events[type] ) {
+                                               // remove the given handler for the given type
+                                               if ( handler )
+                                                       delete events[type][handler.guid];
+
+                                               // remove all handlers for the given type
+                                               else
+                                                       for ( var handle in events[type] )
+                                                               // Handle the removal of namespaced events
+                                                               if ( namespace.test(events[type][handle].type) )
+                                                                       delete events[type][handle];
+                                                                       
+                                               if ( jQuery.event.specialAll[type] )
+                                                       jQuery.event.specialAll[type].teardown.call(elem, namespaces);
+
+                                               // remove generic event handler if no more handlers exist
+                                               for ( ret in events[type] ) break;
+                                               if ( !ret ) {
+                                                       if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem, namespaces) === false ) {
+                                                               if (elem.removeEventListener)
+                                                                       elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
+                                                               else if (elem.detachEvent)
+                                                                       elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
+                                                       }
+                                                       ret = null;
+                                                       delete events[type];
+                                               }
+                                       }
+                               });
+                       }
+
+                       // Remove the expando if it's no longer used
+                       for ( ret in events ) break;
+                       if ( !ret ) {
+                               var handle = jQuery.data( elem, "handle" );
+                               if ( handle ) handle.elem = null;
+                               jQuery.removeData( elem, "events" );
+                               jQuery.removeData( elem, "handle" );
+                       }
+               }
+       },
+
+       // bubbling is internal
+       trigger: function( event, data, elem, bubbling ) {
+               // Event object or event type
+               var type = event.type || event;
+
+               if( !bubbling ){
+                       event = typeof event === "object" ?
+                               // jQuery.Event object
+                               event[expando] ? event :
+                               // Object literal
+                               jQuery.extend( jQuery.Event(type), event ) :
+                               // Just the event type (string)
+                               jQuery.Event(type);
+
+                       if ( type.indexOf("!") >= 0 ) {
+                               event.type = type = type.slice(0, -1);
+                               event.exclusive = true;
+                       }
+
+                       // Handle a global trigger
+                       if ( !elem ) {
+                               // Don't bubble custom events when global (to avoid too much overhead)
+                               event.stopPropagation();
+                               // Only trigger if we've ever bound an event for it
+                               if ( this.global[type] )
+                                       jQuery.each( jQuery.cache, function(){
+                                               if ( this.events && this.events[type] )
+                                                       jQuery.event.trigger( event, data, this.handle.elem );
+                                       });
+                       }
+
+                       // Handle triggering a single element
+
+                       // don't do events on text and comment nodes
+                       if ( !elem || elem.nodeType == 3 || elem.nodeType == 8 )
+                               return undefined;
+                       
+                       // Clean up in case it is reused
+                       event.result = undefined;
+                       event.target = elem;
+                       
+                       // Clone the incoming data, if any
+                       data = jQuery.makeArray(data);
+                       data.unshift( event );
+               }
+
+               event.currentTarget = elem;
+
+               // Trigger the event, it is assumed that "handle" is a function
+               var handle = jQuery.data(elem, "handle");
+               if ( handle )
+                       handle.apply( elem, data );
+
+               // Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
+               if ( (!elem[type] || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
+                       event.result = false;
+
+               // Trigger the native events (except for clicks on links)
+               if ( !bubbling && elem[type] && !event.isDefaultPrevented() && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
+                       this.triggered = true;
+                       try {
+                               elem[ type ]();
+                       // prevent IE from throwing an error for some hidden elements
+                       } catch (e) {}
+               }
+
+               this.triggered = false;
+
+               if ( !event.isPropagationStopped() ) {
+                       var parent = elem.parentNode || elem.ownerDocument;
+                       if ( parent )
+                               jQuery.event.trigger(event, data, parent, true);
+               }
+       },
+
+       handle: function(event) {
+               // returned undefined or false
+               var all, handlers;
+
+               event = arguments[0] = jQuery.event.fix( event || window.event );
+               event.currentTarget = this;
+               
+               // Namespaced event handlers
+               var namespaces = event.type.split(".");
+               event.type = namespaces.shift();
+
+               // Cache this now, all = true means, any handler
+               all = !namespaces.length && !event.exclusive;
+               
+               var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
+
+               handlers = ( jQuery.data(this, "events") || {} )[event.type];
+
+               for ( var j in handlers ) {
+                       var handler = handlers[j];
+
+                       // Filter the functions by class
+                       if ( all || namespace.test(handler.type) ) {
+                               // Pass in a reference to the handler function itself
+                               // So that we can later remove it
+                               event.handler = handler;
+                               event.data = handler.data;
+
+                               var ret = handler.apply(this, arguments);
+
+                               if( ret !== undefined ){
+                                       event.result = ret;
+                                       if ( ret === false ) {
+                                               event.preventDefault();
+                                               event.stopPropagation();
+                                       }
+                               }
+
+                               if( event.isImmediatePropagationStopped() )
+                                       break;
+
+                       }
+               }
+       },
+
+       props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
+
+       fix: function(event) {
+               if ( event[expando] )
+                       return event;
+
+               // store a copy of the original event object
+               // and "clone" to set read-only properties
+               var originalEvent = event;
+               event = jQuery.Event( originalEvent );
+
+               for ( var i = this.props.length, prop; i; ){
+                       prop = this.props[ --i ];
+                       event[ prop ] = originalEvent[ prop ];
+               }
+
+               // Fix target property, if necessary
+               if ( !event.target )
+                       event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
+
+               // check if target is a textnode (safari)
+               if ( event.target.nodeType == 3 )
+                       event.target = event.target.parentNode;
+
+               // Add relatedTarget, if necessary
+               if ( !event.relatedTarget && event.fromElement )
+                       event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
+
+               // Calculate pageX/Y if missing and clientX/Y available
+               if ( event.pageX == null && event.clientX != null ) {
+                       var doc = document.documentElement, body = document.body;
+                       event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
+                       event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
+               }
+
+               // Add which for key events
+               if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
+                       event.which = event.charCode || event.keyCode;
+
+               // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
+               if ( !event.metaKey && event.ctrlKey )
+                       event.metaKey = event.ctrlKey;
+
+               // Add which for click: 1 == left; 2 == middle; 3 == right
+               // Note: button is not normalized, so don't use it
+               if ( !event.which && event.button )
+                       event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
+
+               return event;
+       },
+
+       proxy: function( fn, proxy ){
+               proxy = proxy || function(){ return fn.apply(this, arguments); };
+               // Set the guid of unique handler to the same of original handler, so it can be removed
+               proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
+               // So proxy can be declared as an argument
+               return proxy;
+       },
+
+       special: {
+               ready: {
+                       // Make sure the ready event is setup
+                       setup: bindReady,
+                       teardown: function() {}
+               }
+       },
+       
+       specialAll: {
+               live: {
+                       setup: function( selector, namespaces ){
+                               jQuery.event.add( this, namespaces[0], liveHandler );
+                       },
+                       teardown:  function( namespaces ){
+                               if ( namespaces.length ) {
+                                       var remove = 0, name = RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");
+                                       
+                                       jQuery.each( (jQuery.data(this, "events").live || {}), function(){
+                                               if ( name.test(this.type) )
+                                                       remove++;
+                                       });
+                                       
+                                       if ( remove < 1 )
+                                               jQuery.event.remove( this, namespaces[0], liveHandler );
+                               }
+                       }
+               }
+       }
+};
+
+jQuery.Event = function( src ){
+       // Allow instantiation without the 'new' keyword
+       if( !this.preventDefault )
+               return new jQuery.Event(src);
+       
+       // Event object
+       if( src && src.type ){
+               this.originalEvent = src;
+               this.type = src.type;
+       // Event type
+       }else
+               this.type = src;
+
+       // timeStamp is buggy for some events on Firefox(#3843)
+       // So we won't rely on the native value
+       this.timeStamp = now();
+       
+       // Mark it as fixed
+       this[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)
+               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
+};
+// Checks if an event happened on an element within another element
+// Used in jQuery.event.special.mouseenter and mouseleave handlers
+var withinElement = function(event) {
+       // Check if mouse(over|out) are still within the same parent element
+       var parent = event.relatedTarget;
+       // Traverse up the tree
+       while ( parent && parent != this )
+               try { parent = parent.parentNode; }
+               catch(e) { parent = this; }
+       
+       if( parent != this ){
+               // set the correct event type
+               event.type = event.data;
+               // handle event if we actually just moused on to a non sub-element
+               jQuery.event.handle.apply( this, arguments );
+       }
+};
+       
+jQuery.each({ 
+       mouseover: 'mouseenter', 
+       mouseout: 'mouseleave'
+}, function( orig, fix ){
+       jQuery.event.special[ fix ] = {
+               setup: function(){
+                       jQuery.event.add( this, orig, withinElement, fix );
+               },
+               teardown: function(){
+                       jQuery.event.remove( this, orig, withinElement );
+               }
+       };                         
+});
+
+jQuery.fn.extend({
+       bind: function( type, data, fn ) {
+               return type == "unload" ? this.one(type, data, fn) : this.each(function(){
+                       jQuery.event.add( this, type, fn || data, fn && data );
+               });
+       },
+
+       one: function( type, data, fn ) {
+               var one = jQuery.event.proxy( fn || data, function(event) {
+                       jQuery(this).unbind(event, one);
+                       return (fn || data).apply( this, arguments );
+               });
+               return this.each(function(){
+                       jQuery.event.add( this, type, one, fn && data);
+               });
+       },
+
+       unbind: function( type, fn ) {
+               return this.each(function(){
+                       jQuery.event.remove( this, type, fn );
+               });
+       },
+
+       trigger: function( type, data ) {
+               return this.each(function(){
+                       jQuery.event.trigger( type, data, this );
+               });
+       },
+
+       triggerHandler: function( type, data ) {
+               if( this[0] ){
+                       var event = jQuery.Event(type);
+                       event.preventDefault();
+                       event.stopPropagation();
+                       jQuery.event.trigger( event, data, this[0] );
+                       return event.result;
+               }               
+       },
+
+       toggle: function( fn ) {
+               // Save reference to arguments for access in closure
+               var args = arguments, i = 1;
+
+               // link all the functions, so any of them can unbind this click handler
+               while( i < args.length )
+                       jQuery.event.proxy( fn, args[i++] );
+
+               return this.click( jQuery.event.proxy( fn, function(event) {
+                       // Figure out which function to execute
+                       this.lastToggle = ( this.lastToggle || 0 ) % i;
+
+                       // Make sure that clicks stop
+                       event.preventDefault();
+
+                       // and execute the function
+                       return args[ this.lastToggle++ ].apply( this, arguments ) || false;
+               }));
+       },
+
+       hover: function(fnOver, fnOut) {
+               return this.mouseenter(fnOver).mouseleave(fnOut);
+       },
+
+       ready: function(fn) {
+               // Attach the listeners
+               bindReady();
+
+               // If the DOM is already ready
+               if ( jQuery.isReady )
+                       // Execute the function immediately
+                       fn.call( document, jQuery );
+
+               // Otherwise, remember the function for later
+               else
+                       // Add the function to the wait list
+                       jQuery.readyList.push( fn );
+
+               return this;
+       },
+       
+       live: function( type, fn ){
+               var proxy = jQuery.event.proxy( fn );
+               proxy.guid += this.selector + type;
+
+               jQuery(document).bind( liveConvert(type, this.selector), this.selector, proxy );
+
+               return this;
+       },
+       
+       die: function( type, fn ){
+               jQuery(document).unbind( liveConvert(type, this.selector), fn ? { guid: fn.guid + this.selector + type } : null );
+               return this;
+       }
+});
+
+function liveHandler( event ){
+       var check = RegExp("(^|\\.)" + event.type + "(\\.|$)"),
+               stop = true,
+               elems = [];
+
+       jQuery.each(jQuery.data(this, "events").live || [], function(i, fn){
+               if ( check.test(fn.type) ) {
+                       var elem = jQuery(event.target).closest(fn.data)[0];
+                       if ( elem )
+                               elems.push({ elem: elem, fn: fn });
+               }
+       });
+
+       elems.sort(function(a,b) {
+               return jQuery.data(a.elem, "closest") - jQuery.data(b.elem, "closest");
+       });
+       
+       jQuery.each(elems, function(){
+               if ( this.fn.call(this.elem, event, this.fn.data) === false )
+                       return (stop = false);
+       });
+
+       return stop;
+}
+
+function liveConvert(type, selector){
+       return ["live", type, selector.replace(/\./g, "`").replace(/ /g, "|")].join(".");
+}
+
+jQuery.extend({
+       isReady: false,
+       readyList: [],
+       // Handle when the DOM is ready
+       ready: function() {
+               // Make sure that the DOM is not already loaded
+               if ( !jQuery.isReady ) {
+                       // Remember that the DOM is ready
+                       jQuery.isReady = true;
+
+                       // If there are functions bound, to execute
+                       if ( jQuery.readyList ) {
+                               // Execute all of them
+                               jQuery.each( jQuery.readyList, function(){
+                                       this.call( document, jQuery );
+                               });
+
+                               // Reset the list of functions
+                               jQuery.readyList = null;
+                       }
+
+                       // Trigger any bound ready events
+                       jQuery(document).triggerHandler("ready");
+               }
+       }
+});
+
+var readyBound = false;
+
+function bindReady(){
+       if ( readyBound ) return;
+       readyBound = true;
+
+       // Mozilla, Opera and webkit nightlies currently support this event
+       if ( document.addEventListener ) {
+               // Use the handy event callback
+               document.addEventListener( "DOMContentLoaded", function(){
+                       document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
+                       jQuery.ready();
+               }, false );
+
+       // If IE event model is used
+       } else if ( document.attachEvent ) {
+               // ensure firing before onload,
+               // maybe late but safe also for iframes
+               document.attachEvent("onreadystatechange", function(){
+                       if ( document.readyState === "complete" ) {
+                               document.detachEvent( "onreadystatechange", arguments.callee );
+                               jQuery.ready();
+                       }
+               });
+
+               // If IE and not an iframe
+               // continually check to see if the document is ready
+               if ( document.documentElement.doScroll && window == window.top ) (function(){
+                       if ( jQuery.isReady ) return;
+
+                       try {
+                               // If IE is used, use the trick by Diego Perini
+                               // http://javascript.nwbox.com/IEContentLoaded/
+                               document.documentElement.doScroll("left");
+                       } catch( error ) {
+                               setTimeout( arguments.callee, 0 );
+                               return;
+                       }
+
+                       // and execute any waiting functions
+                       jQuery.ready();
+               })();
+       }
+
+       // A fallback to window.onload, that will always work
+       jQuery.event.add( window, "load", jQuery.ready );
+}
+
+jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
+       "mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave," +
+       "change,select,submit,keydown,keypress,keyup,error").split(","), function(i, name){
+
+       // Handle event binding
+       jQuery.fn[name] = function(fn){
+               return fn ? this.bind(name, fn) : this.trigger(name);
+       };
+});
+
+// Prevent memory leaks in IE
+// And prevent errors on refresh with events like mouseover in other browsers
+// Window isn't included so as not to unbind existing unload events
+jQuery( window ).bind( 'unload', function(){ 
+       for ( var id in jQuery.cache )
+               // Skip the window
+               if ( id != 1 && jQuery.cache[ id ].handle )
+                       jQuery.event.remove( jQuery.cache[ id ].handle.elem );
+}); 
+(function(){
+
+       jQuery.support = {};
+
+       var root = document.documentElement,
+               script = document.createElement("script"),
+               div = document.createElement("div"),
+               id = "script" + (new Date).getTime();
+
+       div.style.display = "none";
+       div.innerHTML = '   <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>';
+
+       var all = div.getElementsByTagName("*"),
+               a = div.getElementsByTagName("a")[0];
+
+       // Can't get basic test support
+       if ( !all || !all.length || !a ) {
+               return;
+       }
+
+       jQuery.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 you can get all elements in an <object> element
+               // IE 7 always returns no results
+               objectAll: !!div.getElementsByTagName("object")[0]
+                       .getElementsByTagName("*").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 insted)
+               style: /red/.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)
+               opacity: a.style.opacity === "0.5",
+               
+               // Verify style float existence
+               // (IE uses styleFloat instead of cssFloat)
+               cssFloat: !!a.style.cssFloat,
+
+               // Will be defined later
+               scriptEval: false,
+               noCloneEvent: true,
+               boxModel: null
+       };
+       
+       script.type = "text/javascript";
+       try {
+               script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
+       } catch(e){}
+
+       root.insertBefore( script, root.firstChild );
+       
+       // Make sure that the execution of code works by injecting a script
+       // tag with appendChild/createTextNode
+       // (IE doesn't support this, fails, and uses .text instead)
+       if ( window[ id ] ) {
+               jQuery.support.scriptEval = true;
+               delete window[ id ];
+       }
+
+       root.removeChild( script );
+
+       if ( div.attachEvent && div.fireEvent ) {
+               div.attachEvent("onclick", function(){
+                       // Cloning a node shouldn't copy over any
+                       // bound event handlers (IE does this)
+                       jQuery.support.noCloneEvent = false;
+                       div.detachEvent("onclick", arguments.callee);
+               });
+               div.cloneNode(true).fireEvent("onclick");
+       }
+
+       // Figure out if the W3C box model works as expected
+       // document.body must exist before we can do this
+       jQuery(function(){
+               var div = document.createElement("div");
+               div.style.width = div.style.paddingLeft = "1px";
+
+               document.body.appendChild( div );
+               jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
+               document.body.removeChild( div ).style.display = 'none';
+       });
+})();
+
+var styleFloat = jQuery.support.cssFloat ? "cssFloat" : "styleFloat";
+
+jQuery.props = {
+       "for": "htmlFor",
+       "class": "className",
+       "float": styleFloat,
+       cssFloat: styleFloat,
+       styleFloat: styleFloat,
+       readonly: "readOnly",
+       maxlength: "maxLength",
+       cellspacing: "cellSpacing",
+       rowspan: "rowSpan",
+       tabindex: "tabIndex"
+};
+jQuery.fn.extend({
+       // Keep a copy of the old load
+       _load: jQuery.fn.load,
+
+       load: function( url, params, callback ) {
+               if ( typeof url !== "string" )
+                       return this._load( url );
+
+               var off = url.indexOf(" ");
+               if ( off >= 0 ) {
+                       var selector = url.slice(off, url.length);
+                       url = url.slice(0, off);
+               }
+
+               // Default to a GET request
+               var type = "GET";
+
+               // If the second parameter was provided
+               if ( params )
+                       // If it's a function
+                       if ( jQuery.isFunction( params ) ) {
+                               // We assume that it's the callback
+                               callback = params;
+                               params = null;
+
+                       // Otherwise, build a param string
+                       } else if( typeof params === "object" ) {
+                               params = jQuery.param( params );
+                               type = "POST";
+                       }
+
+               var self = this;
+
+               // Request the remote document
+               jQuery.ajax({
+                       url: url,
+                       type: type,
+                       dataType: "html",
+                       data: params,
+                       complete: function(res, status){
+                               // If successful, inject the HTML into all the matched elements
+                               if ( status == "success" || status == "notmodified" )
+                                       // 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(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
+
+                                                       // Locate the specified elements
+                                                       .find(selector) :
+
+                                               // If not, just inject the full result
+                                               res.responseText );
+
+                               if( callback )
+                                       self.each( callback, [res.responseText, status, res] );
+                       }
+               });
+               return this;
+       },
+
+       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 || /select|textarea/i.test(this.nodeName) ||
+                                       /text|hidden|password|search/i.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};
+                                       }) :
+                                       {name: elem.name, value: val};
+               }).get();
+       }
+});
+
+// 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.bind(o, f);
+       };
+});
+
+var jsc = now();
+
+jQuery.extend({
+  
+       get: function( url, data, callback, type ) {
+               // shift arguments if data argument was ommited
+               if ( jQuery.isFunction( data ) ) {
+                       callback = data;
+                       data = null;
+               }
+
+               return jQuery.ajax({
+                       type: "GET",
+                       url: url,
+                       data: data,
+                       success: callback,
+                       dataType: type
+               });
+       },
+
+       getScript: function( url, callback ) {
+               return jQuery.get(url, null, callback, "script");
+       },
+
+       getJSON: function( url, data, callback ) {
+               return jQuery.get(url, data, callback, "json");
+       },
+
+       post: function( url, data, callback, type ) {
+               if ( jQuery.isFunction( data ) ) {
+                       callback = data;
+                       data = {};
+               }
+
+               return jQuery.ajax({
+                       type: "POST",
+                       url: url,
+                       data: data,
+                       success: callback,
+                       dataType: type
+               });
+       },
+
+       ajaxSetup: function( settings ) {
+               jQuery.extend( jQuery.ajaxSettings, settings );
+       },
+
+       ajaxSettings: {
+               url: location.href,
+               global: true,
+               type: "GET",
+               contentType: "application/x-www-form-urlencoded",
+               processData: true,
+               async: true,
+               /*
+               timeout: 0,
+               data: null,
+               username: null,
+               password: null,
+               */
+               // Create the request object; Microsoft failed to properly
+               // implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
+               // This function can be overriden by calling jQuery.ajaxSetup
+               xhr:function(){
+                       return window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
+               },
+               accepts: {
+                       xml: "application/xml, text/xml",
+                       html: "text/html",
+                       script: "text/javascript, application/javascript",
+                       json: "application/json, text/javascript",
+                       text: "text/plain",
+                       _default: "*/*"
+               }
+       },
+
+       // Last-Modified header cache for next request
+       lastModified: {},
+
+       ajax: function( s ) {
+               // Extend the settings, but re-extend 's' so that it can be
+               // checked again later (in the test suite, specifically)
+               s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
+
+               var jsonp, jsre = /=\?(&|$)/g, status, data,
+                       type = s.type.toUpperCase();
+
+               // convert data if not already a string
+               if ( s.data && s.processData && typeof s.data !== "string" )
+                       s.data = jQuery.param(s.data);
+
+               // Handle JSONP Parameter Callbacks
+               if ( s.dataType == "jsonp" ) {
+                       if ( type == "GET" ) {
+                               if ( !s.url.match(jsre) )
+                                       s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
+                       } else if ( !s.data || !s.data.match(jsre) )
+                               s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
+                       s.dataType = "json";
+               }
+
+               // Build temporary JSONP function
+               if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
+                       jsonp = "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 ] = function(tmp){
+                               data = tmp;
+                               success();
+                               complete();
+                               // Garbage collect
+                               window[ jsonp ] = undefined;
+                               try{ delete window[ jsonp ]; } catch(e){}
+                               if ( head )
+                                       head.removeChild( script );
+                       };
+               }
+
+               if ( s.dataType == "script" && s.cache == null )
+                       s.cache = false;
+
+               if ( s.cache === false && type == "GET" ) {
+                       var ts = now();
+                       // try replacing _= if it is there
+                       var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
+                       // if nothing was replaced, add timestamp to the end
+                       s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
+               }
+
+               // If data is available, append data to url for get requests
+               if ( s.data && type == "GET" ) {
+                       s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
+
+                       // IE likes to send both get and post data, prevent this
+                       s.data = null;
+               }
+
+               // Watch for a new set of requests
+               if ( s.global && ! jQuery.active++ )
+                       jQuery.event.trigger( "ajaxStart" );
+
+               // Matches an absolute URL, and saves the domain
+               var parts = /^(\w+:)?\/\/([^\/?#]+)/.exec( s.url );
+
+               // If we're requesting a remote document
+               // and trying to load JSON or Script with a GET
+               if ( s.dataType == "script" && type == "GET" && parts
+                       && ( parts[1] && parts[1] != location.protocol || parts[2] != location.host )){
+
+                       var head = document.getElementsByTagName("head")[0];
+                       var script = document.createElement("script");
+                       script.src = s.url;
+                       if (s.scriptCharset)
+                               script.charset = s.scriptCharset;
+
+                       // Handle Script loading
+                       if ( !jsonp ) {
+                               var done = false;
+
+                               // Attach handlers for all browsers
+                               script.onload = script.onreadystatechange = function(){
+                                       if ( !done && (!this.readyState ||
+                                                       this.readyState == "loaded" || this.readyState == "complete") ) {
+                                               done = true;
+                                               success();
+                                               complete();
+
+                                               // Handle memory leak in IE
+                                               script.onload = script.onreadystatechange = null;
+                                               head.removeChild( script );
+                                       }
+                               };
+                       }
+
+                       head.appendChild(script);
+
+                       // We handle everything using the script element injection
+                       return undefined;
+               }
+
+               var requestDone = false;
+
+               // Create the request object
+               var xhr = s.xhr();
+
+               // Open the socket
+               // Passing null username, generates a login popup on Opera (#2865)
+               if( s.username )
+                       xhr.open(type, s.url, s.async, s.username, s.password);
+               else
+                       xhr.open(type, s.url, s.async);
+
+               // Need an extra try/catch for cross domain requests in Firefox 3
+               try {
+                       // Set the correct header, if data is being sent
+                       if ( s.data )
+                               xhr.setRequestHeader("Content-Type", s.contentType);
+
+                       // Set the If-Modified-Since header, if ifModified mode.
+                       if ( s.ifModified )
+                               xhr.setRequestHeader("If-Modified-Since",
+                                       jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
+
+                       // Set header so the called script knows that it's an XMLHttpRequest
+                       xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
+
+                       // Set the Accepts header for the server, depending on the dataType
+                       xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
+                               s.accepts[ s.dataType ] + ", */*" :
+                               s.accepts._default );
+               } catch(e){}
+
+               // Allow custom headers/mimetypes and early abort
+               if ( s.beforeSend && s.beforeSend(xhr, s) === false ) {
+                       // Handle the global AJAX counter
+                       if ( s.global && ! --jQuery.active )
+                               jQuery.event.trigger( "ajaxStop" );
+                       // close opended socket
+                       xhr.abort();
+                       return false;
+               }
+
+               if ( s.global )
+                       jQuery.event.trigger("ajaxSend", [xhr, s]);
+
+               // Wait for a response to come back
+               var onreadystatechange = function(isTimeout){
+                       // The request was aborted, clear the interval and decrement jQuery.active
+                       if (xhr.readyState == 0) {
+                               if (ival) {
+                                       // clear poll interval
+                                       clearInterval(ival);
+                                       ival = null;
+                                       // Handle the global AJAX counter
+                                       if ( s.global && ! --jQuery.active )
+                                               jQuery.event.trigger( "ajaxStop" );
+                               }
+                       // The transfer is complete and the data is available, or the request timed out
+                       } else if ( !requestDone && xhr && (xhr.readyState == 4 || isTimeout == "timeout") ) {
+                               requestDone = true;
+
+                               // clear poll interval
+                               if (ival) {
+                                       clearInterval(ival);
+                                       ival = null;
+                               }
+
+                               status = isTimeout == "timeout" ? "timeout" :
+                                       !jQuery.httpSuccess( xhr ) ? "error" :
+                                       s.ifModified && jQuery.httpNotModified( xhr, s.url ) ? "notmodified" :
+                                       "success";
+
+                               if ( status == "success" ) {
+                                       // Watch for, and catch, XML document parse errors
+                                       try {
+                                               // process the data (runs the xml through httpData regardless of callback)
+                                               data = jQuery.httpData( xhr, s.dataType, s );
+                                       } catch(e) {
+                                               status = "parsererror";
+                                       }
+                               }
+
+                               // Make sure that the request was successful or notmodified
+                               if ( status == "success" ) {
+                                       // Cache Last-Modified header, if ifModified mode.
+                                       var modRes;
+                                       try {
+                                               modRes = xhr.getResponseHeader("Last-Modified");
+                                       } catch(e) {} // swallow exception thrown by FF if header is not available
+
+                                       if ( s.ifModified && modRes )
+                                               jQuery.lastModified[s.url] = modRes;
+
+                                       // JSONP handles its own success callback
+                                       if ( !jsonp )
+                                               success();
+                               } else
+                                       jQuery.handleError(s, xhr, status);
+
+                               // Fire the complete handlers
+                               complete();
+
+                               if ( isTimeout )
+                                       xhr.abort();
+
+                               // Stop memory leaks
+                               if ( s.async )
+                                       xhr = null;
+                       }
+               };
+
+               if ( s.async ) {
+                       // don't attach the handler to the request, just poll it instead
+                       var ival = setInterval(onreadystatechange, 13);
+
+                       // Timeout checker
+                       if ( s.timeout > 0 )
+                               setTimeout(function(){
+                                       // Check to see if the request is still happening
+                                       if ( xhr && !requestDone )
+                                               onreadystatechange( "timeout" );
+                               }, s.timeout);
+               }
+
+               // Send the data
+               try {
+                       xhr.send(s.data);
+               } catch(e) {
+                       jQuery.handleError(s, xhr, null, e);
+               }
+
+               // firefox 1.5 doesn't fire statechange for sync requests
+               if ( !s.async )
+                       onreadystatechange();
+
+               function success(){
+                       // If a local callback was specified, fire it and pass it the data
+                       if ( s.success )
+                               s.success( data, status );
+
+                       // Fire the global callback
+                       if ( s.global )
+                               jQuery.event.trigger( "ajaxSuccess", [xhr, s] );
+               }
+
+               function complete(){
+                       // Process result
+                       if ( s.complete )
+                               s.complete(xhr, status);
+
+                       // The request was completed
+                       if ( s.global )
+                               jQuery.event.trigger( "ajaxComplete", [xhr, s] );
+
+                       // Handle the global AJAX counter
+                       if ( s.global && ! --jQuery.active )
+                               jQuery.event.trigger( "ajaxStop" );
+               }
+
+               // return XMLHttpRequest to allow aborting the request etc.
+               return xhr;
+       },
+
+       handleError: function( s, xhr, status, e ) {
+               // If a local callback was specified, fire it
+               if ( s.error ) s.error( xhr, status, e );
+
+               // Fire the global callback
+               if ( s.global )
+                       jQuery.event.trigger( "ajaxError", [xhr, s, e] );
+       },
+
+       // Counter for holding the number of active queries
+       active: 0,
+
+       // Determines if an XMLHttpRequest was successful or not
+       httpSuccess: function( xhr ) {
+               try {
+                       // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
+                       return !xhr.status && location.protocol == "file:" ||
+                               ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status == 304 || xhr.status == 1223;
+               } catch(e){}
+               return false;
+       },
+
+       // Determines if an XMLHttpRequest returns NotModified
+       httpNotModified: function( xhr, url ) {
+               try {
+                       var xhrRes = xhr.getResponseHeader("Last-Modified");
+
+                       // Firefox always returns 200. check Last-Modified date
+                       return xhr.status == 304 || xhrRes == jQuery.lastModified[url];
+               } catch(e){}
+               return false;
+       },
+
+       httpData: function( xhr, type, s ) {
+               var ct = xhr.getResponseHeader("content-type"),
+                       xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0,
+                       data = xml ? xhr.responseXML : xhr.responseText;
+
+               if ( xml && data.documentElement.tagName == "parsererror" )
+                       throw "parsererror";
+                       
+               // Allow a pre-filtering function to sanitize the response
+               // s != null is checked to keep backwards compatibility
+               if( s && s.dataFilter )
+                       data = s.dataFilter( data, type );
+
+               // The filter can actually parse the response
+               if( typeof data === "string" ){
+
+                       // If the type is "script", eval it in global context
+                       if ( type == "script" )
+                               jQuery.globalEval( data );
+
+                       // Get the JavaScript object, if JSON is used.
+                       if ( type == "json" )
+                               data = window["eval"]("(" + data + ")");
+               }
+               
+               return data;
+       },
+
+       // Serialize an array of form elements or a set of
+       // key/values into a query string
+       param: function( a ) {
+               var s = [ ];
+
+               function add( key, value ){
+                       s[ s.length ] = encodeURIComponent(key) + '=' + encodeURIComponent(value);
+               };
+
+               // If an array was passed in, assume that it is an array
+               // of form elements
+               if ( jQuery.isArray(a) || a.jquery )
+                       // Serialize the form elements
+                       jQuery.each( a, function(){
+                               add( this.name, this.value );
+                       });
+
+               // Otherwise, assume that it's an object of key/value pairs
+               else
+                       // Serialize the key/values
+                       for ( var j in a )
+                               // If the value is an array then the key names need to be repeated
+                               if ( jQuery.isArray(a[j]) )
+                                       jQuery.each( a[j], function(){
+                                               add( j, this );
+                                       });
+                               else
+                                       add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] );
+
+               // Return the resulting serialization
+               return s.join("&").replace(/%20/g, "+");
+       }
+
+});
+var elemdisplay = {},
+       timerId,
+       fxAttrs = [
+               // height animations
+               [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
+               // width animations
+               [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
+               // opacity animations
+               [ "opacity" ]
+       ];
+
+function genFx( type, num ){
+       var obj = {};
+       jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function(){
+               obj[ this ] = type;
+       });
+       return obj;
+}
+
+jQuery.fn.extend({
+       show: function(speed,callback){
+               if ( speed ) {
+                       return this.animate( genFx("show", 3), speed, callback);
+               } else {
+                       for ( var i = 0, l = this.length; i < l; i++ ){
+                               var old = jQuery.data(this[i], "olddisplay");
+                               
+                               this[i].style.display = old || "";
+                               
+                               if ( jQuery.css(this[i], "display") === "none" ) {
+                                       var tagName = this[i].tagName, display;
+                                       
+                                       if ( elemdisplay[ tagName ] ) {
+                                               display = elemdisplay[ tagName ];
+                                       } else {
+                                               var elem = jQuery("<" + tagName + " />").appendTo("body");
+                                               
+                                               display = elem.css("display");
+                                               if ( display === "none" )
+                                                       display = "block";
+                                               
+                                               elem.remove();
+                                               
+                                               elemdisplay[ tagName ] = display;
+                                       }
+                                       
+                                       jQuery.data(this[i], "olddisplay", display);
+                               }
+                       }
+
+                       // Set the display of the elements in a second loop
+                       // to avoid the constant reflow
+                       for ( var i = 0, l = this.length; i < l; i++ ){
+                               this[i].style.display = jQuery.data(this[i], "olddisplay") || "";
+                       }
+                       
+                       return this;
+               }
+       },
+
+       hide: function(speed,callback){
+               if ( speed ) {
+                       return this.animate( genFx("hide", 3), speed, callback);
+               } else {
+                       for ( var i = 0, l = this.length; i < l; i++ ){
+                               var old = jQuery.data(this[i], "olddisplay");
+                               if ( !old && old !== "none" )
+                                       jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display"));
+                       }
+
+                       // Set the display of the elements in a second loop
+                       // to avoid the constant reflow
+                       for ( var i = 0, l = this.length; i < l; i++ ){
+                               this[i].style.display = "none";
+                       }
+
+                       return this;
+               }
+       },
+
+       // Save the old toggle function
+       _toggle: jQuery.fn.toggle,
+
+       toggle: function( fn, fn2 ){
+               var bool = typeof fn === "boolean";
+
+               return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
+                       this._toggle.apply( this, arguments ) :
+                       fn == null || bool ?
+                               this.each(function(){
+                                       var state = bool ? fn : jQuery(this).is(":hidden");
+                                       jQuery(this)[ state ? "show" : "hide" ]();
+                               }) :
+                               this.animate(genFx("toggle", 3), fn, fn2);
+       },
+
+       fadeTo: function(speed,to,callback){
+               return this.animate({opacity: to}, speed, callback);
+       },
+
+       animate: function( prop, speed, easing, callback ) {
+               var optall = jQuery.speed(speed, easing, callback);
+
+               return this[ optall.queue === false ? "each" : "queue" ](function(){
+               
+                       var opt = jQuery.extend({}, optall), p,
+                               hidden = this.nodeType == 1 && jQuery(this).is(":hidden"),
+                               self = this;
+       
+                       for ( p in prop ) {
+                               if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
+                                       return opt.complete.call(this);
+
+                               if ( ( p == "height" || p == "width" ) && this.style ) {
+                                       // Store display property
+                                       opt.display = jQuery.css(this, "display");
+
+                                       // Make sure that nothing sneaks out
+                                       opt.overflow = this.style.overflow;
+                               }
+                       }
+
+                       if ( opt.overflow != null )
+                               this.style.overflow = "hidden";
+
+                       opt.curAnim = jQuery.extend({}, prop);
+
+                       jQuery.each( prop, function(name, val){
+                               var e = new jQuery.fx( self, opt, name );
+
+                               if ( /toggle|show|hide/.test(val) )
+                                       e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
+                               else {
+                                       var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
+                                               start = e.cur(true) || 0;
+
+                                       if ( parts ) {
+                                               var end = parseFloat(parts[2]),
+                                                       unit = parts[3] || "px";
+
+                                               // We need to compute starting value
+                                               if ( unit != "px" ) {
+                                                       self.style[ name ] = (end || 1) + unit;
+                                                       start = ((end || 1) / e.cur(true)) * start;
+                                                       self.style[ name ] = start + unit;
+                                               }
+
+                                               // If a +=/-= token was provided, we're doing a relative animation
+                                               if ( parts[1] )
+                                                       end = ((parts[1] == "-=" ? -1 : 1) * end) + start;
+
+                                               e.custom( start, end, unit );
+                                       } else
+                                               e.custom( start, val, "" );
+                               }
+                       });
+
+                       // For JS strict compliance
+                       return true;
+               });
+       },
+
+       stop: function(clearQueue, gotoEnd){
+               var timers = jQuery.timers;
+
+               if (clearQueue)
+                       this.queue([]);
+
+               this.each(function(){
+                       // go in reverse order so anything added to the queue during the loop is ignored
+                       for ( var i = timers.length - 1; i >= 0; i-- )
+                               if ( timers[i].elem == this ) {
+                                       if (gotoEnd)
+                                               // force the next step to be the last
+                                               timers[i](true);
+                                       timers.splice(i, 1);
+                               }
+               });
+
+               // start the next in the queue if the last step wasn't forced
+               if (!gotoEnd)
+                       this.dequeue();
+
+               return this;
+       }
+
+});
+
+// Generate shortcuts for custom animations
+jQuery.each({
+       slideDown: genFx("show", 1),
+       slideUp: genFx("hide", 1),
+       slideToggle: genFx("toggle", 1),
+       fadeIn: { opacity: "show" },
+       fadeOut: { opacity: "hide" }
+}, function( name, props ){
+       jQuery.fn[ name ] = function( speed, callback ){
+               return this.animate( props, speed, callback );
+       };
+});
+
+jQuery.extend({
+
+       speed: function(speed, easing, fn) {
+               var opt = typeof speed === "object" ? 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 :
+                       jQuery.fx.speeds[opt.duration] || jQuery.fx.speeds._default;
+
+               // Queueing
+               opt.old = opt.complete;
+               opt.complete = function(){
+                       if ( opt.queue !== false )
+                               jQuery(this).dequeue();
+                       if ( jQuery.isFunction( opt.old ) )
+                               opt.old.call( this );
+               };
+
+               return opt;
+       },
+
+       easing: {
+               linear: function( p, n, firstNum, diff ) {
+                       return firstNum + diff * p;
+               },
+               swing: function( p, n, firstNum, diff ) {
+                       return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
+               }
+       },
+
+       timers: [],
+
+       fx: function( elem, options, prop ){
+               this.options = options;
+               this.elem = elem;
+               this.prop = prop;
+
+               if ( !options.orig )
+                       options.orig = {};
+       }
+
+});
+
+jQuery.fx.prototype = {
+
+       // Simple function for setting a style value
+       update: function(){
+               if ( this.options.step )
+                       this.options.step.call( this.elem, this.now, this );
+
+               (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
+
+               // Set display property to block for height/width animations
+               if ( ( this.prop == "height" || this.prop == "width" ) && this.elem.style )
+                       this.elem.style.display = "block";
+       },
+
+       // Get the current size
+       cur: function(force){
+               if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) )
+                       return this.elem[ this.prop ];
+
+               var r = parseFloat(jQuery.css(this.elem, this.prop, force));
+               return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
+       },
+
+       // Start an animation from one number to another
+       custom: function(from, to, unit){
+               this.startTime = now();
+               this.start = from;
+               this.end = to;
+               this.unit = unit || this.unit || "px";
+               this.now = this.start;
+               this.pos = this.state = 0;
+
+               var self = this;
+               function t(gotoEnd){
+                       return self.step(gotoEnd);
+               }
+
+               t.elem = this.elem;
+
+               if ( t() && jQuery.timers.push(t) && !timerId ) {
+                       timerId = setInterval(function(){
+                               var timers = jQuery.timers;
+
+                               for ( var i = 0; i < timers.length; i++ )
+                                       if ( !timers[i]() )
+                                               timers.splice(i--, 1);
+
+                               if ( !timers.length ) {
+                                       clearInterval( timerId );
+                                       timerId = undefined;
+                               }
+                       }, 13);
+               }
+       },
+
+       // Simple 'show' function
+       show: function(){
+               // Remember where we started, so that we can go back to it later
+               this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
+               this.options.show = true;
+
+               // Begin the animation
+               // Make sure that we start at a small width/height to avoid any
+               // flash of content
+               this.custom(this.prop == "width" || this.prop == "height" ? 1 : 0, this.cur());
+
+               // Start by showing the element
+               jQuery(this.elem).show();
+       },
+
+       // Simple 'hide' function
+       hide: function(){
+               // Remember where we started, so that we can go back to it later
+               this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
+               this.options.hide = true;
+
+               // Begin the animation
+               this.custom(this.cur(), 0);
+       },
+
+       // Each step of an animation
+       step: function(gotoEnd){
+               var t = now();
+
+               if ( gotoEnd || t >= this.options.duration + this.startTime ) {
+                       this.now = this.end;
+                       this.pos = this.state = 1;
+                       this.update();
+
+                       this.options.curAnim[ this.prop ] = true;
+
+                       var done = true;
+                       for ( var i in this.options.curAnim )
+                               if ( this.options.curAnim[i] !== true )
+                                       done = false;
+
+                       if ( done ) {
+                               if ( this.options.display != null ) {
+                                       // Reset the overflow
+                                       this.elem.style.overflow = this.options.overflow;
+
+                                       // Reset the display
+                                       this.elem.style.display = this.options.display;
+                                       if ( jQuery.css(this.elem, "display") == "none" )
+                                               this.elem.style.display = "block";
+                               }
+
+                               // Hide the element if the "hide" operation was done
+                               if ( this.options.hide )
+                                       jQuery(this.elem).hide();
+
+                               // Reset the properties, if the item has been hidden or shown
+                               if ( this.options.hide || this.options.show )
+                                       for ( var p in this.options.curAnim )
+                                               jQuery.attr(this.elem.style, p, this.options.orig[p]);
+                                       
+                               // Execute the complete function
+                               this.options.complete.call( this.elem );
+                       }
+
+                       return false;
+               } else {
+                       var n = t - this.startTime;
+                       this.state = n / this.options.duration;
+
+                       // Perform the easing function, defaults to swing
+                       this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
+                       this.now = this.start + ((this.end - this.start) * this.pos);
+
+                       // Perform the next step of the animation
+                       this.update();
+               }
+
+               return true;
+       }
+
+};
+
+jQuery.extend( jQuery.fx, {
+       speeds:{
+               slow: 600,
+               fast: 200,
+               // Default speed
+               _default: 400
+       },
+       step: {
+
+               opacity: function(fx){
+                       jQuery.attr(fx.elem.style, "opacity", fx.now);
+               },
+
+               _default: function(fx){
+                       if ( fx.elem.style && fx.elem.style[ fx.prop ] != null )
+                               fx.elem.style[ fx.prop ] = fx.now + fx.unit;
+                       else
+                               fx.elem[ fx.prop ] = fx.now;
+               }
+       }
+});
+if ( document.documentElement["getBoundingClientRect"] )
+       jQuery.fn.offset = function() {
+               if ( !this[0] ) return { top: 0, left: 0 };
+               if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
+               var box  = this[0].getBoundingClientRect(), doc = this[0].ownerDocument, body = doc.body, docElem = doc.documentElement,
+                       clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,
+                       top  = box.top  + (self.pageYOffset || jQuery.boxModel && docElem.scrollTop  || body.scrollTop ) - clientTop,
+                       left = box.left + (self.pageXOffset || jQuery.boxModel && docElem.scrollLeft || body.scrollLeft) - clientLeft;
+               return { top: top, left: left };
+       };
+else 
+       jQuery.fn.offset = function() {
+               if ( !this[0] ) return { top: 0, left: 0 };
+               if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
+               jQuery.offset.initialized || jQuery.offset.initialize();
+
+               var elem = this[0], offsetParent = elem.offsetParent, prevOffsetParent = elem,
+                       doc = elem.ownerDocument, computedStyle, docElem = doc.documentElement,
+                       body = doc.body, defaultView = doc.defaultView,
+                       prevComputedStyle = defaultView.getComputedStyle(elem, null),
+                       top = elem.offsetTop, left = elem.offsetLeft;
+
+               while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
+                       computedStyle = defaultView.getComputedStyle(elem, null);
+                       top -= elem.scrollTop, left -= elem.scrollLeft;
+                       if ( elem === offsetParent ) {
+                               top += elem.offsetTop, left += elem.offsetLeft;
+                               if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.tagName)) )
+                                       top  += parseInt( computedStyle.borderTopWidth,  10) || 0,
+                                       left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
+                               prevOffsetParent = offsetParent, offsetParent = elem.offsetParent;
+                       }
+                       if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" )
+                               top  += parseInt( computedStyle.borderTopWidth,  10) || 0,
+                               left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
+                       prevComputedStyle = computedStyle;
+               }
+
+               if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" )
+                       top  += body.offsetTop,
+                       left += body.offsetLeft;
+
+               if ( prevComputedStyle.position === "fixed" )
+                       top  += Math.max(docElem.scrollTop, body.scrollTop),
+                       left += Math.max(docElem.scrollLeft, body.scrollLeft);
+
+               return { top: top, left: left };
+       };
+
+jQuery.offset = {
+       initialize: function() {
+               if ( this.initialized ) return;
+               var body = document.body, container = document.createElement('div'), innerDiv, checkDiv, table, td, rules, prop, bodyMarginTop = body.style.marginTop,
+                       html = '<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>';
+
+               rules = { position: 'absolute', top: 0, left: 0, margin: 0, border: 0, width: '1px', height: '1px', visibility: 'hidden' };
+               for ( prop in rules ) container.style[prop] = rules[prop];
+
+               container.innerHTML = html;
+               body.insertBefore(container, body.firstChild);
+               innerDiv = container.firstChild, checkDiv = innerDiv.firstChild, td = innerDiv.nextSibling.firstChild.firstChild;
+
+               this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
+               this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
+
+               innerDiv.style.overflow = 'hidden', innerDiv.style.position = 'relative';
+               this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
+
+               body.style.marginTop = '1px';
+               this.doesNotIncludeMarginInBodyOffset = (body.offsetTop === 0);
+               body.style.marginTop = bodyMarginTop;
+
+               body.removeChild(container);
+               this.initialized = true;
+       },
+
+       bodyOffset: function(body) {
+               jQuery.offset.initialized || jQuery.offset.initialize();
+               var top = body.offsetTop, left = body.offsetLeft;
+               if ( jQuery.offset.doesNotIncludeMarginInBodyOffset )
+                       top  += parseInt( jQuery.curCSS(body, 'marginTop',  true), 10 ) || 0,
+                       left += parseInt( jQuery.curCSS(body, 'marginLeft', true), 10 ) || 0;
+               return { top: top, left: left };
+       }
+};
+
+
+jQuery.fn.extend({
+       position: function() {
+               var left = 0, top = 0, results;
+
+               if ( this[0] ) {
+                       // Get *real* offsetParent
+                       var offsetParent = this.offsetParent(),
+
+                       // Get correct offsets
+                       offset       = this.offset(),
+                       parentOffset = /^body|html$/i.test(offsetParent[0].tagName) ? { 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  -= num( this, 'marginTop'  );
+                       offset.left -= num( this, 'marginLeft' );
+
+                       // Add offsetParent borders
+                       parentOffset.top  += num( offsetParent, 'borderTopWidth'  );
+                       parentOffset.left += num( offsetParent, 'borderLeftWidth' );
+
+                       // Subtract the two offsets
+                       results = {
+                               top:  offset.top  - parentOffset.top,
+                               left: offset.left - parentOffset.left
+                       };
+               }
+
+               return results;
+       },
+
+       offsetParent: function() {
+               var offsetParent = this[0].offsetParent || document.body;
+               while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && jQuery.css(offsetParent, 'position') == 'static') )
+                       offsetParent = offsetParent.offsetParent;
+               return jQuery(offsetParent);
+       }
+});
+
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( ['Left', 'Top'], function(i, name) {
+       var method = 'scroll' + name;
+       
+       jQuery.fn[ method ] = function(val) {
+               if (!this[0]) return null;
+
+               return val !== undefined ?
+
+                       // Set the scroll offset
+                       this.each(function() {
+                               this == window || this == document ?
+                                       window.scrollTo(
+                                               !i ? val : jQuery(window).scrollLeft(),
+                                                i ? val : jQuery(window).scrollTop()
+                                       ) :
+                                       this[ method ] = val;
+                       }) :
+
+                       // Return the scroll offset
+                       this[0] == window || this[0] == document ?
+                               self[ i ? 'pageYOffset' : 'pageXOffset' ] ||
+                                       jQuery.boxModel && document.documentElement[ method ] ||
+                                       document.body[ method ] :
+                               this[0][ method ];
+       };
+});
+// Create innerHeight, innerWidth, outerHeight and outerWidth methods
+jQuery.each([ "Height", "Width" ], function(i, name){
+
+       var tl = i ? "Left"  : "Top",  // top or left
+               br = i ? "Right" : "Bottom", // bottom or right
+               lower = name.toLowerCase();
+
+       // innerHeight and innerWidth
+       jQuery.fn["inner" + name] = function(){
+               return this[0] ?
+                       jQuery.css( this[0], lower, false, "padding" ) :
+                       null;
+       };
+
+       // outerHeight and outerWidth
+       jQuery.fn["outer" + name] = function(margin) {
+               return this[0] ?
+                       jQuery.css( this[0], lower, false, margin ? "margin" : "border" ) :
+                       null;
+       };
+       
+       var type = name.toLowerCase();
+
+       jQuery.fn[ type ] = function( size ) {
+               // Get window width or height
+               return this[0] == window ?
+                       // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
+                       document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] ||
+                       document.body[ "client" + name ] :
+
+                       // Get document width or height
+                       this[0] == document ?
+                               // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
+                               Math.max(
+                                       document.documentElement["client" + name],
+                                       document.body["scroll" + name], document.documentElement["scroll" + name],
+                                       document.body["offset" + name], document.documentElement["offset" + name]
+                               ) :
+
+                               // Get or set width or height on the element
+                               size === undefined ?
+                                       // Get width or height on the element
+                                       (this.length ? jQuery.css( this[0], type ) : null) :
+
+                                       // Set the width or height on the element (default to pixels if value is unitless)
+                                       this.css( type, typeof size === "string" ? size : size + "px" );
+       };
+
+});
+})();
+/*
+ * jQuery UI 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI
+ */
+;jQuery.ui || (function($) {
+
+var _remove = $.fn.remove,
+       isFF2 = $.browser.mozilla && (parseFloat($.browser.version) < 1.9);
+
+//Helper functions and ui object
+$.ui = {
+       version: "1.7.2",
+
+       // $.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);
+                               }
+                       }
+               }
+       },
+
+       contains: function(a, b) {
+               return document.compareDocumentPosition
+                       ? a.compareDocumentPosition(b) & 16
+                       : a !== b && a.contains(b);
+       },
+
+       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;
+       },
+
+       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);
+       },
+
+       keyCode: {
+               BACKSPACE: 8,
+               CAPS_LOCK: 20,
+               COMMA: 188,
+               CONTROL: 17,
+               DELETE: 46,
+               DOWN: 40,
+               END: 35,
+               ENTER: 13,
+               ESCAPE: 27,
+               HOME: 36,
+               INSERT: 45,
+               LEFT: 37,
+               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
+       }
+};
+
+// WAI-ARIA normalization
+if (isFF2) {
+       var attr = $.attr,
+               removeAttr = $.fn.removeAttr,
+               ariaNS = "http://www.w3.org/2005/07/aaa",
+               ariaState = /^aria-/,
+               ariaRole = /^wairole:/;
+
+       $.attr = function(elem, name, value) {
+               var set = value !== undefined;
+
+               return (name == 'role'
+                       ? (set
+                               ? attr.call(this, elem, name, "wairole:" + value)
+                               : (attr.apply(this, arguments) || "").replace(ariaRole, ""))
+                       : (ariaState.test(name)
+                               ? (set
+                                       ? elem.setAttributeNS(ariaNS,
+                                               name.replace(ariaState, "aaa:"), value)
+                                       : attr.call(this, elem, name.replace(ariaState, "aaa:")))
+                               : attr.apply(this, arguments)));
+       };
+
+       $.fn.removeAttr = function(name) {
+               return (ariaState.test(name)
+                       ? this.each(function() {
+                               this.removeAttributeNS(ariaNS, name.replace(ariaState, ""));
+                       }) : removeAttr.call(this, name));
+       };
+}
+
+//jQuery plugins
+$.fn.extend({
+       remove: function() {
+               // Safari has a native remove event which actually removes DOM elements,
+               // so we have to use triggerHandler instead of trigger (#3037).
+               $("*", this).add(this).each(function() {
+                       $(this).triggerHandler("remove");
+               });
+               return _remove.apply(this, arguments );
+       },
+
+       enableSelection: function() {
+               return this
+                       .attr('unselectable', 'off')
+                       .css('MozUserSelect', '')
+                       .unbind('selectstart.ui');
+       },
+
+       disableSelection: function() {
+               return this
+                       .attr('unselectable', 'on')
+                       .css('MozUserSelect', 'none')
+                       .bind('selectstart.ui', function() { return false; });
+       },
+
+       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;
+       }
+});
+
+
+//Additional selectors
+$.extend($.expr[':'], {
+       data: function(elem, i, match) {
+               return !!$.data(elem, match[3]);
+       },
+
+       focusable: function(element) {
+               var nodeName = element.nodeName.toLowerCase(),
+                       tabIndex = $.attr(element, 'tabindex');
+               return (/input|select|textarea|button|object/.test(nodeName)
+                       ? !element.disabled
+                       : 'a' == nodeName || 'area' == nodeName
+                               ? element.href || !isNaN(tabIndex)
+                               : !isNaN(tabIndex))
+                       // the element and all of its ancestors must be visible
+                       // the browser may report that the area is hidden
+                       && !$(element)['area' == nodeName ? 'parents' : 'closest'](':hidden').length;
+       },
+
+       tabbable: function(element) {
+               var tabIndex = $.attr(element, 'tabindex');
+               return (isNaN(tabIndex) || tabIndex >= 0) && $(element).is(':focusable');
+       }
+});
+
+
+// $.widget is a factory to create jQuery plugins
+// taking some boilerplate code out of the plugin code
+function getter(namespace, plugin, method, args) {
+       function getMethods(type) {
+               var methods = $[namespace][plugin][type] || [];
+               return (typeof methods == 'string' ? methods.split(/,?\s+/) : methods);
+       }
+
+       var methods = getMethods('getter');
+       if (args.length == 1 && typeof args[0] == 'string') {
+               methods = methods.concat(getMethods('getterSetter'));
+       }
+       return ($.inArray(method, methods) != -1);
+}
+
+$.widget = function(name, prototype) {
+       var namespace = name.split(".")[0];
+       name = name.split(".")[1];
+
+       // create plugin method
+       $.fn[name] = function(options) {
+               var isMethodCall = (typeof options == 'string'),
+                       args = Array.prototype.slice.call(arguments, 1);
+
+               // prevent calls to internal methods
+               if (isMethodCall && options.substring(0, 1) == '_') {
+                       return this;
+               }
+
+               // handle getter methods
+               if (isMethodCall && getter(namespace, name, options, args)) {
+                       var instance = $.data(this[0], name);
+                       return (instance ? instance[options].apply(instance, args)
+                               : undefined);
+               }
+
+               // handle initialization and non-getter methods
+               return this.each(function() {
+                       var instance = $.data(this, name);
+
+                       // constructor
+                       (!instance && !isMethodCall &&
+                               $.data(this, name, new $[namespace][name](this, options))._init());
+
+                       // method call
+                       (instance && isMethodCall && $.isFunction(instance[options]) &&
+                               instance[options].apply(instance, args));
+               });
+       };
+
+       // create widget constructor
+       $[namespace] = $[namespace] || {};
+       $[namespace][name] = function(element, options) {
+               var self = this;
+
+               this.namespace = namespace;
+               this.widgetName = name;
+               this.widgetEventPrefix = $[namespace][name].eventPrefix || name;
+               this.widgetBaseClass = namespace + '-' + name;
+
+               this.options = $.extend({},
+                       $.widget.defaults,
+                       $[namespace][name].defaults,
+                       $.metadata && $.metadata.get(element)[name],
+                       options);
+
+               this.element = $(element)
+                       .bind('setData.' + name, function(event, key, value) {
+                               if (event.target == element) {
+                                       return self._setData(key, value);
+                               }
+                       })
+                       .bind('getData.' + name, function(event, key) {
+                               if (event.target == element) {
+                                       return self._getData(key);
+                               }
+                       })
+                       .bind('remove', function() {
+                               return self.destroy();
+                       });
+       };
+
+       // add widget prototype
+       $[namespace][name].prototype = $.extend({}, $.widget.prototype, prototype);
+
+       // TODO: merge getter and getterSetter properties from widget prototype
+       // and plugin prototype
+       $[namespace][name].getterSetter = 'option';
+};
+
+$.widget.prototype = {
+       _init: function() {},
+       destroy: function() {
+               this.element.removeData(this.widgetName)
+                       .removeClass(this.widgetBaseClass + '-disabled' + ' ' + this.namespace + '-state-disabled')
+                       .removeAttr('aria-disabled');
+       },
+
+       option: function(key, value) {
+               var options = key,
+                       self = this;
+
+               if (typeof key == "string") {
+                       if (value === undefined) {
+                               return this._getData(key);
+                       }
+                       options = {};
+                       options[key] = value;
+               }
+
+               $.each(options, function(key, value) {
+                       self._setData(key, value);
+               });
+       },
+       _getData: function(key) {
+               return this.options[key];
+       },
+       _setData: function(key, value) {
+               this.options[key] = value;
+
+               if (key == 'disabled') {
+                       this.element
+                               [value ? 'addClass' : 'removeClass'](
+                                       this.widgetBaseClass + '-disabled' + ' ' +
+                                       this.namespace + '-state-disabled')
+                               .attr("aria-disabled", value);
+               }
+       },
+
+       enable: function() {
+               this._setData('disabled', false);
+       },
+       disable: function() {
+               this._setData('disabled', true);
+       },
+
+       _trigger: function(type, event, data) {
+               var callback = this.options[type],
+                       eventName = (type == this.widgetEventPrefix
+                               ? type : this.widgetEventPrefix + type);
+
+               event = $.Event(event);
+               event.type = eventName;
+
+               // copy original event properties over to the new event
+               // this would happen if we could call $.event.fix instead of $.Event
+               // but we don't have a way to force an event to be fixed multiple times
+               if (event.originalEvent) {
+                       for (var i = $.event.props.length, prop; i;) {
+                               prop = $.event.props[--i];
+                               event[prop] = event.originalEvent[prop];
+                       }
+               }
+
+               this.element.trigger(event, data);
+
+               return !($.isFunction(callback) && callback.call(this.element[0], event, data) === false
+                       || event.isDefaultPrevented());
+       }
+};
+
+$.widget.defaults = {
+       disabled: false
+};
+
+
+/** Mouse Interaction Plugin **/
+
+$.ui.mouse = {
+       _mouseInit: function() {
+               var self = this;
+
+               this.element
+                       .bind('mousedown.'+this.widgetName, function(event) {
+                               return self._mouseDown(event);
+                       })
+                       .bind('click.'+this.widgetName, function(event) {
+                               if(self._preventClickEvent) {
+                                       self._preventClickEvent = false;
+                                       event.stopImmediatePropagation();
+                                       return false;
+                               }
+                       });
+
+               // Prevent text selection in IE
+               if ($.browser.msie) {
+                       this._mouseUnselectable = this.element.attr('unselectable');
+                       this.element.attr('unselectable', 'on');
+               }
+
+               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);
+
+               // Restore text selection in IE
+               ($.browser.msie
+                       && this.element.attr('unselectable', this._mouseUnselectable));
+       },
+
+       _mouseDown: function(event) {
+               // don't let more than one widget handle mouseStart
+               // TODO: figure out why we have to use originalEvent
+               event.originalEvent = event.originalEvent || {};
+               if (event.originalEvent.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),
+                       elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(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;
+                       }
+               }
+
+               // 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);
+
+               // preventDefault() is used to prevent the selection of text here -
+               // however, in Safari, this causes select boxes not to be selectable
+               // anymore, so this fix is needed
+               ($.browser.safari || event.preventDefault());
+
+               event.originalEvent.mouseHandled = true;
+               return true;
+       },
+
+       _mouseMove: function(event) {
+               // IE mouseup check - mouseup happened when mouse was out of window
+               if ($.browser.msie && !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;
+                       this._preventClickEvent = (event.target == this._mouseDownEvent.target);
+                       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; }
+};
+
+$.ui.mouse.defaults = {
+       cancel: null,
+       distance: 1,
+       delay: 0
+};
+
+})(jQuery);
+/*
+ * jQuery UI Draggable 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Draggables
+ *
+ * Depends:
+ *     ui.core.js
+ */
+(function($) {
+
+$.widget("ui.draggable", $.extend({}, $.ui.mouse, {
+
+       _init: 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();
+       },
+
+       _mouseCapture: function(event) {
+
+               var o = this.options;
+
+               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;
+
+               return true;
+
+       },
+
+       _mouseStart: function(event) {
+
+               var o = this.options;
+
+               //Create and append the visible helper
+               this.helper = this._createHelper(event);
+
+               //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.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._generatePosition(event);
+               this.originalPageX = event.pageX;
+               this.originalPageY = event.pageY;
+
+               //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
+               if(o.cursorAt)
+                       this._adjustOffsetFromHelper(o.cursorAt);
+
+               //Set a containment if given in the options
+               if(o.containment)
+                       this._setContainment();
+
+               //Call plugins and callbacks
+               this._trigger("start", event);
+
+               //Recache the helper size
+               this._cacheHelperProportions();
+
+               //Prepare the droppable offsets
+               if ($.ui.ddmanager && !o.dropBehaviour)
+                       $.ui.ddmanager.prepareOffsets(this, event);
+
+               this.helper.addClass("ui-draggable-dragging");
+               this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
+               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();
+                       this._trigger('drag', event, ui);
+                       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((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() {
+                               self._trigger("stop", event);
+                               self._clear();
+                       });
+               } else {
+                       this._trigger("stop", event);
+                       this._clear();
+               }
+
+               return false;
+       },
+
+       _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() : 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(obj.left != undefined) this.offset.click.left = obj.left + this.margins.left;
+               if(obj.right != undefined) this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
+               if(obj.top != undefined) this.offset.click.top = obj.top + this.margins.top;
+               if(obj.bottom != undefined) 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)
+               };
+       },
+
+       _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) && o.containment.constructor != Array) {
+                       var ce = $(o.containment)[0]; if(!ce) return;
+                       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
+                       ];
+               } 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 && 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() ))
+                       )
+               };
+
+       },
+
+       _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,
+                       absolutePosition: this.positionAbs, //deprecated
+                       offset: this.positionAbs
+               };
+       }
+
+}));
+
+$.extend($.ui.draggable, {
+       version: "1.7.2",
+       eventPrefix: "drag",
+       defaults: {
+               addClasses: true,
+               appendTo: "parent",
+               axis: false,
+               cancel: ":input,option",
+               connectToSortable: false,
+               containment: false,
+               cursor: "auto",
+               cursorAt: false,
+               delay: 0,
+               distance: 1,
+               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
+       }
+});
+
+$.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._refreshItems();       //Do a one-time refresh at start to refresh the containerCache
+                               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().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", "iframeFix", {
+       start: function(event, ui) {
+               var o = $(this).data('draggable').options;
+               $(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");
+               });
+       },
+       stop: function(event, ui) {
+               $("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers
+       }
+});
+
+$.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.group)).sort(function(a,b) {
+                       return (parseInt($(a).css("zIndex"),10) || o.stack.min) - (parseInt($(b).css("zIndex"),10) || o.stack.min);
+               });
+
+               $(group).each(function(i) {
+                       this.style.zIndex = o.stack.min + i;
+               });
+
+               this[0].style.zIndex = o.stack.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);
+/*
+ * jQuery UI Resizable 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Resizables
+ *
+ * Depends:
+ *     ui.core.js
+ */
+(function($) {
+
+$.widget("ui.resizable", $.extend({}, $.ui.mouse, {
+
+       _init: 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)) {
+
+                       //Opera fix for relative positioning
+                       if (/relative/.test(this.element.css('position')) && $.browser.opera)
+                               this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
+
+                       //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>');
+
+                               // increase zIndex of sw, se, ne, nw axis
+                               //TODO : this modifies original option
+                               if(/sw|se|ne|nw/.test(handle)) 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() {
+                                       $(this).removeClass("ui-resizable-autohide");
+                                       self._handles.show();
+                               },
+                               function(){
+                                       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.parent().append(
+                               this.originalElement.css({
+                                       position: wrapper.css('position'),
+                                       width: wrapper.outerWidth(),
+                                       height: wrapper.outerHeight(),
+                                       top: wrapper.css('top'),
+                                       left: wrapper.css('left')
+                               })
+                       ).end().remove();
+               }
+
+               this.originalElement.css('resize', this.originalResizeStyle);
+               _destroy(this.originalElement);
+
+       },
+
+       _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 });
+               }
+
+               //Opera fixing relative position
+               if ($.browser.opera && (/relative/).test(el.css('position')))
+                       el.css({ position: 'relative', top: 'auto', left: 'auto' });
+
+               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;
+
+               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.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;
+
+                       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;
+
+       },
+
+       _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 (data.height) data.width = (csize.height * this.aspectRatio);
+               else if (data.width) data.height = (csize.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.options, 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.7.2",
+       eventPrefix: "resize",
+       defaults: {
+               alsoResize: false,
+               animate: false,
+               animateDuration: "slow",
+               animateEasing: "swing",
+               aspectRatio: false,
+               autoHide: false,
+               cancel: ":input,option",
+               containment: false,
+               delay: 0,
+               distance: 1,
+               ghost: false,
+               grid: false,
+               handles: "e,s,se",
+               helper: false,
+               maxHeight: null,
+               maxWidth: null,
+               minHeight: 10,
+               minWidth: 10,
+               zIndex: 1000
+       }
+});
+
+/*
+ * Resizable Extensions
+ */
+
+$.ui.plugin.add("resizable", "alsoResize", {
+
+       start: function(event, ui) {
+
+               var self = $(this).data("resizable"), o = self.options;
+
+               _store = function(exp) {
+                       $(exp).each(function() {
+                               $(this).data("resizable-alsoresize", {
+                                       width: parseInt($(this).width(), 10), height: parseInt($(this).height(), 10),
+                                       left: parseInt($(this).css('left'), 10), top: parseInt($(this).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, c) { _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 : ['width', 'height', 'top', 'left'];
+
+                               $.each(css || ['width', 'height', 'top', 'left'], function(i, prop) {
+                                       var sum = (start[prop]||0) + (delta[prop]||0);
+                                       if (sum && sum >= 0)
+                                               style[prop] = sum || null;
+                               });
+
+                               //Opera fixing relative position
+                               if (/relative/.test(el.css('position')) && $.browser.opera) {
+                                       self._revertToRelativePosition = true;
+                                       el.css({ position: 'absolute', top: 'auto', left: 'auto' });
+                               }
+
+                               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){
+               var self = $(this).data("resizable");
+
+               //Opera fixing relative position
+               if (self._revertToRelativePosition && $.browser.opera) {
+                       self._revertToRelativePosition = false;
+                       el.css({ position: 'relative' });
+               }
+
+               $(this).removeData("resizable-alsoresize-start");
+       }
+});
+
+$.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 / o.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 * o.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);
+/*
+ * jQuery UI Dialog 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Dialog
+ *
+ * Depends:
+ *     ui.core.js
+ *     ui.draggable.js
+ *     ui.resizable.js
+ */
+(function($) {
+
+var setDataSwitch = {
+               dragStart: "start.draggable",
+               drag: "drag.draggable",
+               dragStop: "stop.draggable",
+               maxHeight: "maxHeight.resizable",
+               minHeight: "minHeight.resizable",
+               maxWidth: "maxWidth.resizable",
+               minWidth: "minWidth.resizable",
+               resizeStart: "start.resizable",
+               resize: "drag.resizable",
+               resizeStop: "stop.resizable"
+       },
+       
+       uiDialogClasses =
+               'ui-dialog ' +
+               'ui-widget ' +
+               'ui-widget-content ' +
+               'ui-corner-all ';
+
+$.widget("ui.dialog", {
+
+       _init: function() {
+               this.originalTitle = this.element.attr('title');
+
+               var self = this,
+                       options = this.options,
+
+                       title = options.title || this.originalTitle || '&nbsp;',
+                       titleId = $.ui.dialog.getTitleId(this.element),
+
+                       uiDialog = (this.uiDialog = $('<div/>'))
+                               .appendTo(document.body)
+                               .hide()
+                               .addClass(uiDialogClasses + options.dialogClass)
+                               .css({
+                                       position: 'absolute',
+                                       overflow: 'hidden',
+                                       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) {
+                                       (options.closeOnEscape && event.keyCode
+                                               && event.keyCode == $.ui.keyCode.ESCAPE && self.close(event));
+                               })
+                               .attr({
+                                       role: 'dialog',
+                                       'aria-labelledby': titleId
+                               })
+                               .mousedown(function(event) {
+                                       self.moveToTop(false, event);
+                               }),
+
+                       uiDialogContent = this.element
+                               .show()
+                               .removeAttr('title')
+                               .addClass(
+                                       'ui-dialog-content ' +
+                                       'ui-widget-content')
+                               .appendTo(uiDialog),
+
+                       uiDialogTitlebar = (this.uiDialogTitlebar = $('<div></div>'))
+                               .addClass(
+                                       'ui-dialog-titlebar ' +
+                                       'ui-widget-header ' +
+                                       'ui-corner-all ' +
+                                       'ui-helper-clearfix'
+                               )
+                               .prependTo(uiDialog),
+
+                       uiDialogTitlebarClose = $('<a href="#"/>')
+                               .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');
+                               })
+                               .mousedown(function(ev) {
+                                       ev.stopPropagation();
+                               })
+                               .click(function(event) {
+                                       self.close(event);
+                                       return false;
+                               })
+                               .appendTo(uiDialogTitlebar),
+
+                       uiDialogTitlebarCloseText = (this.uiDialogTitlebarCloseText = $('<span/>'))
+                               .addClass(
+                                       'ui-icon ' +
+                                       'ui-icon-closethick'
+                               )
+                               .text(options.closeText)
+                               .appendTo(uiDialogTitlebarClose),
+
+                       uiDialogTitle = $('<span/>')
+                               .addClass('ui-dialog-title')
+                               .attr('id', titleId)
+                               .html(title)
+                               .prependTo(uiDialogTitlebar);
+
+               uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
+
+               (options.draggable && $.fn.draggable && this._makeDraggable());
+               (options.resizable && $.fn.resizable && this._makeResizable());
+
+               this._createButtons(options.buttons);
+               this._isOpen = false;
+
+               (options.bgiframe && $.fn.bgiframe && uiDialog.bgiframe());
+               (options.autoOpen && this.open());
+               
+       },
+
+       destroy: function() {
+               (this.overlay && this.overlay.destroy());
+               this.uiDialog.hide();
+               this.element
+                       .unbind('.dialog')
+                       .removeData('dialog')
+                       .removeClass('ui-dialog-content ui-widget-content')
+                       .hide().appendTo('body');
+               this.uiDialog.remove();
+
+               (this.originalTitle && this.element.attr('title', this.originalTitle));
+       },
+
+       close: function(event) {
+               var self = this;
+               
+               if (false === self._trigger('beforeclose', event)) {
+                       return;
+               }
+
+               (self.overlay && self.overlay.destroy());
+               self.uiDialog.unbind('keypress.ui-dialog');
+
+               (self.options.hide
+                       ? self.uiDialog.hide(self.options.hide, function() {
+                               self._trigger('close', event);
+                       })
+                       : self.uiDialog.hide() && self._trigger('close', event));
+
+               $.ui.dialog.overlay.resize();
+
+               self._isOpen = false;
+               
+               // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
+               if (self.options.modal) {
+                       var maxZ = 0;
+                       $('.ui-dialog').each(function() {
+                               if (this != self.uiDialog[0]) {
+                                       maxZ = Math.max(maxZ, $(this).css('z-index'));
+                               }
+                       });
+                       $.ui.dialog.maxZ = maxZ;
+               }
+       },
+
+       isOpen: function() {
+               return this._isOpen;
+       },
+
+       // the force parameter allows us to move modal dialogs to their correct
+       // position on open
+       moveToTop: function(force, event) {
+
+               if ((this.options.modal && !force)
+                       || (!this.options.stack && !this.options.modal)) {
+                       return this._trigger('focus', event);
+               }
+               
+               if (this.options.zIndex > $.ui.dialog.maxZ) {
+                       $.ui.dialog.maxZ = this.options.zIndex;
+               }
+               (this.overlay && this.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
+               var saveScroll = { scrollTop: this.element.attr('scrollTop'), scrollLeft: this.element.attr('scrollLeft') };
+               this.uiDialog.css('z-index', ++$.ui.dialog.maxZ);
+               this.element.attr(saveScroll);
+               this._trigger('focus', event);
+       },
+
+       open: function() {
+               if (this._isOpen) { return; }
+
+               var options = this.options,
+                       uiDialog = this.uiDialog;
+
+               this.overlay = options.modal ? new $.ui.dialog.overlay(this) : null;
+               (uiDialog.next().length && uiDialog.appendTo('body'));
+               this._size();
+               this._position(options.position);
+               uiDialog.show(options.show);
+               this.moveToTop(true);
+
+               // prevent tabbing out of modal dialogs
+               (options.modal && uiDialog.bind('keypress.ui-dialog', function(event) {
+                       if (event.keyCode != $.ui.keyCode.TAB) {
+                               return;
+                       }
+
+                       var tabbables = $(':tabbable', this),
+                               first = tabbables.filter(':first')[0],
+                               last  = tabbables.filter(':last')[0];
+
+                       if (event.target == last && !event.shiftKey) {
+                               setTimeout(function() {
+                                       first.focus();
+                               }, 1);
+                       } else if (event.target == first && event.shiftKey) {
+                               setTimeout(function() {
+                                       last.focus();
+                               }, 1);
+                       }
+               }));
+
+               // 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
+               $([])
+                       .add(uiDialog.find('.ui-dialog-content :tabbable:first'))
+                       .add(uiDialog.find('.ui-dialog-buttonpane :tabbable:first'))
+                       .add(uiDialog)
+                       .filter(':first')
+                       .focus();
+
+               this._trigger('open');
+               this._isOpen = true;
+       },
+
+       _createButtons: function(buttons) {
+               var self = this,
+                       hasButtons = false,
+                       uiDialogButtonPane = $('<div></div>')
+                               .addClass(
+                                       'ui-dialog-buttonpane ' +
+                                       'ui-widget-content ' +
+                                       'ui-helper-clearfix'
+                               );
+
+               // if we already have a button pane, remove it
+               this.uiDialog.find('.ui-dialog-buttonpane').remove();
+
+               (typeof buttons == 'object' && buttons !== null &&
+                       $.each(buttons, function() { return !(hasButtons = true); }));
+               if (hasButtons) {
+                       $.each(buttons, function(name, fn) {
+                               $('<button type="button"></button>')
+                                       .addClass(
+                                               'ui-state-default ' +
+                                               'ui-corner-all'
+                                       )
+                                       .text(name)
+                                       .click(function() { fn.apply(self.element[0], arguments); })
+                                       .hover(
+                                               function() {
+                                                       $(this).addClass('ui-state-hover');
+                                               },
+                                               function() {
+                                                       $(this).removeClass('ui-state-hover');
+                                               }
+                                       )
+                                       .focus(function() {
+                                               $(this).addClass('ui-state-focus');
+                                       })
+                                       .blur(function() {
+                                               $(this).removeClass('ui-state-focus');
+                                       })
+                                       .appendTo(uiDialogButtonPane);
+                       });
+                       uiDialogButtonPane.appendTo(this.uiDialog);
+               }
+       },
+
+       _makeDraggable: function() {
+               var self = this,
+                       options = this.options,
+                       heightBeforeDrag;
+
+               this.uiDialog.draggable({
+                       cancel: '.ui-dialog-content',
+                       handle: '.ui-dialog-titlebar',
+                       containment: 'document',
+                       start: function() {
+                               heightBeforeDrag = options.height;
+                               $(this).height($(this).height()).addClass("ui-dialog-dragging");
+                               (options.dragStart && options.dragStart.apply(self.element[0], arguments));
+                       },
+                       drag: function() {
+                               (options.drag && options.drag.apply(self.element[0], arguments));
+                       },
+                       stop: function() {
+                               $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
+                               (options.dragStop && options.dragStop.apply(self.element[0], arguments));
+                               $.ui.dialog.overlay.resize();
+                       }
+               });
+       },
+
+       _makeResizable: function(handles) {
+               handles = (handles === undefined ? this.options.resizable : handles);
+               var self = this,
+                       options = this.options,
+                       resizeHandles = typeof handles == 'string'
+                               ? handles
+                               : 'n,e,s,w,se,sw,ne,nw';
+
+               this.uiDialog.resizable({
+                       cancel: '.ui-dialog-content',
+                       alsoResize: this.element,
+                       maxWidth: options.maxWidth,
+                       maxHeight: options.maxHeight,
+                       minWidth: options.minWidth,
+                       minHeight: options.minHeight,
+                       start: function() {
+                               $(this).addClass("ui-dialog-resizing");
+                               (options.resizeStart && options.resizeStart.apply(self.element[0], arguments));
+                       },
+                       resize: function() {
+                               (options.resize && options.resize.apply(self.element[0], arguments));
+                       },
+                       handles: resizeHandles,
+                       stop: function() {
+                               $(this).removeClass("ui-dialog-resizing");
+                               options.height = $(this).height();
+                               options.width = $(this).width();
+                               (options.resizeStop && options.resizeStop.apply(self.element[0], arguments));
+                               $.ui.dialog.overlay.resize();
+                       }
+               })
+               .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
+       },
+
+       _position: function(pos) {
+               var wnd = $(window), doc = $(document),
+                       pTop = doc.scrollTop(), pLeft = doc.scrollLeft(),
+                       minTop = pTop;
+
+               if ($.inArray(pos, ['center','top','right','bottom','left']) >= 0) {
+                       pos = [
+                               pos == 'right' || pos == 'left' ? pos : 'center',
+                               pos == 'top' || pos == 'bottom' ? pos : 'middle'
+                       ];
+               }
+               if (pos.constructor != Array) {
+                       pos = ['center', 'middle'];
+               }
+               if (pos[0].constructor == Number) {
+                       pLeft += pos[0];
+               } else {
+                       switch (pos[0]) {
+                               case 'left':
+                                       pLeft += 0;
+                                       break;
+                               case 'right':
+                                       pLeft += wnd.width() - this.uiDialog.outerWidth();
+                                       break;
+                               default:
+                               case 'center':
+                                       pLeft += (wnd.width() - this.uiDialog.outerWidth()) / 2;
+                       }
+               }
+               if (pos[1].constructor == Number) {
+                       pTop += pos[1];
+               } else {
+                       switch (pos[1]) {
+                               case 'top':
+                                       pTop += 0;
+                                       break;
+                               case 'bottom':
+                                       pTop += wnd.height() - this.uiDialog.outerHeight();
+                                       break;
+                               default:
+                               case 'middle':
+                                       pTop += (wnd.height() - this.uiDialog.outerHeight()) / 2;
+                       }
+               }
+
+               // prevent the dialog from being too high (make sure the titlebar
+               // is accessible)
+               pTop = Math.max(pTop, minTop);
+               this.uiDialog.css({top: pTop, left: pLeft});
+       },
+
+       _setData: function(key, value){
+               (setDataSwitch[key] && this.uiDialog.data(setDataSwitch[key], value));
+               switch (key) {
+                       case "buttons":
+                               this._createButtons(value);
+                               break;
+                       case "closeText":
+                               this.uiDialogTitlebarCloseText.text(value);
+                               break;
+                       case "dialogClass":
+                               this.uiDialog
+                                       .removeClass(this.options.dialogClass)
+                                       .addClass(uiDialogClasses + value);
+                               break;
+                       case "draggable":
+                               (value
+                                       ? this._makeDraggable()
+                                       : this.uiDialog.draggable('destroy'));
+                               break;
+                       case "height":
+                               this.uiDialog.height(value);
+                               break;
+                       case "position":
+                               this._position(value);
+                               break;
+                       case "resizable":
+                               var uiDialog = this.uiDialog,
+                                       isResizable = this.uiDialog.is(':data(resizable)');
+
+                               // currently resizable, becoming non-resizable
+                               (isResizable && !value && uiDialog.resizable('destroy'));
+
+                               // currently resizable, changing handles
+                               (isResizable && typeof value == 'string' &&
+                                       uiDialog.resizable('option', 'handles', value));
+
+                               // currently non-resizable, becoming resizable
+                               (isResizable || this._makeResizable(value));
+                               break;
+                       case "title":
+                               $(".ui-dialog-title", this.uiDialogTitlebar).html(value || '&nbsp;');
+                               break;
+                       case "width":
+                               this.uiDialog.width(value);
+                               break;
+               }
+
+               $.widget.prototype._setData.apply(this, 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;
+
+               // reset content sizing
+               this.element.css({
+                       height: 0,
+                       minHeight: 0,
+                       width: 'auto'
+               });
+
+               // reset wrapper sizing
+               // determine the height of all the non-content elements
+               var nonContentHeight = this.uiDialog.css({
+                               height: 'auto',
+                               width: options.width
+                       })
+                       .height();
+
+               this.element
+                       .css({
+                               minHeight: Math.max(options.minHeight - nonContentHeight, 0),
+                               height: options.height == 'auto'
+                                       ? 'auto'
+                                       : Math.max(options.height - nonContentHeight, 0)
+                       });
+       }
+});
+
+$.extend($.ui.dialog, {
+       version: "1.7.2",
+       defaults: {
+               autoOpen: true,
+               bgiframe: false,
+               buttons: {},
+               closeOnEscape: true,
+               closeText: 'close',
+               dialogClass: '',
+               draggable: true,
+               hide: null,
+               height: 'auto',
+               maxHeight: false,
+               maxWidth: false,
+               minHeight: 150,
+               minWidth: 150,
+               modal: false,
+               position: 'center',
+               resizable: true,
+               show: null,
+               stack: true,
+               title: '',
+               width: 300,
+               zIndex: 1000
+       },
+
+       getter: 'isOpen',
+
+       uuid: 0,
+       maxZ: 0,
+
+       getTitleId: function($el) {
+               return 'ui-dialog-title-' + ($el.attr('id') || ++this.uuid);
+       },
+
+       overlay: function(dialog) {
+               this.$el = $.ui.dialog.overlay.create(dialog);
+       }
+});
+
+$.extend($.ui.dialog.overlay, {
+       instances: [],
+       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) {
+                                               var dialogZ = $(event.target).parents('.ui-dialog').css('zIndex') || 0;
+                                               return (dialogZ > $.ui.dialog.overlay.maxZ);
+                                       });
+                               }
+                       }, 1);
+
+                       // allow closing by pressing the escape key
+                       $(document).bind('keydown.dialog-overlay', function(event) {
+                               (dialog.options.closeOnEscape && event.keyCode
+                                               && event.keyCode == $.ui.keyCode.ESCAPE && dialog.close(event));
+                       });
+
+                       // handle window resize
+                       $(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
+               }
+
+               var $el = $('<div></div>').appendTo(document.body)
+                       .addClass('ui-widget-overlay').css({
+                               width: this.width(),
+                               height: this.height()
+                       });
+
+               (dialog.options.bgiframe && $.fn.bgiframe && $el.bgiframe());
+
+               this.instances.push($el);
+               return $el;
+       },
+
+       destroy: function($el) {
+               this.instances.splice($.inArray(this.instances, $el), 1);
+
+               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() {
+               // handle IE 6
+               if ($.browser.msie && $.browser.version < 7) {
+                       var scrollHeight = Math.max(
+                               document.documentElement.scrollHeight,
+                               document.body.scrollHeight
+                       );
+                       var 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() {
+               // handle IE 6
+               if ($.browser.msie && $.browser.version < 7) {
+                       var scrollWidth = Math.max(
+                               document.documentElement.scrollWidth,
+                               document.body.scrollWidth
+                       );
+                       var 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);
+/*
+ * jQuery UI Tabs 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Tabs
+ *
+ * Depends:
+ *     ui.core.js
+ */
+(function($) {
+
+$.widget("ui.tabs", {
+
+       _init: function() {
+               if (this.options.deselectable !== undefined) {
+                       this.options.collapsible = this.options.deselectable;
+               }
+               this._tabify(true);
+       },
+
+       _setData: function(key, value) {
+               if (key == 'selected') {
+                       if (this.options.collapsible && value == this.options.selected) {
+                               return;
+                       }
+                       this.select(value);
+               }
+               else {
+                       this.options[key] = value;
+                       if (key == 'deselectable') {
+                               this.options.collapsible = value;
+                       }
+                       this._tabify();
+               }
+       },
+
+       _tabId: function(a) {
+               return a.title && a.title.replace(/\s/g, '_').replace(/[^A-Za-z0-9\-_:\.]/g, '') ||
+                       this.options.idPrefix + $.data(a);
+       },
+
+       _sanitizeSelector: function(hash) {
+               return hash.replace(/:/g, '\\:'); // we need this because an id may contain a ":"
+       },
+
+       _cookie: function() {
+               var cookie = this.cookie || (this.cookie = this.options.cookie.name || 'ui-tabs-' + $.data(this.list[0]));
+               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) {
+
+               this.list = this.element.children('ul:first');
+               this.lis = $('li:has(a[href])', this.list);
+               this.anchors = this.lis.map(function() { return $('a', this)[0]; });
+               this.panels = $([]);
+
+               var self = this, o = this.options;
+
+               var fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
+               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._sanitizeSelector(href));
+                       }
+
+                       // remote tab
+                       else if (href != '#') { // prevent loading the page itself if href is just "#"
+                               $.data(a, 'href.tabs', href); // required for restore on destroy
+
+                               // TODO until #3808 is fixed strip fragment identifier from url
+                               // (IE fails to load from such url)
+                               $.data(a, 'load.tabs', href.replace(/#.*$/, '')); // mutable data
+
+                               var id = self._tabId(a);
+                               a.href = '#' + id;
+                               var $panel = $('#' + 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; // break
+                                               }
+                                       });
+                               }
+                               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 || 0;
+                       }
+                       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');
+                       if (o.selected >= 0 && this.anchors.length) { // check for length avoids error when initializing empty list
+                               this.panels.eq(o.selected).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.panels[o.selected]));
+                               });
+                               
+                               this.load(o.selected);
+                       }
+
+                       // clean up to avoid memory leaks in certain versions of IE 6
+                       $(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
+               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 &&
+                               !$(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 ($.browser.msie && fx.opacity) {
+                               $el[0].style.removeAttribute('filter');
+                       }
+               }
+
+               // Show a tab...
+               var showTab = showFx ?
+                       function(clicked, $show) {
+                               $(clicked).closest('li').removeClass('ui-state-default').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').removeClass('ui-state-default').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').addClass('ui-state-default');
+                                       $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').addClass('ui-state-default');
+                               $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 = $(this).closest('li'), $hide = self.panels.filter(':not(.ui-tabs-hide)'),
+                                       $show = $(self._sanitizeSelector(this.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._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);
+                                       });
+
+                                       self.load(self.anchors.index(this)); // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
+                                       
+                                       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;});
+
+       },
+
+       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);
+               }
+       },
+
+       add: function(url, label, index) {
+               if (index === undefined) {
+                       index = this.anchors.length; // append by default
+               }
+
+               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 = $('#' + 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) { // after tabify
+                       $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);
+               }
+
+               // callback
+               this._trigger('add', null, this._ui(this.anchors[index], this.panels[index]));
+       },
+
+       remove: function(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();
+
+               // callback
+               this._trigger('remove', null, this._ui($li.find('a')[0], $panel[0]));
+       },
+
+       enable: function(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; });
+
+               // callback
+               this._trigger('enable', null, this._ui(this.anchors[index], this.panels[index]));
+       },
+
+       disable: function(index) {
+               var self = this, o = this.options;
+               if (index != o.selected) { // cannot disable already selected tab
+                       this.lis.eq(index).addClass('ui-state-disabled');
+
+                       o.disabled.push(index);
+                       o.disabled.sort();
+
+                       // callback
+                       this._trigger('disable', null, this._ui(this.anchors[index], this.panels[index]));
+               }
+       },
+
+       select: function(index) {
+               if (typeof index == 'string') {
+                       index = this.anchors.index(this.anchors.filter('[href$=' + index + ']'));
+               }
+               else if (index === null) { // usage of null is deprecated, TODO remove in next release
+                       index = -1;
+               }
+               if (index == -1 && this.options.collapsible) {
+                       index = this.options.selected;
+               }
+
+               this.anchors.eq(index).trigger(this.options.event + '.tabs');
+       },
+
+       load: function(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._sanitizeSelector(a.hash)).html(r);
+
+                               // take care of tab labels
+                               self._cleanup();
+
+                               if (o.cache) {
+                                       $.data(a, 'cache.tabs', true); // if loaded once do not load them again
+                               }
+
+                               // callbacks
+                               self._trigger('load', null, self._ui(self.anchors[index], self.panels[index]));
+                               try {
+                                       o.ajaxOptions.success(r, s);
+                               }
+                               catch (e) {}
+
+                               // last, so that load event is fired before show...
+                               self.element.dequeue("tabs");
+                       }
+               }));
+       },
+
+       abort: function() {
+               // stop possibly running animations
+               this.element.queue([]);
+               this.panels.stop(false, true);
+
+               // terminate pending requests from other tabs
+               if (this.xhr) {
+                       this.xhr.abort();
+                       delete this.xhr;
+               }
+
+               // take care of tab labels
+               this._cleanup();
+
+       },
+
+       url: function(index, url) {
+               this.anchors.eq(index).removeData('cache.tabs').data('load.tabs', url);
+       },
+
+       length: function() {
+               return this.anchors.length;
+       }
+
+});
+
+$.extend($.ui.tabs, {
+       version: '1.7.2',
+       getter: 'length',
+       defaults: {
+               ajaxOptions: null,
+               cache: false,
+               cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
+               collapsible: false,
+               disabled: [],
+               event: 'click',
+               fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
+               idPrefix: 'ui-tabs-',
+               panelTemplate: '<div></div>',
+               spinner: '<em>Loading&#8230;</em>',
+               tabTemplate: '<li><a href="#{href}"><span>#{label}</span></a></li>'
+       }
+});
+
+/*
+ * 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) {
+                               t = o.selected;
+                               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;
+               }
+       }
+});
+
+})(jQuery);
+/*
+ * jQuery UI Datepicker 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Datepicker
+ *
+ * Depends:
+ *     ui.core.js
+ */
+
+(function($) { // hide the namespace
+
+$.extend($.ui, { datepicker: { version: "1.7.2" } });
+
+var PROP_NAME = 'datepicker';
+
+/* 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
+               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
+       };
+       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: 'show', // 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
+               showMonthAfterYear: false, // True if the year select precedes month, false for month then year
+               yearRange: '-10:+10', // Range of years to display in drop-down,
+                       // either relative to current year (-nn:+nn) or absolute (nnnn:nnnn)
+               showOtherMonths: false, // True to show dates in other months, false to leave blank
+               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: 'normal', // 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
+       };
+       $.extend(this._defaults, this.regional['']);
+       this.dpDiv = $('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>');
+}
+
+$.extend(Datepicker.prototype, {
+       /* Class name added to elements to indicate already configured with a date picker. */
+       markerClassName: 'hasDatepicker',
+
+       /* Debug logging (if enabled). */
+       log: function () {
+               if (this.debug)
+                       console.log.apply('', arguments);
+       },
+
+       /* 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)
+                       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(/([:\[\]\.])/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
+                       $('<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;
+               var appendText = this._get(inst, 'appendText');
+               var isRTL = this._get(inst, 'isRTL');
+               if (appendText) {
+                       inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
+                       input[isRTL ? 'before' : 'after'](inst.append);
+               }
+               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 == target)
+                                       $.datepicker._hideDatepicker();
+                               else
+                                       $.datepicker._showDatepicker(target);
+                               return false;
+                       });
+               }
+               input.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).
+                       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);
+       },
+
+       /* 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));
+               this._updateDatepicker(inst);
+               this._updateAlternate(inst);
+       },
+
+       /* Pop-up the date picker in a "dialog" box.
+          @param  input     element - ignored
+          @param  dateText  string - the initial date to display (in the current format)
+          @param  onSelect  function - the function(dateText) 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, dateText, onSelect, settings, pos) {
+               var inst = this._dialogInst; // internal instance
+               if (!inst) {
+                       var id = 'dp' + (++this.uuid);
+                       this._dialogInput = $('<input type="text" id="' + id +
+                               '" size="1" style="position: absolute; top: -100px;"/>');
+                       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 || {});
+               this._dialogInput.val(dateText);
+
+               this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
+               if (!this._pos) {
+                       var browserWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
+                       var browserHeight = window.innerHeight || document.documentElement.clientHeight || document.body.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] + '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);
+               } 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');
+               }
+               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');
+               }
+               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(null);
+                       }
+                       var date = this._getDateDatepicker(target);
+                       extendRemove(inst.settings, settings);
+                       this._setDateDatepicker(target, date);
+                       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
+          @param  endDate  Date - the new end date for a range (optional) */
+       _setDateDatepicker: function(target, date, endDate) {
+               var inst = this._getInst(target);
+               if (inst) {
+                       this._setDate(inst, date, endDate);
+                       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
+          @return Date - the current date or
+                  Date[2] - the current dates for a range */
+       _getDateDatepicker: function(target) {
+               var inst = this._getInst(target);
+               if (inst && !inst.inline)
+                       this._setDateFromField(inst);
+               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(null, '');
+                                               break; // hide on tab out
+                               case 13: var sel = $('td.' + $.datepicker._dayOverClass +
+                                                       ', td.' + $.datepicker._currentClass, inst.dpDiv);
+                                               if (sel[0])
+                                                       $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
+                                               else
+                                                       $.datepicker._hideDatepicker(null, $.datepicker._get(inst, 'duration'));
+                                               return false; // don't submit the form
+                                               break; // select the value on enter
+                               case 27: $.datepicker._hideDatepicker(null, $.datepicker._get(inst, 'duration'));
+                                               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 || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
+               }
+       },
+
+       /* Pop-up the date picker for a given input field.
+          @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);
+               var beforeShow = $.datepicker._get(inst, 'beforeShow');
+               extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
+               $.datepicker._hideDatepicker(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;
+               inst.rangeStart = null;
+               // 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') || 'show';
+                       var duration = $.datepicker._get(inst, 'duration');
+                       var postProcess = function() {
+                               $.datepicker._datepickerShowing = true;
+                               if ($.browser.msie && parseInt($.browser.version,10) < 7) // fix IE < 7 select problems
+                                       $('iframe.ui-datepicker-cover').css({width: inst.dpDiv.width() + 4,
+                                               height: inst.dpDiv.height() + 4});
+                       };
+                       if ($.effects && $.effects[showAnim])
+                               inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
+                       else
+                               inst.dpDiv[showAnim](duration, postProcess);
+                       if (duration == '')
+                               postProcess();
+                       if (inst.input[0].type != 'hidden')
+                               inst.input[0].focus();
+                       $.datepicker._curInst = inst;
+               }
+       },
+
+       /* Generate the date picker content. */
+       _updateDatepicker: function(inst) {
+               var dims = {width: inst.dpDiv.width() + 4,
+                       height: inst.dpDiv.height() + 4};
+               var self = this;
+               inst.dpDiv.empty().append(this._generateHTML(inst))
+                       .find('iframe.ui-datepicker-cover').
+                               css({width: dims.width, height: dims.height})
+                       .end()
+                       .find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')
+                               .bind('mouseout', function(){
+                                       $(this).removeClass('ui-state-hover');
+                                       if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
+                                       if(this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
+                               })
+                               .bind('mouseover', function(){
+                                       if (!self._isDisabledDatepicker( inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) {
+                                               $(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
+                                               $(this).addClass('ui-state-hover');
+                                               if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
+                                               if(this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
+                                       }
+                               })
+                       .end()
+                       .find('.' + this._dayOverClass + ' a')
+                               .trigger('mouseover')
+                       .end();
+               var numMonths = this._getNumberOfMonths(inst);
+               var cols = numMonths[1];
+               var width = 17;
+               if (cols > 1) {
+                       inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
+               } else {
+                       inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
+               }
+               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.input && inst.input[0].type != 'hidden' && inst == $.datepicker._curInst)
+                       $(inst.input[0]).focus();
+       },
+
+       /* 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 = (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) + $(document).scrollLeft();
+               var viewHeight = (window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight) + $(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 -= (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? Math.abs(offset.left + dpWidth - viewWidth) : 0;
+               offset.top -= (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? Math.abs(offset.top + dpHeight + inputHeight*2 - viewHeight) : 0;
+
+               return offset;
+       },
+
+       /* Find an object's position on the screen. */
+       _findPos: function(obj) {
+        while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
+            obj = obj.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
+          @param  duration  string - the duration over which to close the date picker */
+       _hideDatepicker: function(input, duration) {
+               var inst = this._curInst;
+               if (!inst || (input && inst != $.data(input, PROP_NAME)))
+                       return;
+               if (inst.stayOpen)
+                       this._selectDate('#' + inst.id, this._formatDate(inst,
+                               inst.currentDay, inst.currentMonth, inst.currentYear));
+               inst.stayOpen = false;
+               if (this._datepickerShowing) {
+                       duration = (duration != null ? duration : this._get(inst, 'duration'));
+                       var showAnim = this._get(inst, 'showAnim');
+                       var postProcess = function() {
+                               $.datepicker._tidyDialog(inst);
+                       };
+                       if (duration != '' && $.effects && $.effects[showAnim])
+                               inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'),
+                                       duration, postProcess);
+                       else
+                               inst.dpDiv[(duration == '' ? 'hide' : (showAnim == 'slideDown' ? 'slideUp' :
+                                       (showAnim == 'fadeIn' ? 'fadeOut' : 'hide')))](duration, postProcess);
+                       if (duration == '')
+                               this._tidyDialog(inst);
+                       var onClose = this._get(inst, 'onClose');
+                       if (onClose)
+                               onClose.apply((inst.input ? inst.input[0] : null),
+                                       [(inst.input ? inst.input.val() : ''), inst]);  // trigger custom callback
+                       this._datepickerShowing = false;
+                       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;
+               }
+               this._curInst = null;
+       },
+
+       /* 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);
+               if (($target.parents('#' + $.datepicker._mainDivId).length == 0) &&
+                               !$target.hasClass($.datepicker.markerClassName) &&
+                               !$target.hasClass($.datepicker._triggerClass) &&
+                               $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
+                       $.datepicker._hideDatepicker(null, '');
+       },
+
+       /* 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._selectingMonthYear = false;
+               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);
+       },
+
+       /* Restore input focus after not changing month/year. */
+       _clickMonthYear: function(id) {
+               var target = $(id);
+               var inst = this._getInst(target[0]);
+               if (inst.input && inst._selectingMonthYear && !$.browser.msie)
+                       inst.input[0].focus();
+               inst._selectingMonthYear = !inst._selectingMonthYear;
+       },
+
+       /* 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;
+               if (inst.stayOpen) {
+                       inst.endDay = inst.endMonth = inst.endYear = null;
+               }
+               this._selectDate(id, this._formatDate(inst,
+                       inst.currentDay, inst.currentMonth, inst.currentYear));
+               if (inst.stayOpen) {
+                       inst.rangeStart = this._daylightSavingAdjust(
+                               new Date(inst.currentYear, inst.currentMonth, inst.currentDay));
+                       this._updateDatepicker(inst);
+               }
+       },
+
+       /* Erase the input field and hide the date picker. */
+       _clearDate: function(id) {
+               var target = $(id);
+               var inst = this._getInst(target[0]);
+               inst.stayOpen = false;
+               inst.endDay = inst.endMonth = inst.endYear = inst.rangeStart = null;
+               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 if (!inst.stayOpen) {
+                       this._hideDatepicker(null, this._get(inst, 'duration'));
+                       this._lastInput = inst.input[0];
+                       if (typeof(inst.input[0]) != 'object')
+                               inst.input[0].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);
+                       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.getFullYear(), date.getMonth(), date.getDate());
+               var firstMon = new Date(checkDate.getFullYear(), 1 - 1, 4); // First week always contains 4 Jan
+               var firstDay = firstMon.getDay() || 7; // Day of week: Mon = 1, ..., Sun = 7
+               firstMon.setDate(firstMon.getDate() + 1 - firstDay); // Preceding Monday
+               if (firstDay < 4 && checkDate < firstMon) { // Adjust first three days in year if necessary
+                       checkDate.setDate(checkDate.getDate() - 3); // Generate for previous year
+                       return $.datepicker.iso8601Week(checkDate);
+               } else if (checkDate > new Date(checkDate.getFullYear(), 12 - 1, 28)) { // Check last three days in year
+                       firstDay = new Date(checkDate.getFullYear() + 1, 1 - 1, 4).getDay() || 7;
+                       if (firstDay > 4 && (checkDate.getDay() || 7) < firstDay - 3) { // Adjust if necessary
+                               return 1;
+                       }
+               }
+               return Math.floor(((checkDate - firstMon) / 86400000) / 7) + 1; // Weeks to given date
+       },
+
+       /* 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;
+               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) {
+                       lookAhead(match);
+                       var origSize = (match == '@' ? 14 : (match == 'y' ? 4 : (match == 'o' ? 3 : 2)));
+                       var size = origSize;
+                       var num = 0;
+                       while (size > 0 && iValue < value.length &&
+                                       value.charAt(iValue) >= '0' && value.charAt(iValue) <= '9') {
+                               num = num * 10 + parseInt(value.charAt(iValue++),10);
+                               size--;
+                       }
+                       if (size == origSize)
+                               throw 'Missing number at position ' + iValue;
+                       return num;
+               };
+               // Extract a name from the string value and convert to an index
+               var getName = function(match, shortNames, longNames) {
+                       var names = (lookAhead(match) ? longNames : shortNames);
+                       var size = 0;
+                       for (var j = 0; j < names.length; j++)
+                               size = Math.max(size, names[j].length);
+                       var name = '';
+                       var iInit = iValue;
+                       while (size > 0 && iValue < value.length) {
+                               name += value.charAt(iValue++);
+                               for (var i = 0; i < names.length; i++)
+                                       if (name == names[i])
+                                               return i + 1;
+                               size--;
+                       }
+                       throw 'Unknown name at position ' + iInit;
+               };
+               // 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 "'":
+                                               if (lookAhead("'"))
+                                                       checkLiteral();
+                                               else
+                                                       literal = true;
+                                               break;
+                                       default:
+                                               checkLiteral();
+                               }
+               }
+               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/*
+               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
+       TIMESTAMP: '@',
+       W3C: 'yy-mm-dd', // ISO 8601
+
+       /* 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)
+          '...' - 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':
+                                                       var doy = date.getDate();
+                                                       for (var m = date.getMonth() - 1; m >= 0; m--)
+                                                               doy += this._getDaysInMonth(date.getFullYear(), m);
+                                                       output += formatNumber('o', doy, 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 "'":
+                                                       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;
+               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) {
+               var dateFormat = this._get(inst, 'dateFormat');
+               var dates = inst.input ? inst.input.val() : null;
+               inst.endDay = inst.endMonth = inst.endYear = null;
+               var date = defaultDate = this._getDefaultDate(inst);
+               var settings = this._getFormatConfig(inst);
+               try {
+                       date = this.parseDate(dateFormat, dates, settings) || defaultDate;
+               } catch (event) {
+                       this.log(event);
+                       date = defaultDate;
+               }
+               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) {
+               var date = this._determineDate(this._get(inst, 'defaultDate'), new Date());
+               var minDate = this._getMinMaxDate(inst, 'min', true);
+               var maxDate = this._getMinMaxDate(inst, 'max');
+               date = (minDate && date < minDate ? minDate : date);
+               date = (maxDate && date > maxDate ? maxDate : date);
+               return date;
+       },
+
+       /* A date may be specified as an exact value or a relative one. */
+       _determineDate: function(date, defaultDate) {
+               var offsetNumeric = function(offset) {
+                       var date = new Date();
+                       date.setDate(date.getDate() + offset);
+                       return date;
+               };
+               var offsetString = function(offset, getDaysInMonth) {
+                       var date = 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, getDaysInMonth(year, month));
+                                               break;
+                                       case 'y': case 'Y' :
+                                               year += parseInt(matches[1],10);
+                                               day = Math.min(day, getDaysInMonth(year, month));
+                                               break;
+                               }
+                               matches = pattern.exec(offset);
+                       }
+                       return new Date(year, month, day);
+               };
+               date = (date == null ? defaultDate :
+                       (typeof date == 'string' ? offsetString(date, this._getDaysInMonth) :
+                       (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : date)));
+               date = (date && date.toString() == 'Invalid Date' ? defaultDate : date);
+               if (date) {
+                       date.setHours(0);
+                       date.setMinutes(0);
+                       date.setSeconds(0);
+                       date.setMilliseconds(0);
+               }
+               return this._daylightSavingAdjust(date);
+       },
+
+       /* 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, endDate) {
+               var clear = !(date);
+               var origMonth = inst.selectedMonth;
+               var origYear = inst.selectedYear;
+               date = this._determineDate(date, new Date());
+               inst.selectedDay = inst.currentDay = date.getDate();
+               inst.drawMonth = inst.selectedMonth = inst.currentMonth = date.getMonth();
+               inst.drawYear = inst.selectedYear = inst.currentYear = date.getFullYear();
+               if (origMonth != inst.selectedMonth || origYear != inst.selectedYear)
+                       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;
+       },
+
+       /* 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 stepBigMonths = this._get(inst, 'stepBigMonths');
+               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', true);
+               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[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" onclick="DP_jQuery.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
+                       ' 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" onclick="DP_jQuery.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
+                       ' 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" onclick="DP_jQuery.datepicker._hideDatepicker();">' + 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" onclick="DP_jQuery.datepicker._gotoToday(\'#' + inst.id + '\');"' +
+                       '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
+               var firstDay = parseInt(this._get(inst, 'firstDay'),10);
+               firstDay = (isNaN(firstDay) ? 0 : firstDay);
+               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 calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
+               var endDate = inst.endDay ? this._daylightSavingAdjust(
+                       new Date(inst.endYear, inst.endMonth, inst.endDay)) : currentDate;
+               var defaultDate = this._getDefaultDate(inst);
+               var html = '';
+               for (var row = 0; row < numMonths[0]; row++) {
+                       var group = '';
+                       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 ui-datepicker-group-';
+                                       switch (col) {
+                                               case 0: calender += 'first'; cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
+                                               case numMonths[1]-1: calender += 'last'; cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
+                                               default: calender += '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,
+                                       selectedDate, row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
+                                       '</div><table class="ui-datepicker-calendar"><thead>' +
+                                       '<tr>';
+                               var thead = '';
+                               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 numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
+                               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 = '';
+                                       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 || !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() && printDate.getTime() <= endDate.getTime() ? // in current range
+                                                       ' ' + 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 ? '' : ' onclick="DP_jQuery.datepicker._selectDay(\'#' +
+                                                       inst.id + '\',' + drawMonth + ',' + drawYear + ', this);return false;"') + '>' + // actions
+                                                       (otherMonth ? (showOtherMonths ? printDate.getDate() : '&#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() && printDate.getTime() <= endDate.getTime() ? // in current range
+                                                       ' ui-state-active' : '') + // highlight selected day
+                                                       '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display for this month
+                                               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,
+                       selectedDate, secondary, monthNames, monthNamesShort) {
+               minDate = (inst.rangeStart && minDate && selectedDate < minDate ? selectedDate : minDate);
+               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" ' +
+                               'onchange="DP_jQuery.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
+                               'onclick="DP_jQuery.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
+                               '>';
+                       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) && (!(changeMonth && changeYear)) ? '&#xa0;' : '');
+               // year selection
+               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 year = 0;
+                       var endYear = 0;
+                       if (years.length != 2) {
+                               year = drawYear - 10;
+                               endYear = drawYear + 10;
+                       } else if (years[0].charAt(0) == '+' || years[0].charAt(0) == '-') {
+                               year = drawYear + parseInt(years[0], 10);
+                               endYear = drawYear + parseInt(years[1], 10);
+                       } else {
+                               year = parseInt(years[0], 10);
+                               endYear = parseInt(years[1], 10);
+                       }
+                       year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
+                       endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
+                       html += '<select class="ui-datepicker-year" ' +
+                               'onchange="DP_jQuery.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
+                               'onclick="DP_jQuery.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
+                               '>';
+                       for (; year <= endYear; year++) {
+                               html += '<option value="' + year + '"' +
+                                       (year == drawYear ? ' selected="selected"' : '') +
+                                       '>' + year + '</option>';
+                       }
+                       html += '</select>';
+               }
+               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._daylightSavingAdjust(new Date(year, month, day));
+               // ensure it is within the bounds set
+               var minDate = this._getMinMaxDate(inst, 'min', true);
+               var maxDate = this._getMinMaxDate(inst, 'max');
+               date = (minDate && date < minDate ? minDate : date);
+               date = (maxDate && date > maxDate ? maxDate : date);
+               inst.selectedDay = date.getDate();
+               inst.drawMonth = inst.selectedMonth = date.getMonth();
+               inst.drawYear = inst.selectedYear = date.getFullYear();
+               if (period == 'M' || period == 'Y')
+                       this._notifyChange(inst);
+       },
+
+       /* 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 - may be overridden for a range. */
+       _getMinMaxDate: function(inst, minMax, checkRange) {
+               var date = this._determineDate(this._get(inst, minMax + 'Date'), null);
+               return (!checkRange || !inst.rangeStart ? date :
+                       (!date || inst.rangeStart > date ? inst.rangeStart : date));
+       },
+
+       /* Find the number of days in a given month. */
+       _getDaysInMonth: function(year, month) {
+               return 32 - 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[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) {
+               // during range selection, use minimum of selected date and range start
+               var newMinDate = (!inst.rangeStart ? null : this._daylightSavingAdjust(
+                       new Date(inst.selectedYear, inst.selectedMonth, inst.selectedDay)));
+               newMinDate = (newMinDate && inst.rangeStart < newMinDate ? inst.rangeStart : newMinDate);
+               var minDate = newMinDate || this._getMinMaxDate(inst, 'min');
+               var maxDate = this._getMinMaxDate(inst, 'max');
+               return ((!minDate || date >= minDate) && (!maxDate || date <= maxDate));
+       },
+
+       /* 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));
+       }
+});
+
+/* 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){
+
+       /* 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'))
+               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.7.2";
+
+// Workaround for #4055
+// Add another global to avoid noConflict issues with inline event handlers
+window.DP_jQuery = $;
+
+})(jQuery);
+/* JavaScript for MediaWIki JS2 */
+
+/**
+ * This is designed to be directly compatible with (and is essentially taken
+ * directly from) the mv_embed code for bringing internationalized messages into
+ * the JavaScript space. As such, if we get to the point of merging that stuff
+ * into the main branch this code will be uneeded and probably cause issues.
+ */
+// Creates global message object if not already in existence
+if ( !gMsg ) var gMsg = {};
+/**
+ * Caches a list of messages for later retrieval
+ * @param {Object} msgSet Hash of key:value pairs of messages to cache
+ */
+function loadGM( msgSet ){
+       for ( var i in msgSet ){
+               gMsg[ i ] = msgSet[i];
+       }
+}
+/**
+ * Retieves a message from the global message cache, performing on-the-fly
+ * replacements using MediaWiki message syntax ($1, $2, etc.)
+ * @param {String} key Name of message as it is in MediaWiki
+ * @param {Array} args Array of replacement arguments
+ */
+function gM( key, args ) {
+       var ms = '';    
+       if ( key in gMsg ) {
+               ms = gMsg[ key ];
+               if ( typeof args == 'object' || typeof args == 'array' ) {
+                       for ( var v in args ){
+                               var rep = '\$'+ ( parseInt(v) + 1 );
+                               ms = ms.replace( rep, args[v]);
+                       }
+               } else if ( typeof args =='string' || typeof args =='number' ) {
+                       ms = ms.replace( /\$1/, args );
+               }
+               return ms;
+       } else {
+               return '[' + key + ']';
+       }
+}
+/**
+ * Mimics the no-conflict method used by the js2 stuff
+ */
+$j = jQuery.noConflict();
+/**
+ * Provides js2 compatible onload hook
+ * @param func Function to call when ready
+ */
+function js2AddOnloadHook( func ) {
+       $j(document).ready( func );
+}
+
+// Define a dummy mvJsLoader.doLoad() function
+mvJsLoader = { doLoad: function( deps, callback ) { callback(); } };
diff --git a/js2/js2stopgap.min.js b/js2/js2stopgap.min.js
new file mode 100644 (file)
index 0000000..94cd141
--- /dev/null
@@ -0,0 +1,782 @@
+
+(function(){var
+window=this,undefined,_jQuery=window.jQuery,_$=window.$,jQuery=window.jQuery=window.$=function(selector,context){return new jQuery.fn.init(selector,context);},quickExpr=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,isSimple=/^.[^:#\[\.,]*$/;jQuery.fn=jQuery.prototype={init:function(selector,context){selector=selector||document;if(selector.nodeType){this[0]=selector;this.length=1;this.context=selector;return this;}
+if(typeof selector==="string"){var match=quickExpr.exec(selector);if(match&&(match[1]||!context)){if(match[1])
+selector=jQuery.clean([match[1]],context);else{var elem=document.getElementById(match[3]);if(elem&&elem.id!=match[3])
+return jQuery().find(selector);var ret=jQuery(elem||[]);ret.context=document;ret.selector=selector;return ret;}}else
+return jQuery(context).find(selector);}else if(jQuery.isFunction(selector))
+return jQuery(document).ready(selector);if(selector.selector&&selector.context){this.selector=selector.selector;this.context=selector.context;}
+return this.setArray(jQuery.isArray(selector)?selector:jQuery.makeArray(selector));},selector:"",jquery:"1.3.2",size:function(){return this.length;},get:function(num){return num===undefined?Array.prototype.slice.call(this):this[num];},pushStack:function(elems,name,selector){var ret=jQuery(elems);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 ret;},setArray:function(elems){this.length=0;Array.prototype.push.apply(this,elems);return this;},each:function(callback,args){return jQuery.each(this,callback,args);},index:function(elem){return jQuery.inArray(elem&&elem.jquery?elem[0]:elem,this);},attr:function(name,value,type){var options=name;if(typeof name==="string")
+if(value===undefined)
+return this[0]&&jQuery[type||"attr"](this[0],name);else{options={};options[name]=value;}
+return this.each(function(i){for(name in options)
+jQuery.attr(type?this.style:this,name,jQuery.prop(this,options[name],type,i,name));});},css:function(key,value){if((key=='width'||key=='height')&&parseFloat(value)<0)
+value=undefined;return this.attr(key,value,"curCSS");},text:function(text){if(typeof text!=="object"&&text!=null)
+return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(text));var ret="";jQuery.each(text||this,function(){jQuery.each(this.childNodes,function(){if(this.nodeType!=8)
+ret+=this.nodeType!=1?this.nodeValue:jQuery.fn.text([this]);});});return ret;},wrapAll:function(html){if(this[0]){var wrap=jQuery(html,this[0].ownerDocument).clone();if(this[0].parentNode)
+wrap.insertBefore(this[0]);wrap.map(function(){var elem=this;while(elem.firstChild)
+elem=elem.firstChild;return elem;}).append(this);}
+return this;},wrapInner:function(html){return this.each(function(){jQuery(this).contents().wrapAll(html);});},wrap:function(html){return this.each(function(){jQuery(this).wrapAll(html);});},append:function(){return this.domManip(arguments,true,function(elem){if(this.nodeType==1)
+this.appendChild(elem);});},prepend:function(){return this.domManip(arguments,true,function(elem){if(this.nodeType==1)
+this.insertBefore(elem,this.firstChild);});},before:function(){return this.domManip(arguments,false,function(elem){this.parentNode.insertBefore(elem,this);});},after:function(){return this.domManip(arguments,false,function(elem){this.parentNode.insertBefore(elem,this.nextSibling);});},end:function(){return this.prevObject||jQuery([]);},push:[].push,sort:[].sort,splice:[].splice,find:function(selector){if(this.length===1){var ret=this.pushStack([],"find",selector);ret.length=0;jQuery.find(selector,this[0],ret);return ret;}else{return this.pushStack(jQuery.unique(jQuery.map(this,function(elem){return jQuery.find(selector,elem);})),"find",selector);}},clone:function(events){var ret=this.map(function(){if(!jQuery.support.noCloneEvent&&!jQuery.isXMLDoc(this)){var html=this.outerHTML;if(!html){var div=this.ownerDocument.createElement("div");div.appendChild(this.cloneNode(true));html=div.innerHTML;}
+return jQuery.clean([html.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0];}else
+return this.cloneNode(true);});if(events===true){var orig=this.find("*").andSelf(),i=0;ret.find("*").andSelf().each(function(){if(this.nodeName!==orig[i].nodeName)
+return;var events=jQuery.data(orig[i],"events");for(var type in events){for(var handler in events[type]){jQuery.event.add(this,type,events[type][handler],events[type][handler].data);}}
+i++;});}
+return ret;},filter:function(selector){return this.pushStack(jQuery.isFunction(selector)&&jQuery.grep(this,function(elem,i){return selector.call(elem,i);})||jQuery.multiFilter(selector,jQuery.grep(this,function(elem){return elem.nodeType===1;})),"filter",selector);},closest:function(selector){var pos=jQuery.expr.match.POS.test(selector)?jQuery(selector):null,closer=0;return this.map(function(){var cur=this;while(cur&&cur.ownerDocument){if(pos?pos.index(cur)>-1:jQuery(cur).is(selector)){jQuery.data(cur,"closest",closer);return cur;}
+cur=cur.parentNode;closer++;}});},not:function(selector){if(typeof selector==="string")
+if(isSimple.test(selector))
+return this.pushStack(jQuery.multiFilter(selector,this,true),"not",selector);else
+selector=jQuery.multiFilter(selector,this);var isArrayLike=selector.length&&selector[selector.length-1]!==undefined&&!selector.nodeType;return this.filter(function(){return isArrayLike?jQuery.inArray(this,selector)<0:this!=selector;});},add:function(selector){return this.pushStack(jQuery.unique(jQuery.merge(this.get(),typeof selector==="string"?jQuery(selector):jQuery.makeArray(selector))));},is:function(selector){return!!selector&&jQuery.multiFilter(selector,this).length>0;},hasClass:function(selector){return!!selector&&this.is("."+selector);},val:function(value){if(value===undefined){var elem=this[0];if(elem){if(jQuery.nodeName(elem,'option'))
+return(elem.attributes.value||{}).specified?elem.value:elem.text;if(jQuery.nodeName(elem,"select")){var index=elem.selectedIndex,values=[],options=elem.options,one=elem.type=="select-one";if(index<0)
+return null;for(var i=one?index:0,max=one?index+1:options.length;i<max;i++){var option=options[i];if(option.selected){value=jQuery(option).val();if(one)
+return value;values.push(value);}}
+return values;}
+return(elem.value||"").replace(/\r/g,"");}
+return undefined;}
+if(typeof value==="number")
+value+='';return this.each(function(){if(this.nodeType!=1)
+return;if(jQuery.isArray(value)&&/radio|checkbox/.test(this.type))
+this.checked=(jQuery.inArray(this.value,value)>=0||jQuery.inArray(this.name,value)>=0);else if(jQuery.nodeName(this,"select")){var values=jQuery.makeArray(value);jQuery("option",this).each(function(){this.selected=(jQuery.inArray(this.value,values)>=0||jQuery.inArray(this.text,values)>=0);});if(!values.length)
+this.selectedIndex=-1;}else
+this.value=value;});},html:function(value){return value===undefined?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(value);},replaceWith:function(value){return this.after(value).remove();},eq:function(i){return this.slice(i,+i+1);},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","));},map:function(callback){return this.pushStack(jQuery.map(this,function(elem,i){return callback.call(elem,i,elem);}));},andSelf:function(){return this.add(this.prevObject);},domManip:function(args,table,callback){if(this[0]){var fragment=(this[0].ownerDocument||this[0]).createDocumentFragment(),scripts=jQuery.clean(args,(this[0].ownerDocument||this[0]),fragment),first=fragment.firstChild;if(first)
+for(var i=0,l=this.length;i<l;i++)
+callback.call(root(this[i],first),this.length>1||i>0?fragment.cloneNode(true):fragment);if(scripts)
+jQuery.each(scripts,evalScript);}
+return this;function root(elem,cur){return table&&jQuery.nodeName(elem,"table")&&jQuery.nodeName(cur,"tr")?(elem.getElementsByTagName("tbody")[0]||elem.appendChild(elem.ownerDocument.createElement("tbody"))):elem;}}};jQuery.fn.init.prototype=jQuery.fn;function evalScript(i,elem){if(elem.src)
+jQuery.ajax({url:elem.src,async:false,dataType:"script"});else
+jQuery.globalEval(elem.text||elem.textContent||elem.innerHTML||"");if(elem.parentNode)
+elem.parentNode.removeChild(elem);}
+function now(){return+new Date;}
+jQuery.extend=jQuery.fn.extend=function(){var target=arguments[0]||{},i=1,length=arguments.length,deep=false,options;if(typeof target==="boolean"){deep=target;target=arguments[1]||{};i=2;}
+if(typeof target!=="object"&&!jQuery.isFunction(target))
+target={};if(length==i){target=this;--i;}
+for(;i<length;i++)
+if((options=arguments[i])!=null)
+for(var name in options){var src=target[name],copy=options[name];if(target===copy)
+continue;if(deep&&copy&&typeof copy==="object"&&!copy.nodeType)
+target[name]=jQuery.extend(deep,src||(copy.length!=null?[]:{}),copy);else if(copy!==undefined)
+target[name]=copy;}
+return target;};var exclude=/z-?index|font-?weight|opacity|zoom|line-?height/i,defaultView=document.defaultView||{},toString=Object.prototype.toString;jQuery.extend({noConflict:function(deep){window.$=_$;if(deep)
+window.jQuery=_jQuery;return jQuery;},isFunction:function(obj){return toString.call(obj)==="[object Function]";},isArray:function(obj){return toString.call(obj)==="[object Array]";},isXMLDoc:function(elem){return elem.nodeType===9&&elem.documentElement.nodeName!=="HTML"||!!elem.ownerDocument&&jQuery.isXMLDoc(elem.ownerDocument);},globalEval:function(data){if(data&&/\S/.test(data)){var head=document.getElementsByTagName("head")[0]||document.documentElement,script=document.createElement("script");script.type="text/javascript";if(jQuery.support.scriptEval)
+script.appendChild(document.createTextNode(data));else
+script.text=data;head.insertBefore(script,head.firstChild);head.removeChild(script);}},nodeName:function(elem,name){return elem.nodeName&&elem.nodeName.toUpperCase()==name.toUpperCase();},each:function(object,callback,args){var name,i=0,length=object.length;if(args){if(length===undefined){for(name in object)
+if(callback.apply(object[name],args)===false)
+break;}else
+for(;i<length;)
+if(callback.apply(object[i++],args)===false)
+break;}else{if(length===undefined){for(name in object)
+if(callback.call(object[name],name,object[name])===false)
+break;}else
+for(var value=object[0];i<length&&callback.call(value,i,value)!==false;value=object[++i]){}}
+return object;},prop:function(elem,value,type,i,name){if(jQuery.isFunction(value))
+value=value.call(elem,i);return typeof value==="number"&&type=="curCSS"&&!exclude.test(name)?value+"px":value;},className:{add:function(elem,classNames){jQuery.each((classNames||"").split(/\s+/),function(i,className){if(elem.nodeType==1&&!jQuery.className.has(elem.className,className))
+elem.className+=(elem.className?" ":"")+className;});},remove:function(elem,classNames){if(elem.nodeType==1)
+elem.className=classNames!==undefined?jQuery.grep(elem.className.split(/\s+/),function(className){return!jQuery.className.has(classNames,className);}).join(" "):"";},has:function(elem,className){return elem&&jQuery.inArray(className,(elem.className||elem).toString().split(/\s+/))>-1;}},swap:function(elem,options,callback){var old={};for(var name in options){old[name]=elem.style[name];elem.style[name]=options[name];}
+callback.call(elem);for(var name in options)
+elem.style[name]=old[name];},css:function(elem,name,force,extra){if(name=="width"||name=="height"){var val,props={position:"absolute",visibility:"hidden",display:"block"},which=name=="width"?["Left","Right"]:["Top","Bottom"];function getWH(){val=name=="width"?elem.offsetWidth:elem.offsetHeight;if(extra==="border")
+return;jQuery.each(which,function(){if(!extra)
+val-=parseFloat(jQuery.curCSS(elem,"padding"+this,true))||0;if(extra==="margin")
+val+=parseFloat(jQuery.curCSS(elem,"margin"+this,true))||0;else
+val-=parseFloat(jQuery.curCSS(elem,"border"+this+"Width",true))||0;});}
+if(elem.offsetWidth!==0)
+getWH();else
+jQuery.swap(elem,props,getWH);return Math.max(0,Math.round(val));}
+return jQuery.curCSS(elem,name,force);},curCSS:function(elem,name,force){var ret,style=elem.style;if(name=="opacity"&&!jQuery.support.opacity){ret=jQuery.attr(style,"opacity");return ret==""?"1":ret;}
+if(name.match(/float/i))
+name=styleFloat;if(!force&&style&&style[name])
+ret=style[name];else if(defaultView.getComputedStyle){if(name.match(/float/i))
+name="float";name=name.replace(/([A-Z])/g,"-$1").toLowerCase();var computedStyle=defaultView.getComputedStyle(elem,null);if(computedStyle)
+ret=computedStyle.getPropertyValue(name);if(name=="opacity"&&ret=="")
+ret="1";}else if(elem.currentStyle){var camelCase=name.replace(/\-(\w)/g,function(all,letter){return letter.toUpperCase();});ret=elem.currentStyle[name]||elem.currentStyle[camelCase];if(!/^\d+(px)?$/i.test(ret)&&/^\d/.test(ret)){var left=style.left,rsLeft=elem.runtimeStyle.left;elem.runtimeStyle.left=elem.currentStyle.left;style.left=ret||0;ret=style.pixelLeft+"px";style.left=left;elem.runtimeStyle.left=rsLeft;}}
+return ret;},clean:function(elems,context,fragment){context=context||document;if(typeof context.createElement==="undefined")
+context=context.ownerDocument||context[0]&&context[0].ownerDocument||document;if(!fragment&&elems.length===1&&typeof elems[0]==="string"){var match=/^<(\w+)\s*\/?>$/.exec(elems[0]);if(match)
+return[context.createElement(match[1])];}
+var ret=[],scripts=[],div=context.createElement("div");jQuery.each(elems,function(i,elem){if(typeof elem==="number")
+elem+='';if(!elem)
+return;if(typeof elem==="string"){elem=elem.replace(/(<(\w+)[^>]*?)\/>/g,function(all,front,tag){return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?all:front+"></"+tag+">";});var tags=elem.replace(/^\s+/,"").substring(0,10).toLowerCase();var wrap=!tags.indexOf("<opt")&&[1,"<select multiple='multiple'>","</select>"]||!tags.indexOf("<leg")&&[1,"<fieldset>","</fieldset>"]||tags.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"<table>","</table>"]||!tags.indexOf("<tr")&&[2,"<table><tbody>","</tbody></table>"]||(!tags.indexOf("<td")||!tags.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||!tags.indexOf("<col")&&[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"]||!jQuery.support.htmlSerialize&&[1,"div<div>","</div>"]||[0,"",""];div.innerHTML=wrap[1]+elem+wrap[2];while(wrap[0]--)
+div=div.lastChild;if(!jQuery.support.tbody){var hasBody=/<tbody/i.test(elem),tbody=!tags.indexOf("<table")&&!hasBody?div.firstChild&&div.firstChild.childNodes:wrap[1]=="<table>"&&!hasBody?div.childNodes:[];for(var j=tbody.length-1;j>=0;--j)
+if(jQuery.nodeName(tbody[j],"tbody")&&!tbody[j].childNodes.length)
+tbody[j].parentNode.removeChild(tbody[j]);}
+if(!jQuery.support.leadingWhitespace&&/^\s/.test(elem))
+div.insertBefore(context.createTextNode(elem.match(/^\s*/)[0]),div.firstChild);elem=jQuery.makeArray(div.childNodes);}
+if(elem.nodeType)
+ret.push(elem);else
+ret=jQuery.merge(ret,elem);});if(fragment){for(var i=0;ret[i];i++){if(jQuery.nodeName(ret[i],"script")&&(!ret[i].type||ret[i].type.toLowerCase()==="text/javascript")){scripts.push(ret[i].parentNode?ret[i].parentNode.removeChild(ret[i]):ret[i]);}else{if(ret[i].nodeType===1)
+ret.splice.apply(ret,[i+1,0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))));fragment.appendChild(ret[i]);}}
+return scripts;}
+return ret;},attr:function(elem,name,value){if(!elem||elem.nodeType==3||elem.nodeType==8)
+return undefined;var notxml=!jQuery.isXMLDoc(elem),set=value!==undefined;name=notxml&&jQuery.props[name]||name;if(elem.tagName){var special=/href|src|style/.test(name);if(name=="selected"&&elem.parentNode)
+elem.parentNode.selectedIndex;if(name in elem&&notxml&&!special){if(set){if(name=="type"&&jQuery.nodeName(elem,"input")&&elem.parentNode)
+throw"type property can't be changed";elem[name]=value;}
+if(jQuery.nodeName(elem,"form")&&elem.getAttributeNode(name))
+return elem.getAttributeNode(name).nodeValue;if(name=="tabIndex"){var attributeNode=elem.getAttributeNode("tabIndex");return attributeNode&&attributeNode.specified?attributeNode.value:elem.nodeName.match(/(button|input|object|select|textarea)/i)?0:elem.nodeName.match(/^(a|area)$/i)&&elem.href?0:undefined;}
+return elem[name];}
+if(!jQuery.support.style&&notxml&&name=="style")
+return jQuery.attr(elem.style,"cssText",value);if(set)
+elem.setAttribute(name,""+value);var attr=!jQuery.support.hrefNormalized&&notxml&&special?elem.getAttribute(name,2):elem.getAttribute(name);return attr===null?undefined:attr;}
+if(!jQuery.support.opacity&&name=="opacity"){if(set){elem.zoom=1;elem.filter=(elem.filter||"").replace(/alpha\([^)]*\)/,"")+
+(parseInt(value)+''=="NaN"?"":"alpha(opacity="+value*100+")");}
+return elem.filter&&elem.filter.indexOf("opacity=")>=0?(parseFloat(elem.filter.match(/opacity=([^)]*)/)[1])/100)+'':"";}
+name=name.replace(/-([a-z])/ig,function(all,letter){return letter.toUpperCase();});if(set)
+elem[name]=value;return elem[name];},trim:function(text){return(text||"").replace(/^\s+|\s+$/g,"");},makeArray:function(array){var ret=[];if(array!=null){var i=array.length;if(i==null||typeof array==="string"||jQuery.isFunction(array)||array.setInterval)
+ret[0]=array;else
+while(i)
+ret[--i]=array[i];}
+return ret;},inArray:function(elem,array){for(var i=0,length=array.length;i<length;i++)
+if(array[i]===elem)
+return i;return-1;},merge:function(first,second){var i=0,elem,pos=first.length;if(!jQuery.support.getAll){while((elem=second[i++])!=null)
+if(elem.nodeType!=8)
+first[pos++]=elem;}else
+while((elem=second[i++])!=null)
+first[pos++]=elem;return first;},unique:function(array){var ret=[],done={};try{for(var i=0,length=array.length;i<length;i++){var id=jQuery.data(array[i]);if(!done[id]){done[id]=true;ret.push(array[i]);}}}catch(e){ret=array;}
+return ret;},grep:function(elems,callback,inv){var ret=[];for(var i=0,length=elems.length;i<length;i++)
+if(!inv!=!callback(elems[i],i))
+ret.push(elems[i]);return ret;},map:function(elems,callback){var ret=[];for(var i=0,length=elems.length;i<length;i++){var value=callback(elems[i],i);if(value!=null)
+ret[ret.length]=value;}
+return ret.concat.apply([],ret);}});var userAgent=navigator.userAgent.toLowerCase();jQuery.browser={version:(userAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)||[0,'0'])[1],safari:/webkit/.test(userAgent),opera:/opera/.test(userAgent),msie:/msie/.test(userAgent)&&!/opera/.test(userAgent),mozilla:/mozilla/.test(userAgent)&&!/(compatible|webkit)/.test(userAgent)};jQuery.each({parent:function(elem){return elem.parentNode;},parents:function(elem){return jQuery.dir(elem,"parentNode");},next:function(elem){return jQuery.nth(elem,2,"nextSibling");},prev:function(elem){return jQuery.nth(elem,2,"previousSibling");},nextAll:function(elem){return jQuery.dir(elem,"nextSibling");},prevAll:function(elem){return jQuery.dir(elem,"previousSibling");},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.makeArray(elem.childNodes);}},function(name,fn){jQuery.fn[name]=function(selector){var ret=jQuery.map(this,fn);if(selector&&typeof selector=="string")
+ret=jQuery.multiFilter(selector,ret);return this.pushStack(jQuery.unique(ret),name,selector);};});jQuery.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(name,original){jQuery.fn[name]=function(selector){var ret=[],insert=jQuery(selector);for(var i=0,l=insert.length;i<l;i++){var elems=(i>0?this.clone(true):this).get();jQuery.fn[original].apply(jQuery(insert[i]),elems);ret=ret.concat(elems);}
+return this.pushStack(ret,name,selector);};});jQuery.each({removeAttr:function(name){jQuery.attr(this,name,"");if(this.nodeType==1)
+this.removeAttribute(name);},addClass:function(classNames){jQuery.className.add(this,classNames);},removeClass:function(classNames){jQuery.className.remove(this,classNames);},toggleClass:function(classNames,state){if(typeof state!=="boolean")
+state=!jQuery.className.has(this,classNames);jQuery.className[state?"add":"remove"](this,classNames);},remove:function(selector){if(!selector||jQuery.filter(selector,[this]).length){jQuery("*",this).add([this]).each(function(){jQuery.event.remove(this);jQuery.removeData(this);});if(this.parentNode)
+this.parentNode.removeChild(this);}},empty:function(){jQuery(this).children().remove();while(this.firstChild)
+this.removeChild(this.firstChild);}},function(name,fn){jQuery.fn[name]=function(){return this.each(fn,arguments);};});function num(elem,prop){return elem[0]&&parseInt(jQuery.curCSS(elem[0],prop,true),10)||0;}
+var expando="jQuery"+now(),uuid=0,windowData={};jQuery.extend({cache:{},data:function(elem,name,data){elem=elem==window?windowData:elem;var id=elem[expando];if(!id)
+id=elem[expando]=++uuid;if(name&&!jQuery.cache[id])
+jQuery.cache[id]={};if(data!==undefined)
+jQuery.cache[id][name]=data;return name?jQuery.cache[id][name]:id;},removeData:function(elem,name){elem=elem==window?windowData:elem;var id=elem[expando];if(name){if(jQuery.cache[id]){delete jQuery.cache[id][name];name="";for(name in jQuery.cache[id])
+break;if(!name)
+jQuery.removeData(elem);}}else{try{delete elem[expando];}catch(e){if(elem.removeAttribute)
+elem.removeAttribute(expando);}
+delete jQuery.cache[id];}},queue:function(elem,type,data){if(elem){type=(type||"fx")+"queue";var q=jQuery.data(elem,type);if(!q||jQuery.isArray(data))
+q=jQuery.data(elem,type,jQuery.makeArray(data));else if(data)
+q.push(data);}
+return q;},dequeue:function(elem,type){var queue=jQuery.queue(elem,type),fn=queue.shift();if(!type||type==="fx")
+fn=queue[0];if(fn!==undefined)
+fn.call(elem);}});jQuery.fn.extend({data:function(key,value){var parts=key.split(".");parts[1]=parts[1]?"."+parts[1]:"";if(value===undefined){var data=this.triggerHandler("getData"+parts[1]+"!",[parts[0]]);if(data===undefined&&this.length)
+data=jQuery.data(this[0],key);return data===undefined&&parts[1]?this.data(parts[0]):data;}else
+return this.trigger("setData"+parts[1]+"!",[parts[0],value]).each(function(){jQuery.data(this,key,value);});},removeData:function(key){return this.each(function(){jQuery.removeData(this,key);});},queue:function(type,data){if(typeof type!=="string"){data=type;type="fx";}
+if(data===undefined)
+return jQuery.queue(this[0],type);return this.each(function(){var queue=jQuery.queue(this,type,data);if(type=="fx"&&queue.length==1)
+queue[0].call(this);});},dequeue:function(type){return this.each(function(){jQuery.dequeue(this,type);});}});(function(){var chunker=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,done=0,toString=Object.prototype.toString;var Sizzle=function(selector,context,results,seed){results=results||[];context=context||document;if(context.nodeType!==1&&context.nodeType!==9)
+return[];if(!selector||typeof selector!=="string"){return results;}
+var parts=[],m,set,checkSet,check,mode,extra,prune=true;chunker.lastIndex=0;while((m=chunker.exec(selector))!==null){parts.push(m[1]);if(m[2]){extra=RegExp.rightContext;break;}}
+if(parts.length>1&&origPOS.exec(selector)){if(parts.length===2&&Expr.relative[parts[0]]){set=posProcess(parts[0]+parts[1],context);}else{set=Expr.relative[parts[0]]?[context]:Sizzle(parts.shift(),context);while(parts.length){selector=parts.shift();if(Expr.relative[selector])
+selector+=parts.shift();set=posProcess(selector,set);}}}else{var ret=seed?{expr:parts.pop(),set:makeArray(seed)}:Sizzle.find(parts.pop(),parts.length===1&&context.parentNode?context.parentNode:context,isXML(context));set=Sizzle.filter(ret.expr,ret.set);if(parts.length>0){checkSet=makeArray(set);}else{prune=false;}
+while(parts.length){var cur=parts.pop(),pop=cur;if(!Expr.relative[cur]){cur="";}else{pop=parts.pop();}
+if(pop==null){pop=context;}
+Expr.relative[cur](checkSet,pop,isXML(context));}}
+if(!checkSet){checkSet=set;}
+if(!checkSet){throw"Syntax error, unrecognized expression: "+(cur||selector);}
+if(toString.call(checkSet)==="[object Array]"){if(!prune){results.push.apply(results,checkSet);}else if(context.nodeType===1){for(var i=0;checkSet[i]!=null;i++){if(checkSet[i]&&(checkSet[i]===true||checkSet[i].nodeType===1&&contains(context,checkSet[i]))){results.push(set[i]);}}}else{for(var i=0;checkSet[i]!=null;i++){if(checkSet[i]&&checkSet[i].nodeType===1){results.push(set[i]);}}}}else{makeArray(checkSet,results);}
+if(extra){Sizzle(extra,context,results,seed);if(sortOrder){hasDuplicate=false;results.sort(sortOrder);if(hasDuplicate){for(var i=1;i<results.length;i++){if(results[i]===results[i-1]){results.splice(i--,1);}}}}}
+return results;};Sizzle.matches=function(expr,set){return Sizzle(expr,null,null,set);};Sizzle.find=function(expr,context,isXML){var set,match;if(!expr){return[];}
+for(var i=0,l=Expr.order.length;i<l;i++){var type=Expr.order[i],match;if((match=Expr.match[type].exec(expr))){var left=RegExp.leftContext;if(left.substr(left.length-1)!=="\\"){match[1]=(match[1]||"").replace(/\\/g,"");set=Expr.find[type](match,context,isXML);if(set!=null){expr=expr.replace(Expr.match[type],"");break;}}}}
+if(!set){set=context.getElementsByTagName("*");}
+return{set:set,expr:expr};};Sizzle.filter=function(expr,set,inplace,not){var old=expr,result=[],curLoop=set,match,anyFound,isXMLFilter=set&&set[0]&&isXML(set[0]);while(expr&&set.length){for(var type in Expr.filter){if((match=Expr.match[type].exec(expr))!=null){var filter=Expr.filter[type],found,item;anyFound=false;if(curLoop==result){result=[];}
+if(Expr.preFilter[type]){match=Expr.preFilter[type](match,curLoop,inplace,result,not,isXMLFilter);if(!match){anyFound=found=true;}else if(match===true){continue;}}
+if(match){for(var i=0;(item=curLoop[i])!=null;i++){if(item){found=filter(item,match,i,curLoop);var pass=not^!!found;if(inplace&&found!=null){if(pass){anyFound=true;}else{curLoop[i]=false;}}else if(pass){result.push(item);anyFound=true;}}}}
+if(found!==undefined){if(!inplace){curLoop=result;}
+expr=expr.replace(Expr.match[type],"");if(!anyFound){return[];}
+break;}}}
+if(expr==old){if(anyFound==null){throw"Syntax error, unrecognized expression: "+expr;}else{break;}}
+old=expr;}
+return curLoop;};var Expr=Sizzle.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(elem){return elem.getAttribute("href");}},relative:{"+":function(checkSet,part,isXML){var isPartStr=typeof part==="string",isTag=isPartStr&&!/\W/.test(part),isPartStrNotTag=isPartStr&&!isTag;if(isTag&&!isXML){part=part.toUpperCase();}
+for(var i=0,l=checkSet.length,elem;i<l;i++){if((elem=checkSet[i])){while((elem=elem.previousSibling)&&elem.nodeType!==1){}
+checkSet[i]=isPartStrNotTag||elem&&elem.nodeName===part?elem||false:elem===part;}}
+if(isPartStrNotTag){Sizzle.filter(part,checkSet,true);}},">":function(checkSet,part,isXML){var isPartStr=typeof part==="string";if(isPartStr&&!/\W/.test(part)){part=isXML?part:part.toUpperCase();for(var i=0,l=checkSet.length;i<l;i++){var elem=checkSet[i];if(elem){var parent=elem.parentNode;checkSet[i]=parent.nodeName===part?parent:false;}}}else{for(var i=0,l=checkSet.length;i<l;i++){var elem=checkSet[i];if(elem){checkSet[i]=isPartStr?elem.parentNode:elem.parentNode===part;}}
+if(isPartStr){Sizzle.filter(part,checkSet,true);}}},"":function(checkSet,part,isXML){var doneName=done++,checkFn=dirCheck;if(!part.match(/\W/)){var nodeCheck=part=isXML?part:part.toUpperCase();checkFn=dirNodeCheck;}
+checkFn("parentNode",part,doneName,checkSet,nodeCheck,isXML);},"~":function(checkSet,part,isXML){var doneName=done++,checkFn=dirCheck;if(typeof part==="string"&&!part.match(/\W/)){var nodeCheck=part=isXML?part:part.toUpperCase();checkFn=dirNodeCheck;}
+checkFn("previousSibling",part,doneName,checkSet,nodeCheck,isXML);}},find:{ID:function(match,context,isXML){if(typeof context.getElementById!=="undefined"&&!isXML){var m=context.getElementById(match[1]);return m?[m]:[];}},NAME:function(match,context,isXML){if(typeof context.getElementsByName!=="undefined"){var ret=[],results=context.getElementsByName(match[1]);for(var i=0,l=results.length;i<l;i++){if(results[i].getAttribute("name")===match[1]){ret.push(results[i]);}}
+return ret.length===0?null:ret;}},TAG:function(match,context){return context.getElementsByTagName(match[1]);}},preFilter:{CLASS:function(match,curLoop,inplace,result,not,isXML){match=" "+match[1].replace(/\\/g,"")+" ";if(isXML){return match;}
+for(var i=0,elem;(elem=curLoop[i])!=null;i++){if(elem){if(not^(elem.className&&(" "+elem.className+" ").indexOf(match)>=0)){if(!inplace)
+result.push(elem);}else if(inplace){curLoop[i]=false;}}}
+return false;},ID:function(match){return match[1].replace(/\\/g,"");},TAG:function(match,curLoop){for(var i=0;curLoop[i]===false;i++){}
+return curLoop[i]&&isXML(curLoop[i])?match[1]:match[1].toUpperCase();},CHILD:function(match){if(match[1]=="nth"){var test=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(match[2]=="even"&&"2n"||match[2]=="odd"&&"2n+1"||!/\D/.test(match[2])&&"0n+"+match[2]||match[2]);match[2]=(test[1]+(test[2]||1))-0;match[3]=test[3]-0;}
+match[0]=done++;return match;},ATTR:function(match,curLoop,inplace,result,not,isXML){var name=match[1].replace(/\\/g,"");if(!isXML&&Expr.attrMap[name]){match[1]=Expr.attrMap[name];}
+if(match[2]==="~="){match[4]=" "+match[4]+" ";}
+return match;},PSEUDO:function(match,curLoop,inplace,result,not){if(match[1]==="not"){if(match[3].match(chunker).length>1||/^\w/.test(match[3])){match[3]=Sizzle(match[3],null,null,curLoop);}else{var ret=Sizzle.filter(match[3],curLoop,inplace,true^not);if(!inplace){result.push.apply(result,ret);}
+return false;}}else if(Expr.match.POS.test(match[0])||Expr.match.CHILD.test(match[0])){return true;}
+return match;},POS:function(match){match.unshift(true);return match;}},filters:{enabled:function(elem){return elem.disabled===false&&elem.type!=="hidden";},disabled:function(elem){return elem.disabled===true;},checked:function(elem){return elem.checked===true;},selected:function(elem){elem.parentNode.selectedIndex;return elem.selected===true;},parent:function(elem){return!!elem.firstChild;},empty:function(elem){return!elem.firstChild;},has:function(elem,i,match){return!!Sizzle(match[3],elem).length;},header:function(elem){return/h\d/i.test(elem.nodeName);},text:function(elem){return"text"===elem.type;},radio:function(elem){return"radio"===elem.type;},checkbox:function(elem){return"checkbox"===elem.type;},file:function(elem){return"file"===elem.type;},password:function(elem){return"password"===elem.type;},submit:function(elem){return"submit"===elem.type;},image:function(elem){return"image"===elem.type;},reset:function(elem){return"reset"===elem.type;},button:function(elem){return"button"===elem.type||elem.nodeName.toUpperCase()==="BUTTON";},input:function(elem){return/input|select|textarea|button/i.test(elem.nodeName);}},setFilters:{first:function(elem,i){return i===0;},last:function(elem,i,match,array){return i===array.length-1;},even:function(elem,i){return i%2===0;},odd:function(elem,i){return i%2===1;},lt:function(elem,i,match){return i<match[3]-0;},gt:function(elem,i,match){return i>match[3]-0;},nth:function(elem,i,match){return match[3]-0==i;},eq:function(elem,i,match){return match[3]-0==i;}},filter:{PSEUDO:function(elem,match,i,array){var name=match[1],filter=Expr.filters[name];if(filter){return filter(elem,i,match,array);}else if(name==="contains"){return(elem.textContent||elem.innerText||"").indexOf(match[3])>=0;}else if(name==="not"){var not=match[3];for(var i=0,l=not.length;i<l;i++){if(not[i]===elem){return false;}}
+return true;}},CHILD:function(elem,match){var type=match[1],node=elem;switch(type){case'only':case'first':while(node=node.previousSibling){if(node.nodeType===1)return false;}
+if(type=='first')return true;node=elem;case'last':while(node=node.nextSibling){if(node.nodeType===1)return false;}
+return true;case'nth':var first=match[2],last=match[3];if(first==1&&last==0){return true;}
+var doneName=match[0],parent=elem.parentNode;if(parent&&(parent.sizcache!==doneName||!elem.nodeIndex)){var count=0;for(node=parent.firstChild;node;node=node.nextSibling){if(node.nodeType===1){node.nodeIndex=++count;}}
+parent.sizcache=doneName;}
+var diff=elem.nodeIndex-last;if(first==0){return diff==0;}else{return(diff%first==0&&diff/first>=0);}}},ID:function(elem,match){return elem.nodeType===1&&elem.getAttribute("id")===match;},TAG:function(elem,match){return(match==="*"&&elem.nodeType===1)||elem.nodeName===match;},CLASS:function(elem,match){return(" "+(elem.className||elem.getAttribute("class"))+" ").indexOf(match)>-1;},ATTR:function(elem,match){var name=match[1],result=Expr.attrHandle[name]?Expr.attrHandle[name](elem):elem[name]!=null?elem[name]:elem.getAttribute(name),value=result+"",type=match[2],check=match[4];return result==null?type==="!=":type==="="?value===check:type==="*="?value.indexOf(check)>=0:type==="~="?(" "+value+" ").indexOf(check)>=0:!check?value&&result!==false:type==="!="?value!=check:type==="^="?value.indexOf(check)===0:type==="$="?value.substr(value.length-check.length)===check:type==="|="?value===check||value.substr(0,check.length+1)===check+"-":false;},POS:function(elem,match,i,array){var name=match[2],filter=Expr.setFilters[name];if(filter){return filter(elem,i,match,array);}}}};var origPOS=Expr.match.POS;for(var type in Expr.match){Expr.match[type]=RegExp(Expr.match[type].source+/(?![^\[]*\])(?![^\(]*\))/.source);}
+var makeArray=function(array,results){array=Array.prototype.slice.call(array);if(results){results.push.apply(results,array);return results;}
+return array;};try{Array.prototype.slice.call(document.documentElement.childNodes);}catch(e){makeArray=function(array,results){var ret=results||[];if(toString.call(array)==="[object Array]"){Array.prototype.push.apply(ret,array);}else{if(typeof array.length==="number"){for(var i=0,l=array.length;i<l;i++){ret.push(array[i]);}}else{for(var i=0;array[i];i++){ret.push(array[i]);}}}
+return ret;};}
+var sortOrder;if(document.documentElement.compareDocumentPosition){sortOrder=function(a,b){var ret=a.compareDocumentPosition(b)&4?-1:a===b?0:1;if(ret===0){hasDuplicate=true;}
+return ret;};}else if("sourceIndex"in document.documentElement){sortOrder=function(a,b){var ret=a.sourceIndex-b.sourceIndex;if(ret===0){hasDuplicate=true;}
+return ret;};}else if(document.createRange){sortOrder=function(a,b){var aRange=a.ownerDocument.createRange(),bRange=b.ownerDocument.createRange();aRange.selectNode(a);aRange.collapse(true);bRange.selectNode(b);bRange.collapse(true);var ret=aRange.compareBoundaryPoints(Range.START_TO_END,bRange);if(ret===0){hasDuplicate=true;}
+return ret;};}
+(function(){var form=document.createElement("form"),id="script"+(new Date).getTime();form.innerHTML="<input name='"+id+"'/>";var root=document.documentElement;root.insertBefore(form,root.firstChild);if(!!document.getElementById(id)){Expr.find.ID=function(match,context,isXML){if(typeof context.getElementById!=="undefined"&&!isXML){var m=context.getElementById(match[1]);return m?m.id===match[1]||typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id").nodeValue===match[1]?[m]:undefined:[];}};Expr.filter.ID=function(elem,match){var node=typeof elem.getAttributeNode!=="undefined"&&elem.getAttributeNode("id");return elem.nodeType===1&&node&&node.nodeValue===match;};}
+root.removeChild(form);})();(function(){var div=document.createElement("div");div.appendChild(document.createComment(""));if(div.getElementsByTagName("*").length>0){Expr.find.TAG=function(match,context){var results=context.getElementsByTagName(match[1]);if(match[1]==="*"){var tmp=[];for(var i=0;results[i];i++){if(results[i].nodeType===1){tmp.push(results[i]);}}
+results=tmp;}
+return results;};}
+div.innerHTML="<a href='#'></a>";if(div.firstChild&&typeof div.firstChild.getAttribute!=="undefined"&&div.firstChild.getAttribute("href")!=="#"){Expr.attrHandle.href=function(elem){return elem.getAttribute("href",2);};}})();if(document.querySelectorAll)(function(){var oldSizzle=Sizzle,div=document.createElement("div");div.innerHTML="<p class='TEST'></p>";if(div.querySelectorAll&&div.querySelectorAll(".TEST").length===0){return;}
+Sizzle=function(query,context,extra,seed){context=context||document;if(!seed&&context.nodeType===9&&!isXML(context)){try{return makeArray(context.querySelectorAll(query),extra);}catch(e){}}
+return oldSizzle(query,context,extra,seed);};Sizzle.find=oldSizzle.find;Sizzle.filter=oldSizzle.filter;Sizzle.selectors=oldSizzle.selectors;Sizzle.matches=oldSizzle.matches;})();if(document.getElementsByClassName&&document.documentElement.getElementsByClassName)(function(){var div=document.createElement("div");div.innerHTML="<div class='test e'></div><div class='test'></div>";if(div.getElementsByClassName("e").length===0)
+return;div.lastChild.className="e";if(div.getElementsByClassName("e").length===1)
+return;Expr.order.splice(1,0,"CLASS");Expr.find.CLASS=function(match,context,isXML){if(typeof context.getElementsByClassName!=="undefined"&&!isXML){return context.getElementsByClassName(match[1]);}};})();function dirNodeCheck(dir,cur,doneName,checkSet,nodeCheck,isXML){var sibDir=dir=="previousSibling"&&!isXML;for(var i=0,l=checkSet.length;i<l;i++){var elem=checkSet[i];if(elem){if(sibDir&&elem.nodeType===1){elem.sizcache=doneName;elem.sizset=i;}
+elem=elem[dir];var match=false;while(elem){if(elem.sizcache===doneName){match=checkSet[elem.sizset];break;}
+if(elem.nodeType===1&&!isXML){elem.sizcache=doneName;elem.sizset=i;}
+if(elem.nodeName===cur){match=elem;break;}
+elem=elem[dir];}
+checkSet[i]=match;}}}
+function dirCheck(dir,cur,doneName,checkSet,nodeCheck,isXML){var sibDir=dir=="previousSibling"&&!isXML;for(var i=0,l=checkSet.length;i<l;i++){var elem=checkSet[i];if(elem){if(sibDir&&elem.nodeType===1){elem.sizcache=doneName;elem.sizset=i;}
+elem=elem[dir];var match=false;while(elem){if(elem.sizcache===doneName){match=checkSet[elem.sizset];break;}
+if(elem.nodeType===1){if(!isXML){elem.sizcache=doneName;elem.sizset=i;}
+if(typeof cur!=="string"){if(elem===cur){match=true;break;}}else if(Sizzle.filter(cur,[elem]).length>0){match=elem;break;}}
+elem=elem[dir];}
+checkSet[i]=match;}}}
+var contains=document.compareDocumentPosition?function(a,b){return a.compareDocumentPosition(b)&16;}:function(a,b){return a!==b&&(a.contains?a.contains(b):true);};var isXML=function(elem){return elem.nodeType===9&&elem.documentElement.nodeName!=="HTML"||!!elem.ownerDocument&&isXML(elem.ownerDocument);};var posProcess=function(selector,context){var tmpSet=[],later="",match,root=context.nodeType?[context]:context;while((match=Expr.match.PSEUDO.exec(selector))){later+=match[0];selector=selector.replace(Expr.match.PSEUDO,"");}
+selector=Expr.relative[selector]?selector+"*":selector;for(var i=0,l=root.length;i<l;i++){Sizzle(selector,root[i],tmpSet);}
+return Sizzle.filter(later,tmpSet);};jQuery.find=Sizzle;jQuery.filter=Sizzle.filter;jQuery.expr=Sizzle.selectors;jQuery.expr[":"]=jQuery.expr.filters;Sizzle.selectors.filters.hidden=function(elem){return elem.offsetWidth===0||elem.offsetHeight===0;};Sizzle.selectors.filters.visible=function(elem){return elem.offsetWidth>0||elem.offsetHeight>0;};Sizzle.selectors.filters.animated=function(elem){return jQuery.grep(jQuery.timers,function(fn){return elem===fn.elem;}).length;};jQuery.multiFilter=function(expr,elems,not){if(not){expr=":not("+expr+")";}
+return Sizzle.matches(expr,elems);};jQuery.dir=function(elem,dir){var matched=[],cur=elem[dir];while(cur&&cur!=document){if(cur.nodeType==1)
+matched.push(cur);cur=cur[dir];}
+return matched;};jQuery.nth=function(cur,result,dir,elem){result=result||1;var num=0;for(;cur;cur=cur[dir])
+if(cur.nodeType==1&&++num==result)
+break;return cur;};jQuery.sibling=function(n,elem){var r=[];for(;n;n=n.nextSibling){if(n.nodeType==1&&n!=elem)
+r.push(n);}
+return r;};return;window.Sizzle=Sizzle;})();jQuery.event={add:function(elem,types,handler,data){if(elem.nodeType==3||elem.nodeType==8)
+return;if(elem.setInterval&&elem!=window)
+elem=window;if(!handler.guid)
+handler.guid=this.guid++;if(data!==undefined){var fn=handler;handler=this.proxy(fn);handler.data=data;}
+var events=jQuery.data(elem,"events")||jQuery.data(elem,"events",{}),handle=jQuery.data(elem,"handle")||jQuery.data(elem,"handle",function(){return typeof jQuery!=="undefined"&&!jQuery.event.triggered?jQuery.event.handle.apply(arguments.callee.elem,arguments):undefined;});handle.elem=elem;jQuery.each(types.split(/\s+/),function(index,type){var namespaces=type.split(".");type=namespaces.shift();handler.type=namespaces.slice().sort().join(".");var handlers=events[type];if(jQuery.event.specialAll[type])
+jQuery.event.specialAll[type].setup.call(elem,data,namespaces);if(!handlers){handlers=events[type]={};if(!jQuery.event.special[type]||jQuery.event.special[type].setup.call(elem,data,namespaces)===false){if(elem.addEventListener)
+elem.addEventListener(type,handle,false);else if(elem.attachEvent)
+elem.attachEvent("on"+type,handle);}}
+handlers[handler.guid]=handler;jQuery.event.global[type]=true;});elem=null;},guid:1,global:{},remove:function(elem,types,handler){if(elem.nodeType==3||elem.nodeType==8)
+return;var events=jQuery.data(elem,"events"),ret,index;if(events){if(types===undefined||(typeof types==="string"&&types.charAt(0)=="."))
+for(var type in events)
+this.remove(elem,type+(types||""));else{if(types.type){handler=types.handler;types=types.type;}
+jQuery.each(types.split(/\s+/),function(index,type){var namespaces=type.split(".");type=namespaces.shift();var namespace=RegExp("(^|\\.)"+namespaces.slice().sort().join(".*\\.")+"(\\.|$)");if(events[type]){if(handler)
+delete events[type][handler.guid];else
+for(var handle in events[type])
+if(namespace.test(events[type][handle].type))
+delete events[type][handle];if(jQuery.event.specialAll[type])
+jQuery.event.specialAll[type].teardown.call(elem,namespaces);for(ret in events[type])break;if(!ret){if(!jQuery.event.special[type]||jQuery.event.special[type].teardown.call(elem,namespaces)===false){if(elem.removeEventListener)
+elem.removeEventListener(type,jQuery.data(elem,"handle"),false);else if(elem.detachEvent)
+elem.detachEvent("on"+type,jQuery.data(elem,"handle"));}
+ret=null;delete events[type];}}});}
+for(ret in events)break;if(!ret){var handle=jQuery.data(elem,"handle");if(handle)handle.elem=null;jQuery.removeData(elem,"events");jQuery.removeData(elem,"handle");}}},trigger:function(event,data,elem,bubbling){var type=event.type||event;if(!bubbling){event=typeof event==="object"?event[expando]?event:jQuery.extend(jQuery.Event(type),event):jQuery.Event(type);if(type.indexOf("!")>=0){event.type=type=type.slice(0,-1);event.exclusive=true;}
+if(!elem){event.stopPropagation();if(this.global[type])
+jQuery.each(jQuery.cache,function(){if(this.events&&this.events[type])
+jQuery.event.trigger(event,data,this.handle.elem);});}
+if(!elem||elem.nodeType==3||elem.nodeType==8)
+return undefined;event.result=undefined;event.target=elem;data=jQuery.makeArray(data);data.unshift(event);}
+event.currentTarget=elem;var handle=jQuery.data(elem,"handle");if(handle)
+handle.apply(elem,data);if((!elem[type]||(jQuery.nodeName(elem,'a')&&type=="click"))&&elem["on"+type]&&elem["on"+type].apply(elem,data)===false)
+event.result=false;if(!bubbling&&elem[type]&&!event.isDefaultPrevented()&&!(jQuery.nodeName(elem,'a')&&type=="click")){this.triggered=true;try{elem[type]();}catch(e){}}
+this.triggered=false;if(!event.isPropagationStopped()){var parent=elem.parentNode||elem.ownerDocument;if(parent)
+jQuery.event.trigger(event,data,parent,true);}},handle:function(event){var all,handlers;event=arguments[0]=jQuery.event.fix(event||window.event);event.currentTarget=this;var namespaces=event.type.split(".");event.type=namespaces.shift();all=!namespaces.length&&!event.exclusive;var namespace=RegExp("(^|\\.)"+namespaces.slice().sort().join(".*\\.")+"(\\.|$)");handlers=(jQuery.data(this,"events")||{})[event.type];for(var j in handlers){var handler=handlers[j];if(all||namespace.test(handler.type)){event.handler=handler;event.data=handler.data;var ret=handler.apply(this,arguments);if(ret!==undefined){event.result=ret;if(ret===false){event.preventDefault();event.stopPropagation();}}
+if(event.isImmediatePropagationStopped())
+break;}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(event){if(event[expando])
+return event;var originalEvent=event;event=jQuery.Event(originalEvent);for(var i=this.props.length,prop;i;){prop=this.props[--i];event[prop]=originalEvent[prop];}
+if(!event.target)
+event.target=event.srcElement||document;if(event.target.nodeType==3)
+event.target=event.target.parentNode;if(!event.relatedTarget&&event.fromElement)
+event.relatedTarget=event.fromElement==event.target?event.toElement:event.fromElement;if(event.pageX==null&&event.clientX!=null){var doc=document.documentElement,body=document.body;event.pageX=event.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc.clientLeft||0);event.pageY=event.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc.clientTop||0);}
+if(!event.which&&((event.charCode||event.charCode===0)?event.charCode:event.keyCode))
+event.which=event.charCode||event.keyCode;if(!event.metaKey&&event.ctrlKey)
+event.metaKey=event.ctrlKey;if(!event.which&&event.button)
+event.which=(event.button&1?1:(event.button&2?3:(event.button&4?2:0)));return event;},proxy:function(fn,proxy){proxy=proxy||function(){return fn.apply(this,arguments);};proxy.guid=fn.guid=fn.guid||proxy.guid||this.guid++;return proxy;},special:{ready:{setup:bindReady,teardown:function(){}}},specialAll:{live:{setup:function(selector,namespaces){jQuery.event.add(this,namespaces[0],liveHandler);},teardown:function(namespaces){if(namespaces.length){var remove=0,name=RegExp("(^|\\.)"+namespaces[0]+"(\\.|$)");jQuery.each((jQuery.data(this,"events").live||{}),function(){if(name.test(this.type))
+remove++;});if(remove<1)
+jQuery.event.remove(this,namespaces[0],liveHandler);}}}}};jQuery.Event=function(src){if(!this.preventDefault)
+return new jQuery.Event(src);if(src&&src.type){this.originalEvent=src;this.type=src.type;}else
+this.type=src;this.timeStamp=now();this[expando]=true;};function returnFalse(){return false;}
+function returnTrue(){return true;}
+jQuery.Event.prototype={preventDefault:function(){this.isDefaultPrevented=returnTrue;var e=this.originalEvent;if(!e)
+return;if(e.preventDefault)
+e.preventDefault();e.returnValue=false;},stopPropagation:function(){this.isPropagationStopped=returnTrue;var e=this.originalEvent;if(!e)
+return;if(e.stopPropagation)
+e.stopPropagation();e.cancelBubble=true;},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=returnTrue;this.stopPropagation();},isDefaultPrevented:returnFalse,isPropagationStopped:returnFalse,isImmediatePropagationStopped:returnFalse};var withinElement=function(event){var parent=event.relatedTarget;while(parent&&parent!=this)
+try{parent=parent.parentNode;}
+catch(e){parent=this;}
+if(parent!=this){event.type=event.data;jQuery.event.handle.apply(this,arguments);}};jQuery.each({mouseover:'mouseenter',mouseout:'mouseleave'},function(orig,fix){jQuery.event.special[fix]={setup:function(){jQuery.event.add(this,orig,withinElement,fix);},teardown:function(){jQuery.event.remove(this,orig,withinElement);}};});jQuery.fn.extend({bind:function(type,data,fn){return type=="unload"?this.one(type,data,fn):this.each(function(){jQuery.event.add(this,type,fn||data,fn&&data);});},one:function(type,data,fn){var one=jQuery.event.proxy(fn||data,function(event){jQuery(this).unbind(event,one);return(fn||data).apply(this,arguments);});return this.each(function(){jQuery.event.add(this,type,one,fn&&data);});},unbind:function(type,fn){return this.each(function(){jQuery.event.remove(this,type,fn);});},trigger:function(type,data){return this.each(function(){jQuery.event.trigger(type,data,this);});},triggerHandler:function(type,data){if(this[0]){var event=jQuery.Event(type);event.preventDefault();event.stopPropagation();jQuery.event.trigger(event,data,this[0]);return event.result;}},toggle:function(fn){var args=arguments,i=1;while(i<args.length)
+jQuery.event.proxy(fn,args[i++]);return this.click(jQuery.event.proxy(fn,function(event){this.lastToggle=(this.lastToggle||0)%i;event.preventDefault();return args[this.lastToggle++].apply(this,arguments)||false;}));},hover:function(fnOver,fnOut){return this.mouseenter(fnOver).mouseleave(fnOut);},ready:function(fn){bindReady();if(jQuery.isReady)
+fn.call(document,jQuery);else
+jQuery.readyList.push(fn);return this;},live:function(type,fn){var proxy=jQuery.event.proxy(fn);proxy.guid+=this.selector+type;jQuery(document).bind(liveConvert(type,this.selector),this.selector,proxy);return this;},die:function(type,fn){jQuery(document).unbind(liveConvert(type,this.selector),fn?{guid:fn.guid+this.selector+type}:null);return this;}});function liveHandler(event){var check=RegExp("(^|\\.)"+event.type+"(\\.|$)"),stop=true,elems=[];jQuery.each(jQuery.data(this,"events").live||[],function(i,fn){if(check.test(fn.type)){var elem=jQuery(event.target).closest(fn.data)[0];if(elem)
+elems.push({elem:elem,fn:fn});}});elems.sort(function(a,b){return jQuery.data(a.elem,"closest")-jQuery.data(b.elem,"closest");});jQuery.each(elems,function(){if(this.fn.call(this.elem,event,this.fn.data)===false)
+return(stop=false);});return stop;}
+function liveConvert(type,selector){return["live",type,selector.replace(/\./g,"`").replace(/ /g,"|")].join(".");}
+jQuery.extend({isReady:false,readyList:[],ready:function(){if(!jQuery.isReady){jQuery.isReady=true;if(jQuery.readyList){jQuery.each(jQuery.readyList,function(){this.call(document,jQuery);});jQuery.readyList=null;}
+jQuery(document).triggerHandler("ready");}}});var readyBound=false;function bindReady(){if(readyBound)return;readyBound=true;if(document.addEventListener){document.addEventListener("DOMContentLoaded",function(){document.removeEventListener("DOMContentLoaded",arguments.callee,false);jQuery.ready();},false);}else if(document.attachEvent){document.attachEvent("onreadystatechange",function(){if(document.readyState==="complete"){document.detachEvent("onreadystatechange",arguments.callee);jQuery.ready();}});if(document.documentElement.doScroll&&window==window.top)(function(){if(jQuery.isReady)return;try{document.documentElement.doScroll("left");}catch(error){setTimeout(arguments.callee,0);return;}
+jQuery.ready();})();}
+jQuery.event.add(window,"load",jQuery.ready);}
+jQuery.each(("blur,focus,load,resize,scroll,unload,click,dblclick,"+"mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave,"+"change,select,submit,keydown,keypress,keyup,error").split(","),function(i,name){jQuery.fn[name]=function(fn){return fn?this.bind(name,fn):this.trigger(name);};});jQuery(window).bind('unload',function(){for(var id in jQuery.cache)
+if(id!=1&&jQuery.cache[id].handle)
+jQuery.event.remove(jQuery.cache[id].handle.elem);});(function(){jQuery.support={};var root=document.documentElement,script=document.createElement("script"),div=document.createElement("div"),id="script"+(new Date).getTime();div.style.display="none";div.innerHTML='   <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>';var all=div.getElementsByTagName("*"),a=div.getElementsByTagName("a")[0];if(!all||!all.length||!a){return;}
+jQuery.support={leadingWhitespace:div.firstChild.nodeType==3,tbody:!div.getElementsByTagName("tbody").length,objectAll:!!div.getElementsByTagName("object")[0].getElementsByTagName("*").length,htmlSerialize:!!div.getElementsByTagName("link").length,style:/red/.test(a.getAttribute("style")),hrefNormalized:a.getAttribute("href")==="/a",opacity:a.style.opacity==="0.5",cssFloat:!!a.style.cssFloat,scriptEval:false,noCloneEvent:true,boxModel:null};script.type="text/javascript";try{script.appendChild(document.createTextNode("window."+id+"=1;"));}catch(e){}
+root.insertBefore(script,root.firstChild);if(window[id]){jQuery.support.scriptEval=true;delete window[id];}
+root.removeChild(script);if(div.attachEvent&&div.fireEvent){div.attachEvent("onclick",function(){jQuery.support.noCloneEvent=false;div.detachEvent("onclick",arguments.callee);});div.cloneNode(true).fireEvent("onclick");}
+jQuery(function(){var div=document.createElement("div");div.style.width=div.style.paddingLeft="1px";document.body.appendChild(div);jQuery.boxModel=jQuery.support.boxModel=div.offsetWidth===2;document.body.removeChild(div).style.display='none';});})();var styleFloat=jQuery.support.cssFloat?"cssFloat":"styleFloat";jQuery.props={"for":"htmlFor","class":"className","float":styleFloat,cssFloat:styleFloat,styleFloat:styleFloat,readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",tabindex:"tabIndex"};jQuery.fn.extend({_load:jQuery.fn.load,load:function(url,params,callback){if(typeof url!=="string")
+return this._load(url);var off=url.indexOf(" ");if(off>=0){var selector=url.slice(off,url.length);url=url.slice(0,off);}
+var type="GET";if(params)
+if(jQuery.isFunction(params)){callback=params;params=null;}else if(typeof params==="object"){params=jQuery.param(params);type="POST";}
+var self=this;jQuery.ajax({url:url,type:type,dataType:"html",data:params,complete:function(res,status){if(status=="success"||status=="notmodified")
+self.html(selector?jQuery("<div/>").append(res.responseText.replace(/<script(.|\s)*?\/script>/g,"")).find(selector):res.responseText);if(callback)
+self.each(callback,[res.responseText,status,res]);}});return this;},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||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.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};}):{name:elem.name,value:val};}).get();}});jQuery.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(i,o){jQuery.fn[o]=function(f){return this.bind(o,f);};});var jsc=now();jQuery.extend({get:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data=null;}
+return jQuery.ajax({type:"GET",url:url,data:data,success:callback,dataType:type});},getScript:function(url,callback){return jQuery.get(url,null,callback,"script");},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json");},post:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data={};}
+return jQuery.ajax({type:"POST",url:url,data:data,success:callback,dataType:type});},ajaxSetup:function(settings){jQuery.extend(jQuery.ajaxSettings,settings);},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return window.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest();},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(s){s=jQuery.extend(true,s,jQuery.extend(true,{},jQuery.ajaxSettings,s));var jsonp,jsre=/=\?(&|$)/g,status,data,type=s.type.toUpperCase();if(s.data&&s.processData&&typeof s.data!=="string")
+s.data=jQuery.param(s.data);if(s.dataType=="jsonp"){if(type=="GET"){if(!s.url.match(jsre))
+s.url+=(s.url.match(/\?/)?"&":"?")+(s.jsonp||"callback")+"=?";}else if(!s.data||!s.data.match(jsre))
+s.data=(s.data?s.data+"&":"")+(s.jsonp||"callback")+"=?";s.dataType="json";}
+if(s.dataType=="json"&&(s.data&&s.data.match(jsre)||s.url.match(jsre))){jsonp="jsonp"+jsc++;if(s.data)
+s.data=(s.data+"").replace(jsre,"="+jsonp+"$1");s.url=s.url.replace(jsre,"="+jsonp+"$1");s.dataType="script";window[jsonp]=function(tmp){data=tmp;success();complete();window[jsonp]=undefined;try{delete window[jsonp];}catch(e){}
+if(head)
+head.removeChild(script);};}
+if(s.dataType=="script"&&s.cache==null)
+s.cache=false;if(s.cache===false&&type=="GET"){var ts=now();var ret=s.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+ts+"$2");s.url=ret+((ret==s.url)?(s.url.match(/\?/)?"&":"?")+"_="+ts:"");}
+if(s.data&&type=="GET"){s.url+=(s.url.match(/\?/)?"&":"?")+s.data;s.data=null;}
+if(s.global&&!jQuery.active++)
+jQuery.event.trigger("ajaxStart");var parts=/^(\w+:)?\/\/([^\/?#]+)/.exec(s.url);if(s.dataType=="script"&&type=="GET"&&parts&&(parts[1]&&parts[1]!=location.protocol||parts[2]!=location.host)){var head=document.getElementsByTagName("head")[0];var script=document.createElement("script");script.src=s.url;if(s.scriptCharset)
+script.charset=s.scriptCharset;if(!jsonp){var done=false;script.onload=script.onreadystatechange=function(){if(!done&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){done=true;success();complete();script.onload=script.onreadystatechange=null;head.removeChild(script);}};}
+head.appendChild(script);return undefined;}
+var requestDone=false;var xhr=s.xhr();if(s.username)
+xhr.open(type,s.url,s.async,s.username,s.password);else
+xhr.open(type,s.url,s.async);try{if(s.data)
+xhr.setRequestHeader("Content-Type",s.contentType);if(s.ifModified)
+xhr.setRequestHeader("If-Modified-Since",jQuery.lastModified[s.url]||"Thu, 01 Jan 1970 00:00:00 GMT");xhr.setRequestHeader("X-Requested-With","XMLHttpRequest");xhr.setRequestHeader("Accept",s.dataType&&s.accepts[s.dataType]?s.accepts[s.dataType]+", */*":s.accepts._default);}catch(e){}
+if(s.beforeSend&&s.beforeSend(xhr,s)===false){if(s.global&&!--jQuery.active)
+jQuery.event.trigger("ajaxStop");xhr.abort();return false;}
+if(s.global)
+jQuery.event.trigger("ajaxSend",[xhr,s]);var onreadystatechange=function(isTimeout){if(xhr.readyState==0){if(ival){clearInterval(ival);ival=null;if(s.global&&!--jQuery.active)
+jQuery.event.trigger("ajaxStop");}}else if(!requestDone&&xhr&&(xhr.readyState==4||isTimeout=="timeout")){requestDone=true;if(ival){clearInterval(ival);ival=null;}
+status=isTimeout=="timeout"?"timeout":!jQuery.httpSuccess(xhr)?"error":s.ifModified&&jQuery.httpNotModified(xhr,s.url)?"notmodified":"success";if(status=="success"){try{data=jQuery.httpData(xhr,s.dataType,s);}catch(e){status="parsererror";}}
+if(status=="success"){var modRes;try{modRes=xhr.getResponseHeader("Last-Modified");}catch(e){}
+if(s.ifModified&&modRes)
+jQuery.lastModified[s.url]=modRes;if(!jsonp)
+success();}else
+jQuery.handleError(s,xhr,status);complete();if(isTimeout)
+xhr.abort();if(s.async)
+xhr=null;}};if(s.async){var ival=setInterval(onreadystatechange,13);if(s.timeout>0)
+setTimeout(function(){if(xhr&&!requestDone)
+onreadystatechange("timeout");},s.timeout);}
+try{xhr.send(s.data);}catch(e){jQuery.handleError(s,xhr,null,e);}
+if(!s.async)
+onreadystatechange();function success(){if(s.success)
+s.success(data,status);if(s.global)
+jQuery.event.trigger("ajaxSuccess",[xhr,s]);}
+function complete(){if(s.complete)
+s.complete(xhr,status);if(s.global)
+jQuery.event.trigger("ajaxComplete",[xhr,s]);if(s.global&&!--jQuery.active)
+jQuery.event.trigger("ajaxStop");}
+return xhr;},handleError:function(s,xhr,status,e){if(s.error)s.error(xhr,status,e);if(s.global)
+jQuery.event.trigger("ajaxError",[xhr,s,e]);},active:0,httpSuccess:function(xhr){try{return!xhr.status&&location.protocol=="file:"||(xhr.status>=200&&xhr.status<300)||xhr.status==304||xhr.status==1223;}catch(e){}
+return false;},httpNotModified:function(xhr,url){try{var xhrRes=xhr.getResponseHeader("Last-Modified");return xhr.status==304||xhrRes==jQuery.lastModified[url];}catch(e){}
+return false;},httpData:function(xhr,type,s){var ct=xhr.getResponseHeader("content-type"),xml=type=="xml"||!type&&ct&&ct.indexOf("xml")>=0,data=xml?xhr.responseXML:xhr.responseText;if(xml&&data.documentElement.tagName=="parsererror")
+throw"parsererror";if(s&&s.dataFilter)
+data=s.dataFilter(data,type);if(typeof data==="string"){if(type=="script")
+jQuery.globalEval(data);if(type=="json")
+data=window["eval"]("("+data+")");}
+return data;},param:function(a){var s=[];function add(key,value){s[s.length]=encodeURIComponent(key)+'='+encodeURIComponent(value);};if(jQuery.isArray(a)||a.jquery)
+jQuery.each(a,function(){add(this.name,this.value);});else
+for(var j in a)
+if(jQuery.isArray(a[j]))
+jQuery.each(a[j],function(){add(j,this);});else
+add(j,jQuery.isFunction(a[j])?a[j]():a[j]);return s.join("&").replace(/%20/g,"+");}});var elemdisplay={},timerId,fxAttrs=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function genFx(type,num){var obj={};jQuery.each(fxAttrs.concat.apply([],fxAttrs.slice(0,num)),function(){obj[this]=type;});return obj;}
+jQuery.fn.extend({show:function(speed,callback){if(speed){return this.animate(genFx("show",3),speed,callback);}else{for(var i=0,l=this.length;i<l;i++){var old=jQuery.data(this[i],"olddisplay");this[i].style.display=old||"";if(jQuery.css(this[i],"display")==="none"){var tagName=this[i].tagName,display;if(elemdisplay[tagName]){display=elemdisplay[tagName];}else{var elem=jQuery("<"+tagName+" />").appendTo("body");display=elem.css("display");if(display==="none")
+display="block";elem.remove();elemdisplay[tagName]=display;}
+jQuery.data(this[i],"olddisplay",display);}}
+for(var i=0,l=this.length;i<l;i++){this[i].style.display=jQuery.data(this[i],"olddisplay")||"";}
+return this;}},hide:function(speed,callback){if(speed){return this.animate(genFx("hide",3),speed,callback);}else{for(var i=0,l=this.length;i<l;i++){var old=jQuery.data(this[i],"olddisplay");if(!old&&old!=="none")
+jQuery.data(this[i],"olddisplay",jQuery.css(this[i],"display"));}
+for(var i=0,l=this.length;i<l;i++){this[i].style.display="none";}
+return this;}},_toggle:jQuery.fn.toggle,toggle:function(fn,fn2){var bool=typeof fn==="boolean";return jQuery.isFunction(fn)&&jQuery.isFunction(fn2)?this._toggle.apply(this,arguments):fn==null||bool?this.each(function(){var state=bool?fn:jQuery(this).is(":hidden");jQuery(this)[state?"show":"hide"]();}):this.animate(genFx("toggle",3),fn,fn2);},fadeTo:function(speed,to,callback){return this.animate({opacity:to},speed,callback);},animate:function(prop,speed,easing,callback){var optall=jQuery.speed(speed,easing,callback);return this[optall.queue===false?"each":"queue"](function(){var opt=jQuery.extend({},optall),p,hidden=this.nodeType==1&&jQuery(this).is(":hidden"),self=this;for(p in prop){if(prop[p]=="hide"&&hidden||prop[p]=="show"&&!hidden)
+return opt.complete.call(this);if((p=="height"||p=="width")&&this.style){opt.display=jQuery.css(this,"display");opt.overflow=this.style.overflow;}}
+if(opt.overflow!=null)
+this.style.overflow="hidden";opt.curAnim=jQuery.extend({},prop);jQuery.each(prop,function(name,val){var e=new jQuery.fx(self,opt,name);if(/toggle|show|hide/.test(val))
+e[val=="toggle"?hidden?"show":"hide":val](prop);else{var parts=val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),start=e.cur(true)||0;if(parts){var end=parseFloat(parts[2]),unit=parts[3]||"px";if(unit!="px"){self.style[name]=(end||1)+unit;start=((end||1)/e.cur(true))*start;self.style[name]=start+unit;}
+if(parts[1])
+end=((parts[1]=="-="?-1:1)*end)+start;e.custom(start,end,unit);}else
+e.custom(start,val,"");}});return true;});},stop:function(clearQueue,gotoEnd){var timers=jQuery.timers;if(clearQueue)
+this.queue([]);this.each(function(){for(var i=timers.length-1;i>=0;i--)
+if(timers[i].elem==this){if(gotoEnd)
+timers[i](true);timers.splice(i,1);}});if(!gotoEnd)
+this.dequeue();return this;}});jQuery.each({slideDown:genFx("show",1),slideUp:genFx("hide",1),slideToggle:genFx("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(name,props){jQuery.fn[name]=function(speed,callback){return this.animate(props,speed,callback);};});jQuery.extend({speed:function(speed,easing,fn){var opt=typeof speed==="object"?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:jQuery.fx.speeds[opt.duration]||jQuery.fx.speeds._default;opt.old=opt.complete;opt.complete=function(){if(opt.queue!==false)
+jQuery(this).dequeue();if(jQuery.isFunction(opt.old))
+opt.old.call(this);};return opt;},easing:{linear:function(p,n,firstNum,diff){return firstNum+diff*p;},swing:function(p,n,firstNum,diff){return((-Math.cos(p*Math.PI)/2)+0.5)*diff+firstNum;}},timers:[],fx:function(elem,options,prop){this.options=options;this.elem=elem;this.prop=prop;if(!options.orig)
+options.orig={};}});jQuery.fx.prototype={update:function(){if(this.options.step)
+this.options.step.call(this.elem,this.now,this);(jQuery.fx.step[this.prop]||jQuery.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style)
+this.elem.style.display="block";},cur:function(force){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))
+return this.elem[this.prop];var r=parseFloat(jQuery.css(this.elem,this.prop,force));return r&&r>-10000?r:parseFloat(jQuery.curCSS(this.elem,this.prop))||0;},custom:function(from,to,unit){this.startTime=now();this.start=from;this.end=to;this.unit=unit||this.unit||"px";this.now=this.start;this.pos=this.state=0;var self=this;function t(gotoEnd){return self.step(gotoEnd);}
+t.elem=this.elem;if(t()&&jQuery.timers.push(t)&&!timerId){timerId=setInterval(function(){var timers=jQuery.timers;for(var i=0;i<timers.length;i++)
+if(!timers[i]())
+timers.splice(i--,1);if(!timers.length){clearInterval(timerId);timerId=undefined;}},13);}},show:function(){this.options.orig[this.prop]=jQuery.attr(this.elem.style,this.prop);this.options.show=true;this.custom(this.prop=="width"||this.prop=="height"?1:0,this.cur());jQuery(this.elem).show();},hide:function(){this.options.orig[this.prop]=jQuery.attr(this.elem.style,this.prop);this.options.hide=true;this.custom(this.cur(),0);},step:function(gotoEnd){var t=now();if(gotoEnd||t>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var done=true;for(var i in this.options.curAnim)
+if(this.options.curAnim[i]!==true)
+done=false;if(done){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(jQuery.css(this.elem,"display")=="none")
+this.elem.style.display="block";}
+if(this.options.hide)
+jQuery(this.elem).hide();if(this.options.hide||this.options.show)
+for(var p in this.options.curAnim)
+jQuery.attr(this.elem.style,p,this.options.orig[p]);this.options.complete.call(this.elem);}
+return false;}else{var n=t-this.startTime;this.state=n/this.options.duration;this.pos=jQuery.easing[this.options.easing||(jQuery.easing.swing?"swing":"linear")](this.state,n,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update();}
+return true;}};jQuery.extend(jQuery.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(fx){jQuery.attr(fx.elem.style,"opacity",fx.now);},_default:function(fx){if(fx.elem.style&&fx.elem.style[fx.prop]!=null)
+fx.elem.style[fx.prop]=fx.now+fx.unit;else
+fx.elem[fx.prop]=fx.now;}}});if(document.documentElement["getBoundingClientRect"])
+jQuery.fn.offset=function(){if(!this[0])return{top:0,left:0};if(this[0]===this[0].ownerDocument.body)return jQuery.offset.bodyOffset(this[0]);var box=this[0].getBoundingClientRect(),doc=this[0].ownerDocument,body=doc.body,docElem=doc.documentElement,clientTop=docElem.clientTop||body.clientTop||0,clientLeft=docElem.clientLeft||body.clientLeft||0,top=box.top+(self.pageYOffset||jQuery.boxModel&&docElem.scrollTop||body.scrollTop)-clientTop,left=box.left+(self.pageXOffset||jQuery.boxModel&&docElem.scrollLeft||body.scrollLeft)-clientLeft;return{top:top,left:left};};else
+jQuery.fn.offset=function(){if(!this[0])return{top:0,left:0};if(this[0]===this[0].ownerDocument.body)return jQuery.offset.bodyOffset(this[0]);jQuery.offset.initialized||jQuery.offset.initialize();var elem=this[0],offsetParent=elem.offsetParent,prevOffsetParent=elem,doc=elem.ownerDocument,computedStyle,docElem=doc.documentElement,body=doc.body,defaultView=doc.defaultView,prevComputedStyle=defaultView.getComputedStyle(elem,null),top=elem.offsetTop,left=elem.offsetLeft;while((elem=elem.parentNode)&&elem!==body&&elem!==docElem){computedStyle=defaultView.getComputedStyle(elem,null);top-=elem.scrollTop,left-=elem.scrollLeft;if(elem===offsetParent){top+=elem.offsetTop,left+=elem.offsetLeft;if(jQuery.offset.doesNotAddBorder&&!(jQuery.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(elem.tagName)))
+top+=parseInt(computedStyle.borderTopWidth,10)||0,left+=parseInt(computedStyle.borderLeftWidth,10)||0;prevOffsetParent=offsetParent,offsetParent=elem.offsetParent;}
+if(jQuery.offset.subtractsBorderForOverflowNotVisible&&computedStyle.overflow!=="visible")
+top+=parseInt(computedStyle.borderTopWidth,10)||0,left+=parseInt(computedStyle.borderLeftWidth,10)||0;prevComputedStyle=computedStyle;}
+if(prevComputedStyle.position==="relative"||prevComputedStyle.position==="static")
+top+=body.offsetTop,left+=body.offsetLeft;if(prevComputedStyle.position==="fixed")
+top+=Math.max(docElem.scrollTop,body.scrollTop),left+=Math.max(docElem.scrollLeft,body.scrollLeft);return{top:top,left:left};};jQuery.offset={initialize:function(){if(this.initialized)return;var body=document.body,container=document.createElement('div'),innerDiv,checkDiv,table,td,rules,prop,bodyMarginTop=body.style.marginTop,html='<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>';rules={position:'absolute',top:0,left:0,margin:0,border:0,width:'1px',height:'1px',visibility:'hidden'};for(prop in rules)container.style[prop]=rules[prop];container.innerHTML=html;body.insertBefore(container,body.firstChild);innerDiv=container.firstChild,checkDiv=innerDiv.firstChild,td=innerDiv.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(checkDiv.offsetTop!==5);this.doesAddBorderForTableAndCells=(td.offsetTop===5);innerDiv.style.overflow='hidden',innerDiv.style.position='relative';this.subtractsBorderForOverflowNotVisible=(checkDiv.offsetTop===-5);body.style.marginTop='1px';this.doesNotIncludeMarginInBodyOffset=(body.offsetTop===0);body.style.marginTop=bodyMarginTop;body.removeChild(container);this.initialized=true;},bodyOffset:function(body){jQuery.offset.initialized||jQuery.offset.initialize();var top=body.offsetTop,left=body.offsetLeft;if(jQuery.offset.doesNotIncludeMarginInBodyOffset)
+top+=parseInt(jQuery.curCSS(body,'marginTop',true),10)||0,left+=parseInt(jQuery.curCSS(body,'marginLeft',true),10)||0;return{top:top,left:left};}};jQuery.fn.extend({position:function(){var left=0,top=0,results;if(this[0]){var offsetParent=this.offsetParent(),offset=this.offset(),parentOffset=/^body|html$/i.test(offsetParent[0].tagName)?{top:0,left:0}:offsetParent.offset();offset.top-=num(this,'marginTop');offset.left-=num(this,'marginLeft');parentOffset.top+=num(offsetParent,'borderTopWidth');parentOffset.left+=num(offsetParent,'borderLeftWidth');results={top:offset.top-parentOffset.top,left:offset.left-parentOffset.left};}
+return results;},offsetParent:function(){var offsetParent=this[0].offsetParent||document.body;while(offsetParent&&(!/^body|html$/i.test(offsetParent.tagName)&&jQuery.css(offsetParent,'position')=='static'))
+offsetParent=offsetParent.offsetParent;return jQuery(offsetParent);}});jQuery.each(['Left','Top'],function(i,name){var method='scroll'+name;jQuery.fn[method]=function(val){if(!this[0])return null;return val!==undefined?this.each(function(){this==window||this==document?window.scrollTo(!i?val:jQuery(window).scrollLeft(),i?val:jQuery(window).scrollTop()):this[method]=val;}):this[0]==window||this[0]==document?self[i?'pageYOffset':'pageXOffset']||jQuery.boxModel&&document.documentElement[method]||document.body[method]:this[0][method];};});jQuery.each(["Height","Width"],function(i,name){var tl=i?"Left":"Top",br=i?"Right":"Bottom",lower=name.toLowerCase();jQuery.fn["inner"+name]=function(){return this[0]?jQuery.css(this[0],lower,false,"padding"):null;};jQuery.fn["outer"+name]=function(margin){return this[0]?jQuery.css(this[0],lower,false,margin?"margin":"border"):null;};var type=name.toLowerCase();jQuery.fn[type]=function(size){return this[0]==window?document.compatMode=="CSS1Compat"&&document.documentElement["client"+name]||document.body["client"+name]:this[0]==document?Math.max(document.documentElement["client"+name],document.body["scroll"+name],document.documentElement["scroll"+name],document.body["offset"+name],document.documentElement["offset"+name]):size===undefined?(this.length?jQuery.css(this[0],type):null):this.css(type,typeof size==="string"?size:size+"px");};});})();;jQuery.ui||(function($){var _remove=$.fn.remove,isFF2=$.browser.mozilla&&(parseFloat($.browser.version)<1.9);$.ui={version:"1.7.2",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);}}}},contains:function(a,b){return document.compareDocumentPosition?a.compareDocumentPosition(b)&16:a!==b&&a.contains(b);},hasScroll:function(el,a){if($(el).css('overflow')=='hidden'){return false;}
+var scroll=(a&&a=='left')?'scrollLeft':'scrollTop',has=false;if(el[scroll]>0){return true;}
+el[scroll]=1;has=(el[scroll]>0);el[scroll]=0;return has;},isOverAxis:function(x,reference,size){return(x>reference)&&(x<(reference+size));},isOver:function(y,x,top,left,height,width){return $.ui.isOverAxis(y,top,height)&&$.ui.isOverAxis(x,left,width);},keyCode:{BACKSPACE:8,CAPS_LOCK:20,COMMA:188,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,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}};if(isFF2){var attr=$.attr,removeAttr=$.fn.removeAttr,ariaNS="http://www.w3.org/2005/07/aaa",ariaState=/^aria-/,ariaRole=/^wairole:/;$.attr=function(elem,name,value){var set=value!==undefined;return(name=='role'?(set?attr.call(this,elem,name,"wairole:"+value):(attr.apply(this,arguments)||"").replace(ariaRole,"")):(ariaState.test(name)?(set?elem.setAttributeNS(ariaNS,name.replace(ariaState,"aaa:"),value):attr.call(this,elem,name.replace(ariaState,"aaa:"))):attr.apply(this,arguments)));};$.fn.removeAttr=function(name){return(ariaState.test(name)?this.each(function(){this.removeAttributeNS(ariaNS,name.replace(ariaState,""));}):removeAttr.call(this,name));};}
+$.fn.extend({remove:function(){$("*",this).add(this).each(function(){$(this).triggerHandler("remove");});return _remove.apply(this,arguments);},enableSelection:function(){return this.attr('unselectable','off').css('MozUserSelect','').unbind('selectstart.ui');},disableSelection:function(){return this.attr('unselectable','on').css('MozUserSelect','none').bind('selectstart.ui',function(){return false;});},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;}});$.extend($.expr[':'],{data:function(elem,i,match){return!!$.data(elem,match[3]);},focusable:function(element){var nodeName=element.nodeName.toLowerCase(),tabIndex=$.attr(element,'tabindex');return(/input|select|textarea|button|object/.test(nodeName)?!element.disabled:'a'==nodeName||'area'==nodeName?element.href||!isNaN(tabIndex):!isNaN(tabIndex))&&!$(element)['area'==nodeName?'parents':'closest'](':hidden').length;},tabbable:function(element){var tabIndex=$.attr(element,'tabindex');return(isNaN(tabIndex)||tabIndex>=0)&&$(element).is(':focusable');}});function getter(namespace,plugin,method,args){function getMethods(type){var methods=$[namespace][plugin][type]||[];return(typeof methods=='string'?methods.split(/,?\s+/):methods);}
+var methods=getMethods('getter');if(args.length==1&&typeof args[0]=='string'){methods=methods.concat(getMethods('getterSetter'));}
+return($.inArray(method,methods)!=-1);}
+$.widget=function(name,prototype){var namespace=name.split(".")[0];name=name.split(".")[1];$.fn[name]=function(options){var isMethodCall=(typeof options=='string'),args=Array.prototype.slice.call(arguments,1);if(isMethodCall&&options.substring(0,1)=='_'){return this;}
+if(isMethodCall&&getter(namespace,name,options,args)){var instance=$.data(this[0],name);return(instance?instance[options].apply(instance,args):undefined);}
+return this.each(function(){var instance=$.data(this,name);(!instance&&!isMethodCall&&$.data(this,name,new $[namespace][name](this,options))._init());(instance&&isMethodCall&&$.isFunction(instance[options])&&instance[options].apply(instance,args));});};$[namespace]=$[namespace]||{};$[namespace][name]=function(element,options){var self=this;this.namespace=namespace;this.widgetName=name;this.widgetEventPrefix=$[namespace][name].eventPrefix||name;this.widgetBaseClass=namespace+'-'+name;this.options=$.extend({},$.widget.defaults,$[namespace][name].defaults,$.metadata&&$.metadata.get(element)[name],options);this.element=$(element).bind('setData.'+name,function(event,key,value){if(event.target==element){return self._setData(key,value);}}).bind('getData.'+name,function(event,key){if(event.target==element){return self._getData(key);}}).bind('remove',function(){return self.destroy();});};$[namespace][name].prototype=$.extend({},$.widget.prototype,prototype);$[namespace][name].getterSetter='option';};$.widget.prototype={_init:function(){},destroy:function(){this.element.removeData(this.widgetName).removeClass(this.widgetBaseClass+'-disabled'+' '+this.namespace+'-state-disabled').removeAttr('aria-disabled');},option:function(key,value){var options=key,self=this;if(typeof key=="string"){if(value===undefined){return this._getData(key);}
+options={};options[key]=value;}
+$.each(options,function(key,value){self._setData(key,value);});},_getData:function(key){return this.options[key];},_setData:function(key,value){this.options[key]=value;if(key=='disabled'){this.element
+[value?'addClass':'removeClass'](this.widgetBaseClass+'-disabled'+' '+
+this.namespace+'-state-disabled').attr("aria-disabled",value);}},enable:function(){this._setData('disabled',false);},disable:function(){this._setData('disabled',true);},_trigger:function(type,event,data){var callback=this.options[type],eventName=(type==this.widgetEventPrefix?type:this.widgetEventPrefix+type);event=$.Event(event);event.type=eventName;if(event.originalEvent){for(var i=$.event.props.length,prop;i;){prop=$.event.props[--i];event[prop]=event.originalEvent[prop];}}
+this.element.trigger(event,data);return!($.isFunction(callback)&&callback.call(this.element[0],event,data)===false||event.isDefaultPrevented());}};$.widget.defaults={disabled:false};$.ui.mouse={_mouseInit:function(){var self=this;this.element.bind('mousedown.'+this.widgetName,function(event){return self._mouseDown(event);}).bind('click.'+this.widgetName,function(event){if(self._preventClickEvent){self._preventClickEvent=false;event.stopImmediatePropagation();return false;}});if($.browser.msie){this._mouseUnselectable=this.element.attr('unselectable');this.element.attr('unselectable','on');}
+this.started=false;},_mouseDestroy:function(){this.element.unbind('.'+this.widgetName);($.browser.msie&&this.element.attr('unselectable',this._mouseUnselectable));},_mouseDown:function(event){event.originalEvent=event.originalEvent||{};if(event.originalEvent.mouseHandled){return;}
+(this._mouseStarted&&this._mouseUp(event));this._mouseDownEvent=event;var self=this,btnIsLeft=(event.which==1),elIsCancel=(typeof this.options.cancel=="string"?$(event.target).parents().add(event.target).filter(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;}}
+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);($.browser.safari||event.preventDefault());event.originalEvent.mouseHandled=true;return true;},_mouseMove:function(event){if($.browser.msie&&!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;this._preventClickEvent=(event.target==this._mouseDownEvent.target);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;},_mouseStart:function(event){},_mouseDrag:function(event){},_mouseStop:function(event){},_mouseCapture:function(event){return true;}};$.ui.mouse.defaults={cancel:null,distance:1,delay:0};})(jQuery);(function($){$.widget("ui.draggable",$.extend({},$.ui.mouse,{_init: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();},_mouseCapture:function(event){var o=this.options;if(this.helper||o.disabled||$(event.target).is('.ui-resizable-handle'))
+return false;this.handle=this._getHandle(event);if(!this.handle)
+return false;return true;},_mouseStart:function(event){var o=this.options;this.helper=this._createHelper(event);this._cacheHelperProportions();if($.ui.ddmanager)
+$.ui.ddmanager.current=this;this._cacheMargins();this.cssPosition=this.helper.css("position");this.scrollParent=this.helper.scrollParent();this.offset=this.element.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};$.extend(this.offset,{click:{left:event.pageX-this.offset.left,top:event.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(event);this.originalPageX=event.pageX;this.originalPageY=event.pageY;if(o.cursorAt)
+this._adjustOffsetFromHelper(o.cursorAt);if(o.containment)
+this._setContainment();this._trigger("start",event);this._cacheHelperProportions();if($.ui.ddmanager&&!o.dropBehaviour)
+$.ui.ddmanager.prepareOffsets(this,event);this.helper.addClass("ui-draggable-dragging");this._mouseDrag(event,true);return true;},_mouseDrag:function(event,noPropagation){this.position=this._generatePosition(event);this.positionAbs=this._convertPositionTo("absolute");if(!noPropagation){var ui=this._uiHash();this._trigger('drag',event,ui);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){var dropped=false;if($.ui.ddmanager&&!this.options.dropBehaviour)
+dropped=$.ui.ddmanager.drop(this,event);if(this.dropped){dropped=this.dropped;this.dropped=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(){self._trigger("stop",event);self._clear();});}else{this._trigger("stop",event);this._clear();}
+return false;},_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():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(obj.left!=undefined)this.offset.click.left=obj.left+this.margins.left;if(obj.right!=undefined)this.offset.click.left=this.helperProportions.width-obj.right+this.margins.left;if(obj.top!=undefined)this.offset.click.top=obj.top+this.margins.top;if(obj.bottom!=undefined)this.offset.click.top=this.helperProportions.height-obj.bottom+this.margins.top;},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var po=this.offsetParent.offset();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.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=='html'&&$.browser.msie))
+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)};},_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)&&o.containment.constructor!=Array){var ce=$(o.containment)[0];if(!ce)return;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];}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
++this.offset.relative.top*mod
++this.offset.parent.top*mod
+-($.browser.safari&&this.cssPosition=='fixed'?0:(this.cssPosition=='fixed'?-this.scrollParent.scrollTop():(scrollIsRootNode?0:scroll.scrollTop()))*mod)),left:(pos.left
++this.offset.relative.left*mod
++this.offset.parent.left*mod
+-($.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);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;if(this.originalPosition){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
+-this.offset.click.top
+-this.offset.relative.top
+-this.offset.parent.top
++($.browser.safari&&this.cssPosition=='fixed'?0:(this.cssPosition=='fixed'?-this.scrollParent.scrollTop():(scrollIsRootNode?0:scroll.scrollTop())))),left:(pageX
+-this.offset.click.left
+-this.offset.relative.left
+-this.offset.parent.left
++($.browser.safari&&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();this.helper=null;this.cancelHelperRemoval=false;},_trigger:function(type,event,ui){ui=ui||this._uiHash();$.ui.plugin.call(this,type,[event,ui]);if(type=="drag")this.positionAbs=this._convertPositionTo("absolute");return $.widget.prototype._trigger.call(this,type,event,ui);},plugins:{},_uiHash:function(event){return{helper:this.helper,position:this.position,absolutePosition:this.positionAbs,offset:this.positionAbs};}}));$.extend($.ui.draggable,{version:"1.7.2",eventPrefix:"drag",defaults:{addClasses:true,appendTo:"parent",axis:false,cancel:":input,option",connectToSortable:false,containment:false,cursor:"auto",cursorAt:false,delay:0,distance:1,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}});$.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._refreshItems();sortable._trigger("activate",event,uiSortable);}});},stop:function(event,ui){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;this.instance.cancelHelperRemoval=false;if(this.shouldRevert)this.instance.options.revert=true;this.instance._mouseStop(event);this.instance.options.helper=this.instance.options._helper;if(inst.options.helper=='original')
+this.instance.currentItem.css({top:'auto',left:'auto'});}else{this.instance.cancelHelperRemoval=false;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){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(!this.instance.isOver){this.instance.isOver=1;this.instance.currentItem=$(self).clone().appendTo(this.instance.element).data("sortable-item",true);this.instance.options._helper=this.instance.options.helper;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);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;inst.currentItem=inst.element;this.instance.fromOutside=inst;}
+if(this.instance.currentItem)this.instance._mouseDrag(event);}else{if(this.instance.isOver){this.instance.isOver=0;this.instance.cancelHelperRemoval=true;this.instance.options.revert=false;this.instance._trigger('out',event,this.instance._uiHash(this.instance));this.instance._mouseStop(event,true);this.instance.options.helper=this.instance.options._helper;this.instance.currentItem.remove();if(this.instance.placeholder)this.instance.placeholder.remove();inst._trigger("fromSortable",event);inst.dropped=false;}};});}});$.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","iframeFix",{start:function(event,ui){var o=$(this).data('draggable').options;$(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");});},stop:function(event,ui){$("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this);});}});$.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;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.group)).sort(function(a,b){return(parseInt($(a).css("zIndex"),10)||o.stack.min)-(parseInt($(b).css("zIndex"),10)||o.stack.min);});$(group).each(function(i){this.style.zIndex=o.stack.min+i;});this[0].style.zIndex=o.stack.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);(function($){$.widget("ui.resizable",$.extend({},$.ui.mouse,{_init: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});if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)){if(/relative/.test(this.element.css('position'))&&$.browser.opera)
+this.element.css({position:'relative',top:'auto',left:'auto'});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')}));this.element=this.element.parent().data("resizable",this.element.data('resizable'));this.elementIsWrapper=true;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});this.originalResizeStyle=this.originalElement.css('resize');this.originalElement.css('resize','none');this._proportionallyResizeElements.push(this.originalElement.css({position:'static',zoom:1,display:'block'}));this.originalElement.css({margin:this.originalElement.css('margin')});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>');if(/sw|se|ne|nw/.test(handle))axis.css({zIndex:++o.zIndex});if('se'==handle){axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');};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();if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var axis=$(this.handles[i],this.element),padWrapper=0;padWrapper=/sw|ne|nw|se|n|s/.test(i)?axis.outerHeight():axis.outerWidth();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();}
+if(!$(this.handles[i]).length)
+continue;}};this._renderAxis(this.element);this._handles=$('.ui-resizable-handle',this.element).disableSelection();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);self.axis=axis&&axis[1]?axis[1]:'se';}});if(o.autoHide){this._handles.hide();$(this.element).addClass("ui-resizable-autohide").hover(function(){$(this).removeClass("ui-resizable-autohide");self._handles.show();},function(){if(!self.resizing){$(this).addClass("ui-resizable-autohide");self._handles.hide();}});}
+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();};if(this.elementIsWrapper){_destroy(this.element);var wrapper=this.element;wrapper.parent().append(this.originalElement.css({position:wrapper.css('position'),width:wrapper.outerWidth(),height:wrapper.outerHeight(),top:wrapper.css('top'),left:wrapper.css('left')})).end().remove();}
+this.originalElement.css('resize',this.originalResizeStyle);_destroy(this.originalElement);},_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()};if(el.is('.ui-draggable')||(/absolute/).test(el.css('position'))){el.css({position:'absolute',top:iniPos.top,left:iniPos.left});}
+if($.browser.opera&&(/relative/).test(el.css('position')))
+el.css({position:'relative',top:'auto',left:'auto'});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;}
+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};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){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;var data=trigger.apply(this,[event,dx,dy]),ie6=$.browser.msie&&$.browser.version<7,csdif=this.sizeDiff;if(this._aspectRatio||event.shiftKey)
+data=this._updateRatio(data,event);data=this._respectSize(data,event);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);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')?0:self.sizeDiff.height,soffsetw=ista?0:self.sizeDiff.width;var s={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;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;},_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(data.height)data.width=(csize.height*this.aspectRatio);else if(data.width)data.height=(csize.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.options,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;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>');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});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.7.2",eventPrefix:"resize",defaults:{alsoResize:false,animate:false,animateDuration:"slow",animateEasing:"swing",aspectRatio:false,autoHide:false,cancel:":input,option",containment:false,delay:0,distance:1,ghost:false,grid:false,handles:"e,s,se",helper:false,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1000}});$.ui.plugin.add("resizable","alsoResize",{start:function(event,ui){var self=$(this).data("resizable"),o=self.options;_store=function(exp){$(exp).each(function(){$(this).data("resizable-alsoresize",{width:parseInt($(this).width(),10),height:parseInt($(this).height(),10),left:parseInt($(this).css('left'),10),top:parseInt($(this).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,c){_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:['width','height','top','left'];$.each(css||['width','height','top','left'],function(i,prop){var sum=(start[prop]||0)+(delta[prop]||0);if(sum&&sum>=0)
+style[prop]=sum||null;});if(/relative/.test(el.css('position'))&&$.browser.opera){self._revertToRelativePosition=true;el.css({position:'absolute',top:'auto',left:'auto'});}
+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){var self=$(this).data("resizable");if(self._revertToRelativePosition&&$.browser.opera){self._revertToRelativePosition=false;el.css({position:'relative'});}
+$(this).removeData("resizable-alsoresize-start");}});$.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')?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});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};}
+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/o.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*o.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);(function($){var setDataSwitch={dragStart:"start.draggable",drag:"drag.draggable",dragStop:"stop.draggable",maxHeight:"maxHeight.resizable",minHeight:"minHeight.resizable",maxWidth:"maxWidth.resizable",minWidth:"minWidth.resizable",resizeStart:"start.resizable",resize:"drag.resizable",resizeStop:"stop.resizable"},uiDialogClasses='ui-dialog '+'ui-widget '+'ui-widget-content '+'ui-corner-all ';$.widget("ui.dialog",{_init:function(){this.originalTitle=this.element.attr('title');var self=this,options=this.options,title=options.title||this.originalTitle||'&nbsp;',titleId=$.ui.dialog.getTitleId(this.element),uiDialog=(this.uiDialog=$('<div/>')).appendTo(document.body).hide().addClass(uiDialogClasses+options.dialogClass).css({position:'absolute',overflow:'hidden',zIndex:options.zIndex}).attr('tabIndex',-1).css('outline',0).keydown(function(event){(options.closeOnEscape&&event.keyCode&&event.keyCode==$.ui.keyCode.ESCAPE&&self.close(event));}).attr({role:'dialog','aria-labelledby':titleId}).mousedown(function(event){self.moveToTop(false,event);}),uiDialogContent=this.element.show().removeAttr('title').addClass('ui-dialog-content '+'ui-widget-content').appendTo(uiDialog),uiDialogTitlebar=(this.uiDialogTitlebar=$('<div></div>')).addClass('ui-dialog-titlebar '+'ui-widget-header '+'ui-corner-all '+'ui-helper-clearfix').prependTo(uiDialog),uiDialogTitlebarClose=$('<a href="#"/>').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');}).mousedown(function(ev){ev.stopPropagation();}).click(function(event){self.close(event);return false;}).appendTo(uiDialogTitlebar),uiDialogTitlebarCloseText=(this.uiDialogTitlebarCloseText=$('<span/>')).addClass('ui-icon '+'ui-icon-closethick').text(options.closeText).appendTo(uiDialogTitlebarClose),uiDialogTitle=$('<span/>').addClass('ui-dialog-title').attr('id',titleId).html(title).prependTo(uiDialogTitlebar);uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();(options.draggable&&$.fn.draggable&&this._makeDraggable());(options.resizable&&$.fn.resizable&&this._makeResizable());this._createButtons(options.buttons);this._isOpen=false;(options.bgiframe&&$.fn.bgiframe&&uiDialog.bgiframe());(options.autoOpen&&this.open());},destroy:function(){(this.overlay&&this.overlay.destroy());this.uiDialog.hide();this.element.unbind('.dialog').removeData('dialog').removeClass('ui-dialog-content ui-widget-content').hide().appendTo('body');this.uiDialog.remove();(this.originalTitle&&this.element.attr('title',this.originalTitle));},close:function(event){var self=this;if(false===self._trigger('beforeclose',event)){return;}
+(self.overlay&&self.overlay.destroy());self.uiDialog.unbind('keypress.ui-dialog');(self.options.hide?self.uiDialog.hide(self.options.hide,function(){self._trigger('close',event);}):self.uiDialog.hide()&&self._trigger('close',event));$.ui.dialog.overlay.resize();self._isOpen=false;if(self.options.modal){var maxZ=0;$('.ui-dialog').each(function(){if(this!=self.uiDialog[0]){maxZ=Math.max(maxZ,$(this).css('z-index'));}});$.ui.dialog.maxZ=maxZ;}},isOpen:function(){return this._isOpen;},moveToTop:function(force,event){if((this.options.modal&&!force)||(!this.options.stack&&!this.options.modal)){return this._trigger('focus',event);}
+if(this.options.zIndex>$.ui.dialog.maxZ){$.ui.dialog.maxZ=this.options.zIndex;}
+(this.overlay&&this.overlay.$el.css('z-index',$.ui.dialog.overlay.maxZ=++$.ui.dialog.maxZ));var saveScroll={scrollTop:this.element.attr('scrollTop'),scrollLeft:this.element.attr('scrollLeft')};this.uiDialog.css('z-index',++$.ui.dialog.maxZ);this.element.attr(saveScroll);this._trigger('focus',event);},open:function(){if(this._isOpen){return;}
+var options=this.options,uiDialog=this.uiDialog;this.overlay=options.modal?new $.ui.dialog.overlay(this):null;(uiDialog.next().length&&uiDialog.appendTo('body'));this._size();this._position(options.position);uiDialog.show(options.show);this.moveToTop(true);(options.modal&&uiDialog.bind('keypress.ui-dialog',function(event){if(event.keyCode!=$.ui.keyCode.TAB){return;}
+var tabbables=$(':tabbable',this),first=tabbables.filter(':first')[0],last=tabbables.filter(':last')[0];if(event.target==last&&!event.shiftKey){setTimeout(function(){first.focus();},1);}else if(event.target==first&&event.shiftKey){setTimeout(function(){last.focus();},1);}}));$([]).add(uiDialog.find('.ui-dialog-content :tabbable:first')).add(uiDialog.find('.ui-dialog-buttonpane :tabbable:first')).add(uiDialog).filter(':first').focus();this._trigger('open');this._isOpen=true;},_createButtons:function(buttons){var self=this,hasButtons=false,uiDialogButtonPane=$('<div></div>').addClass('ui-dialog-buttonpane '+'ui-widget-content '+'ui-helper-clearfix');this.uiDialog.find('.ui-dialog-buttonpane').remove();(typeof buttons=='object'&&buttons!==null&&$.each(buttons,function(){return!(hasButtons=true);}));if(hasButtons){$.each(buttons,function(name,fn){$('<button type="button"></button>').addClass('ui-state-default '+'ui-corner-all').text(name).click(function(){fn.apply(self.element[0],arguments);}).hover(function(){$(this).addClass('ui-state-hover');},function(){$(this).removeClass('ui-state-hover');}).focus(function(){$(this).addClass('ui-state-focus');}).blur(function(){$(this).removeClass('ui-state-focus');}).appendTo(uiDialogButtonPane);});uiDialogButtonPane.appendTo(this.uiDialog);}},_makeDraggable:function(){var self=this,options=this.options,heightBeforeDrag;this.uiDialog.draggable({cancel:'.ui-dialog-content',handle:'.ui-dialog-titlebar',containment:'document',start:function(){heightBeforeDrag=options.height;$(this).height($(this).height()).addClass("ui-dialog-dragging");(options.dragStart&&options.dragStart.apply(self.element[0],arguments));},drag:function(){(options.drag&&options.drag.apply(self.element[0],arguments));},stop:function(){$(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);(options.dragStop&&options.dragStop.apply(self.element[0],arguments));$.ui.dialog.overlay.resize();}});},_makeResizable:function(handles){handles=(handles===undefined?this.options.resizable:handles);var self=this,options=this.options,resizeHandles=typeof handles=='string'?handles:'n,e,s,w,se,sw,ne,nw';this.uiDialog.resizable({cancel:'.ui-dialog-content',alsoResize:this.element,maxWidth:options.maxWidth,maxHeight:options.maxHeight,minWidth:options.minWidth,minHeight:options.minHeight,start:function(){$(this).addClass("ui-dialog-resizing");(options.resizeStart&&options.resizeStart.apply(self.element[0],arguments));},resize:function(){(options.resize&&options.resize.apply(self.element[0],arguments));},handles:resizeHandles,stop:function(){$(this).removeClass("ui-dialog-resizing");options.height=$(this).height();options.width=$(this).width();(options.resizeStop&&options.resizeStop.apply(self.element[0],arguments));$.ui.dialog.overlay.resize();}}).find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');},_position:function(pos){var wnd=$(window),doc=$(document),pTop=doc.scrollTop(),pLeft=doc.scrollLeft(),minTop=pTop;if($.inArray(pos,['center','top','right','bottom','left'])>=0){pos=[pos=='right'||pos=='left'?pos:'center',pos=='top'||pos=='bottom'?pos:'middle'];}
+if(pos.constructor!=Array){pos=['center','middle'];}
+if(pos[0].constructor==Number){pLeft+=pos[0];}else{switch(pos[0]){case'left':pLeft+=0;break;case'right':pLeft+=wnd.width()-this.uiDialog.outerWidth();break;default:case'center':pLeft+=(wnd.width()-this.uiDialog.outerWidth())/2;}}
+if(pos[1].constructor==Number){pTop+=pos[1];}else{switch(pos[1]){case'top':pTop+=0;break;case'bottom':pTop+=wnd.height()-this.uiDialog.outerHeight();break;default:case'middle':pTop+=(wnd.height()-this.uiDialog.outerHeight())/2;}}
+pTop=Math.max(pTop,minTop);this.uiDialog.css({top:pTop,left:pLeft});},_setData:function(key,value){(setDataSwitch[key]&&this.uiDialog.data(setDataSwitch[key],value));switch(key){case"buttons":this._createButtons(value);break;case"closeText":this.uiDialogTitlebarCloseText.text(value);break;case"dialogClass":this.uiDialog.removeClass(this.options.dialogClass).addClass(uiDialogClasses+value);break;case"draggable":(value?this._makeDraggable():this.uiDialog.draggable('destroy'));break;case"height":this.uiDialog.height(value);break;case"position":this._position(value);break;case"resizable":var uiDialog=this.uiDialog,isResizable=this.uiDialog.is(':data(resizable)');(isResizable&&!value&&uiDialog.resizable('destroy'));(isResizable&&typeof value=='string'&&uiDialog.resizable('option','handles',value));(isResizable||this._makeResizable(value));break;case"title":$(".ui-dialog-title",this.uiDialogTitlebar).html(value||'&nbsp;');break;case"width":this.uiDialog.width(value);break;}
+$.widget.prototype._setData.apply(this,arguments);},_size:function(){var options=this.options;this.element.css({height:0,minHeight:0,width:'auto'});var nonContentHeight=this.uiDialog.css({height:'auto',width:options.width}).height();this.element.css({minHeight:Math.max(options.minHeight-nonContentHeight,0),height:options.height=='auto'?'auto':Math.max(options.height-nonContentHeight,0)});}});$.extend($.ui.dialog,{version:"1.7.2",defaults:{autoOpen:true,bgiframe:false,buttons:{},closeOnEscape:true,closeText:'close',dialogClass:'',draggable:true,hide:null,height:'auto',maxHeight:false,maxWidth:false,minHeight:150,minWidth:150,modal:false,position:'center',resizable:true,show:null,stack:true,title:'',width:300,zIndex:1000},getter:'isOpen',uuid:0,maxZ:0,getTitleId:function($el){return'ui-dialog-title-'+($el.attr('id')||++this.uuid);},overlay:function(dialog){this.$el=$.ui.dialog.overlay.create(dialog);}});$.extend($.ui.dialog.overlay,{instances:[],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){setTimeout(function(){if($.ui.dialog.overlay.instances.length){$(document).bind($.ui.dialog.overlay.events,function(event){var dialogZ=$(event.target).parents('.ui-dialog').css('zIndex')||0;return(dialogZ>$.ui.dialog.overlay.maxZ);});}},1);$(document).bind('keydown.dialog-overlay',function(event){(dialog.options.closeOnEscape&&event.keyCode&&event.keyCode==$.ui.keyCode.ESCAPE&&dialog.close(event));});$(window).bind('resize.dialog-overlay',$.ui.dialog.overlay.resize);}
+var $el=$('<div></div>').appendTo(document.body).addClass('ui-widget-overlay').css({width:this.width(),height:this.height()});(dialog.options.bgiframe&&$.fn.bgiframe&&$el.bgiframe());this.instances.push($el);return $el;},destroy:function($el){this.instances.splice($.inArray(this.instances,$el),1);if(this.instances.length===0){$([document,window]).unbind('.dialog-overlay');}
+$el.remove();var maxZ=0;$.each(this.instances,function(){maxZ=Math.max(maxZ,this.css('z-index'));});this.maxZ=maxZ;},height:function(){if($.browser.msie&&$.browser.version<7){var scrollHeight=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight);var offsetHeight=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight);if(scrollHeight<offsetHeight){return $(window).height()+'px';}else{return scrollHeight+'px';}}else{return $(document).height()+'px';}},width:function(){if($.browser.msie&&$.browser.version<7){var scrollWidth=Math.max(document.documentElement.scrollWidth,document.body.scrollWidth);var offsetWidth=Math.max(document.documentElement.offsetWidth,document.body.offsetWidth);if(scrollWidth<offsetWidth){return $(window).width()+'px';}else{return scrollWidth+'px';}}else{return $(document).width()+'px';}},resize:function(){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);(function($){$.widget("ui.tabs",{_init:function(){if(this.options.deselectable!==undefined){this.options.collapsible=this.options.deselectable;}
+this._tabify(true);},_setData:function(key,value){if(key=='selected'){if(this.options.collapsible&&value==this.options.selected){return;}
+this.select(value);}
+else{this.options[key]=value;if(key=='deselectable'){this.options.collapsible=value;}
+this._tabify();}},_tabId:function(a){return a.title&&a.title.replace(/\s/g,'_').replace(/[^A-Za-z0-9\-_:\.]/g,'')||this.options.idPrefix+$.data(a);},_sanitizeSelector:function(hash){return hash.replace(/:/g,'\\:');},_cookie:function(){var cookie=this.cookie||(this.cookie=this.options.cookie.name||'ui-tabs-'+$.data(this.list[0]));return $.cookie.apply(null,[cookie].concat($.makeArray(arguments)));},_ui:function(tab,panel){return{tab:tab,panel:panel,index:this.anchors.index(tab)};},_cleanup:function(){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){this.list=this.element.children('ul:first');this.lis=$('li:has(a[href])',this.list);this.anchors=this.lis.map(function(){return $('a',this)[0];});this.panels=$([]);var self=this,o=this.options;var fragmentId=/^#.+/;this.anchors.each(function(i,a){var href=$(a).attr('href');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;}
+if(fragmentId.test(href)){self.panels=self.panels.add(self._sanitizeSelector(href));}
+else if(href!='#'){$.data(a,'href.tabs',href);$.data(a,'load.tabs',href.replace(/#.*$/,''));var id=self._tabId(a);a.href='#'+id;var $panel=$('#'+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);}
+else{o.disabled.push(i);}});if(init){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');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||0;}
+else if(o.selected===null){o.selected=-1;}
+o.selected=((o.selected>=0&&this.anchors[o.selected])||o.selected<0)?o.selected:0;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);}
+this.panels.addClass('ui-tabs-hide');this.lis.removeClass('ui-tabs-selected ui-state-active');if(o.selected>=0&&this.anchors.length){this.panels.eq(o.selected).removeClass('ui-tabs-hide');this.lis.eq(o.selected).addClass('ui-tabs-selected ui-state-active');self.element.queue("tabs",function(){self._trigger('show',null,self._ui(self.anchors[o.selected],self.panels[o.selected]));});this.load(o.selected);}
+$(window).bind('unload',function(){self.lis.add(self.anchors).unbind('.tabs');self.lis=self.anchors=self.panels=null;});}
+else{o.selected=this.lis.index(this.lis.filter('.ui-tabs-selected'));}
+this.element[o.collapsible?'addClass':'removeClass']('ui-tabs-collapsible');if(o.cookie){this._cookie(o.selected,o.cookie);}
+for(var i=0,li;(li=this.lis[i]);i++){$(li)[$.inArray(i,o.disabled)!=-1&&!$(li).hasClass('ui-tabs-selected')?'addClass':'removeClass']('ui-state-disabled');}
+if(o.cache===false){this.anchors.removeData('cache.tabs');}
+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'));});}
+var hideFx,showFx;if(o.fx){if($.isArray(o.fx)){hideFx=o.fx[0];showFx=o.fx[1];}
+else{hideFx=showFx=o.fx;}}
+function resetStyle($el,fx){$el.css({display:''});if($.browser.msie&&fx.opacity){$el[0].style.removeAttribute('filter');}}
+var showTab=showFx?function(clicked,$show){$(clicked).closest('li').removeClass('ui-state-default').addClass('ui-tabs-selected ui-state-active');$show.hide().removeClass('ui-tabs-hide').animate(showFx,showFx.duration||'normal',function(){resetStyle($show,showFx);self._trigger('show',null,self._ui(clicked,$show[0]));});}:function(clicked,$show){$(clicked).closest('li').removeClass('ui-state-default').addClass('ui-tabs-selected ui-state-active');$show.removeClass('ui-tabs-hide');self._trigger('show',null,self._ui(clicked,$show[0]));};var hideTab=hideFx?function(clicked,$hide){$hide.animate(hideFx,hideFx.duration||'normal',function(){self.lis.removeClass('ui-tabs-selected ui-state-active').addClass('ui-state-default');$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').addClass('ui-state-default');$hide.addClass('ui-tabs-hide');self.element.dequeue("tabs");};this.anchors.bind(o.event+'.tabs',function(){var el=this,$li=$(this).closest('li'),$hide=self.panels.filter(':not(.ui-tabs-hide)'),$show=$(self._sanitizeSelector(this.hash));if(($li.hasClass('ui-tabs-selected')&&!o.collapsible)||$li.hasClass('ui-state-disabled')||$li.hasClass('ui-state-processing')||self._trigger('select',null,self._ui(this,$show[0]))===false){this.blur();return false;}
+o.selected=self.anchors.index(this);self.abort();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);});self.load(self.anchors.index(this));this.blur();return false;}}
+if(o.cookie){self._cookie(o.selected,o.cookie);}
+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.';}
+if($.browser.msie){this.blur();}});this.anchors.bind('click.tabs',function(){return false;});},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);}},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);var $panel=$('#'+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){$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]));},remove:function(index){var o=this.options,$li=this.lis.eq(index).remove(),$panel=this.panels.eq(index).remove();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]));},enable:function(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]));},disable:function(index){var self=this,o=this.options;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]));}},select:function(index){if(typeof index=='string'){index=this.anchors.index(this.anchors.filter('[href$='+index+']'));}
+else if(index===null){index=-1;}
+if(index==-1&&this.options.collapsible){index=this.options.selected;}
+this.anchors.eq(index).trigger(this.options.event+'.tabs');},load:function(index){var self=this,o=this.options,a=this.anchors.eq(index)[0],url=$.data(a,'load.tabs');this.abort();if(!url||this.element.queue("tabs").length!==0&&$.data(a,'cache.tabs')){this.element.dequeue("tabs");return;}
+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._sanitizeSelector(a.hash)).html(r);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){}
+self.element.dequeue("tabs");}}));},abort:function(){this.element.queue([]);this.panels.stop(false,true);if(this.xhr){this.xhr.abort();delete this.xhr;}
+this._cleanup();},url:function(index,url){this.anchors.eq(index).removeData('cache.tabs').data('load.tabs',url);},length:function(){return this.anchors.length;}});$.extend($.ui.tabs,{version:'1.7.2',getter:'length',defaults:{ajaxOptions:null,cache:false,cookie:null,collapsible:false,disabled:[],event:'click',fx:null,idPrefix:'ui-tabs-',panelTemplate:'<div></div>',spinner:'<em>Loading&#8230;</em>',tabTemplate:'<li><a href="#{href}"><span>#{label}</span></a></li>'}});$.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){self.rotate(null);}}:function(e){t=o.selected;rotate();});if(ms){this.element.bind('tabsshow',rotate);this.anchors.bind(o.event+'.tabs',stop);rotate();}
+else{clearTimeout(self.rotation);this.element.unbind('tabsshow',rotate);this.anchors.unbind(o.event+'.tabs',stop);delete this._rotate;delete this._unrotate;}}});})(jQuery);(function($){$.extend($.ui,{datepicker:{version:"1.7.2"}});var PROP_NAME='datepicker';function Datepicker(){this.debug=false;this._curInst=null;this._keyEvent=false;this._disabledInputs=[];this._datepickerShowing=false;this._inDialog=false;this._mainDivId='ui-datepicker-div';this._inlineClass='ui-datepicker-inline';this._appendClass='ui-datepicker-append';this._triggerClass='ui-datepicker-trigger';this._dialogClass='ui-datepicker-dialog';this._disableClass='ui-datepicker-disabled';this._unselectableClass='ui-datepicker-unselectable';this._currentClass='ui-datepicker-current-day';this._dayOverClass='ui-datepicker-days-cell-over';this.regional=[];this.regional['']={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'],dateFormat:'mm/dd/yy',firstDay:0,isRTL:false};this._defaults={showOn:'focus',showAnim:'show',showOptions:{},defaultDate:null,appendText:'',buttonText:'...',buttonImage:'',buttonImageOnly:false,hideIfNoPrevNext:false,navigationAsDateFormat:false,gotoCurrent:false,changeMonth:false,changeYear:false,showMonthAfterYear:false,yearRange:'-10:+10',showOtherMonths:false,calculateWeek:this.iso8601Week,shortYearCutoff:'+10',minDate:null,maxDate:null,duration:'normal',beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:'',altFormat:'',constrainInput:true,showButtonPanel:false};$.extend(this._defaults,this.regional['']);this.dpDiv=$('<div id="'+this._mainDivId+'" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>');}
+$.extend(Datepicker.prototype,{markerClassName:'hasDatepicker',log:function(){if(this.debug)
+console.log.apply('',arguments);},setDefaults:function(settings){extendRemove(this._defaults,settings||{});return this;},_attachDatepicker:function(target,settings){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)
+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);}},_newInst:function(target,inline){var id=target[0].id.replace(/([:\[\]\.])/g,'\\\\$1');return{id:id,input:target,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:inline,dpDiv:(!inline?this.dpDiv:$('<div class="'+this._inlineClass+' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))};},_connectDatepicker:function(target,inst){var input=$(target);inst.append=$([]);inst.trigger=$([]);if(input.hasClass(this.markerClassName))
+return;var appendText=this._get(inst,'appendText');var isRTL=this._get(inst,'isRTL');if(appendText){inst.append=$('<span class="'+this._appendClass+'">'+appendText+'</span>');input[isRTL?'before':'after'](inst.append);}
+var showOn=this._get(inst,'showOn');if(showOn=='focus'||showOn=='both')
+input.focus(this._showDatepicker);if(showOn=='button'||showOn=='both'){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==target)
+$.datepicker._hideDatepicker();else
+$.datepicker._showDatepicker(target);return false;});}
+input.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).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);},_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));this._updateDatepicker(inst);this._updateAlternate(inst);},_dialogDatepicker:function(input,dateText,onSelect,settings,pos){var inst=this._dialogInst;if(!inst){var id='dp'+(++this.uuid);this._dialogInput=$('<input type="text" id="'+id+'" size="1" style="position: absolute; top: -100px;"/>');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||{});this._dialogInput.val(dateText);this._pos=(pos?(pos.length?pos:[pos.pageX,pos.pageY]):null);if(!this._pos){var browserWidth=window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth;var browserHeight=window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight;var scrollX=document.documentElement.scrollLeft||document.body.scrollLeft;var scrollY=document.documentElement.scrollTop||document.body.scrollTop;this._pos=[(browserWidth/2)-100+scrollX,(browserHeight/2)-150+scrollY];}
+this._dialogInput.css('left',this._pos[0]+'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;},_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);}else if(nodeName=='div'||nodeName=='span')
+$target.removeClass(this.markerClassName).empty();},_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');}
+this._disabledInputs=$.map(this._disabledInputs,function(value){return(value==target?null:value);});},_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');}
+this._disabledInputs=$.map(this._disabledInputs,function(value){return(value==target?null:value);});this._disabledInputs[this._disabledInputs.length]=target;},_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;},_getInst:function(target){try{return $.data(target,PROP_NAME);}
+catch(err){throw'Missing instance data for this datepicker';}},_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(null);}
+var date=this._getDateDatepicker(target);extendRemove(inst.settings,settings);this._setDateDatepicker(target,date);this._updateDatepicker(inst);}},_changeDatepicker:function(target,name,value){this._optionDatepicker(target,name,value);},_refreshDatepicker:function(target){var inst=this._getInst(target);if(inst){this._updateDatepicker(inst);}},_setDateDatepicker:function(target,date,endDate){var inst=this._getInst(target);if(inst){this._setDate(inst,date,endDate);this._updateDatepicker(inst);this._updateAlternate(inst);}},_getDateDatepicker:function(target){var inst=this._getInst(target);if(inst&&!inst.inline)
+this._setDateFromField(inst);return(inst?this._getDate(inst):null);},_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(null,'');break;case 13:var sel=$('td.'+$.datepicker._dayOverClass+', td.'+$.datepicker._currentClass,inst.dpDiv);if(sel[0])
+$.datepicker._selectDay(event.target,inst.selectedMonth,inst.selectedYear,sel[0]);else
+$.datepicker._hideDatepicker(null,$.datepicker._get(inst,'duration'));return false;break;case 27:$.datepicker._hideDatepicker(null,$.datepicker._get(inst,'duration'));break;case 33:$.datepicker._adjustDate(event.target,(event.ctrlKey?-$.datepicker._get(inst,'stepBigMonths'):-$.datepicker._get(inst,'stepMonths')),'M');break;case 34:$.datepicker._adjustDate(event.target,(event.ctrlKey?+$.datepicker._get(inst,'stepBigMonths'):+$.datepicker._get(inst,'stepMonths')),'M');break;case 35:if(event.ctrlKey||event.metaKey)$.datepicker._clearDate(event.target);handled=event.ctrlKey||event.metaKey;break;case 36:if(event.ctrlKey||event.metaKey)$.datepicker._gotoToday(event.target);handled=event.ctrlKey||event.metaKey;break;case 37:if(event.ctrlKey||event.metaKey)$.datepicker._adjustDate(event.target,(isRTL?+1:-1),'D');handled=event.ctrlKey||event.metaKey;if(event.originalEvent.altKey)$.datepicker._adjustDate(event.target,(event.ctrlKey?-$.datepicker._get(inst,'stepBigMonths'):-$.datepicker._get(inst,'stepMonths')),'M');break;case 38:if(event.ctrlKey||event.metaKey)$.datepicker._adjustDate(event.target,-7,'D');handled=event.ctrlKey||event.metaKey;break;case 39:if(event.ctrlKey||event.metaKey)$.datepicker._adjustDate(event.target,(isRTL?-1:+1),'D');handled=event.ctrlKey||event.metaKey;if(event.originalEvent.altKey)$.datepicker._adjustDate(event.target,(event.ctrlKey?+$.datepicker._get(inst,'stepBigMonths'):+$.datepicker._get(inst,'stepMonths')),'M');break;case 40:if(event.ctrlKey||event.metaKey)$.datepicker._adjustDate(event.target,+7,'D');handled=event.ctrlKey||event.metaKey;break;default:handled=false;}
+else if(event.keyCode==36&&event.ctrlKey)
+$.datepicker._showDatepicker(this);else{handled=false;}
+if(handled){event.preventDefault();event.stopPropagation();}},_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||(chr<' '||!chars||chars.indexOf(chr)>-1);}},_showDatepicker:function(input){input=input.target||input;if(input.nodeName.toLowerCase()!='input')
+input=$('input',input.parentNode)[0];if($.datepicker._isDisabledDatepicker(input)||$.datepicker._lastInput==input)
+return;var inst=$.datepicker._getInst(input);var beforeShow=$.datepicker._get(inst,'beforeShow');extendRemove(inst.settings,(beforeShow?beforeShow.apply(input,[input,inst]):{}));$.datepicker._hideDatepicker(null,'');$.datepicker._lastInput=input;$.datepicker._setDateFromField(inst);if($.datepicker._inDialog)
+input.value='';if(!$.datepicker._pos){$.datepicker._pos=$.datepicker._findPos(input);$.datepicker._pos[1]+=input.offsetHeight;}
+var isFixed=false;$(input).parents().each(function(){isFixed|=$(this).css('position')=='fixed';return!isFixed;});if(isFixed&&$.browser.opera){$.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;inst.rangeStart=null;inst.dpDiv.css({position:'absolute',display:'block',top:'-1000px'});$.datepicker._updateDatepicker(inst);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')||'show';var duration=$.datepicker._get(inst,'duration');var postProcess=function(){$.datepicker._datepickerShowing=true;if($.browser.msie&&parseInt($.browser.version,10)<7)
+$('iframe.ui-datepicker-cover').css({width:inst.dpDiv.width()+4,height:inst.dpDiv.height()+4});};if($.effects&&$.effects[showAnim])
+inst.dpDiv.show(showAnim,$.datepicker._get(inst,'showOptions'),duration,postProcess);else
+inst.dpDiv[showAnim](duration,postProcess);if(duration=='')
+postProcess();if(inst.input[0].type!='hidden')
+inst.input[0].focus();$.datepicker._curInst=inst;}},_updateDatepicker:function(inst){var dims={width:inst.dpDiv.width()+4,height:inst.dpDiv.height()+4};var self=this;inst.dpDiv.empty().append(this._generateHTML(inst)).find('iframe.ui-datepicker-cover').css({width:dims.width,height:dims.height}).end().find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a').bind('mouseout',function(){$(this).removeClass('ui-state-hover');if(this.className.indexOf('ui-datepicker-prev')!=-1)$(this).removeClass('ui-datepicker-prev-hover');if(this.className.indexOf('ui-datepicker-next')!=-1)$(this).removeClass('ui-datepicker-next-hover');}).bind('mouseover',function(){if(!self._isDisabledDatepicker(inst.inline?inst.dpDiv.parent()[0]:inst.input[0])){$(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');$(this).addClass('ui-state-hover');if(this.className.indexOf('ui-datepicker-prev')!=-1)$(this).addClass('ui-datepicker-prev-hover');if(this.className.indexOf('ui-datepicker-next')!=-1)$(this).addClass('ui-datepicker-next-hover');}}).end().find('.'+this._dayOverClass+' a').trigger('mouseover').end();var numMonths=this._getNumberOfMonths(inst);var cols=numMonths[1];var width=17;if(cols>1){inst.dpDiv.addClass('ui-datepicker-multi-'+cols).css('width',(width*cols)+'em');}else{inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');}
+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.input&&inst.input[0].type!='hidden'&&inst==$.datepicker._curInst)
+$(inst.input[0]).focus();},_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=(window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth)+$(document).scrollLeft();var viewHeight=(window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight)+$(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;offset.left-=(offset.left+dpWidth>viewWidth&&viewWidth>dpWidth)?Math.abs(offset.left+dpWidth-viewWidth):0;offset.top-=(offset.top+dpHeight>viewHeight&&viewHeight>dpHeight)?Math.abs(offset.top+dpHeight+inputHeight*2-viewHeight):0;return offset;},_findPos:function(obj){while(obj&&(obj.type=='hidden'||obj.nodeType!=1)){obj=obj.nextSibling;}
+var position=$(obj).offset();return[position.left,position.top];},_hideDatepicker:function(input,duration){var inst=this._curInst;if(!inst||(input&&inst!=$.data(input,PROP_NAME)))
+return;if(inst.stayOpen)
+this._selectDate('#'+inst.id,this._formatDate(inst,inst.currentDay,inst.currentMonth,inst.currentYear));inst.stayOpen=false;if(this._datepickerShowing){duration=(duration!=null?duration:this._get(inst,'duration'));var showAnim=this._get(inst,'showAnim');var postProcess=function(){$.datepicker._tidyDialog(inst);};if(duration!=''&&$.effects&&$.effects[showAnim])
+inst.dpDiv.hide(showAnim,$.datepicker._get(inst,'showOptions'),duration,postProcess);else
+inst.dpDiv[(duration==''?'hide':(showAnim=='slideDown'?'slideUp':(showAnim=='fadeIn'?'fadeOut':'hide')))](duration,postProcess);if(duration=='')
+this._tidyDialog(inst);var onClose=this._get(inst,'onClose');if(onClose)
+onClose.apply((inst.input?inst.input[0]:null),[(inst.input?inst.input.val():''),inst]);this._datepickerShowing=false;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;}
+this._curInst=null;},_tidyDialog:function(inst){inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');},_checkExternalClick:function(event){if(!$.datepicker._curInst)
+return;var $target=$(event.target);if(($target.parents('#'+$.datepicker._mainDivId).length==0)&&!$target.hasClass($.datepicker.markerClassName)&&!$target.hasClass($.datepicker._triggerClass)&&$.datepicker._datepickerShowing&&!($.datepicker._inDialog&&$.blockUI))
+$.datepicker._hideDatepicker(null,'');},_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),period);this._updateDatepicker(inst);},_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);},_selectMonthYear:function(id,select,period){var target=$(id);var inst=this._getInst(target[0]);inst._selectingMonthYear=false;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);},_clickMonthYear:function(id){var target=$(id);var inst=this._getInst(target[0]);if(inst.input&&inst._selectingMonthYear&&!$.browser.msie)
+inst.input[0].focus();inst._selectingMonthYear=!inst._selectingMonthYear;},_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;if(inst.stayOpen){inst.endDay=inst.endMonth=inst.endYear=null;}
+this._selectDate(id,this._formatDate(inst,inst.currentDay,inst.currentMonth,inst.currentYear));if(inst.stayOpen){inst.rangeStart=this._daylightSavingAdjust(new Date(inst.currentYear,inst.currentMonth,inst.currentDay));this._updateDatepicker(inst);}},_clearDate:function(id){var target=$(id);var inst=this._getInst(target[0]);inst.stayOpen=false;inst.endDay=inst.endMonth=inst.endYear=inst.rangeStart=null;this._selectDate(target,'');},_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]);else if(inst.input)
+inst.input.trigger('change');if(inst.inline)
+this._updateDatepicker(inst);else if(!inst.stayOpen){this._hideDatepicker(null,this._get(inst,'duration'));this._lastInput=inst.input[0];if(typeof(inst.input[0])!='object')
+inst.input[0].focus();this._lastInput=null;}},_updateAlternate:function(inst){var altField=this._get(inst,'altField');if(altField){var altFormat=this._get(inst,'altFormat')||this._get(inst,'dateFormat');var date=this._getDate(inst);dateStr=this.formatDate(altFormat,date,this._getFormatConfig(inst));$(altField).each(function(){$(this).val(dateStr);});}},noWeekends:function(date){var day=date.getDay();return[(day>0&&day<6),''];},iso8601Week:function(date){var checkDate=new Date(date.getFullYear(),date.getMonth(),date.getDate());var firstMon=new Date(checkDate.getFullYear(),1-1,4);var firstDay=firstMon.getDay()||7;firstMon.setDate(firstMon.getDate()+1-firstDay);if(firstDay<4&&checkDate<firstMon){checkDate.setDate(checkDate.getDate()-3);return $.datepicker.iso8601Week(checkDate);}else if(checkDate>new Date(checkDate.getFullYear(),12-1,28)){firstDay=new Date(checkDate.getFullYear()+1,1-1,4).getDay()||7;if(firstDay>4&&(checkDate.getDay()||7)<firstDay-3){return 1;}}
+return Math.floor(((checkDate-firstMon)/86400000)/7)+1;},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;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;var lookAhead=function(match){var matches=(iFormat+1<format.length&&format.charAt(iFormat+1)==match);if(matches)
+iFormat++;return matches;};var getNumber=function(match){lookAhead(match);var origSize=(match=='@'?14:(match=='y'?4:(match=='o'?3:2)));var size=origSize;var num=0;while(size>0&&iValue<value.length&&value.charAt(iValue)>='0'&&value.charAt(iValue)<='9'){num=num*10+parseInt(value.charAt(iValue++),10);size--;}
+if(size==origSize)
+throw'Missing number at position '+iValue;return num;};var getName=function(match,shortNames,longNames){var names=(lookAhead(match)?longNames:shortNames);var size=0;for(var j=0;j<names.length;j++)
+size=Math.max(size,names[j].length);var name='';var iInit=iValue;while(size>0&&iValue<value.length){name+=value.charAt(iValue++);for(var i=0;i<names.length;i++)
+if(name==names[i])
+return i+1;size--;}
+throw'Unknown name at position '+iInit;};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"'":if(lookAhead("'"))
+checkLiteral();else
+literal=true;break;default:checkLiteral();}}
+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';return date;},ATOM:'yy-mm-dd',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',TIMESTAMP:'@',W3C:'yy-mm-dd',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;var lookAhead=function(match){var matches=(iFormat+1<format.length&&format.charAt(iFormat+1)==match);if(matches)
+iFormat++;return matches;};var formatNumber=function(match,value,len){var num=''+value;if(lookAhead(match))
+while(num.length<len)
+num='0'+num;return num;};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':var doy=date.getDate();for(var m=date.getMonth()-1;m>=0;m--)
+doy+=this._getDaysInMonth(date.getFullYear(),m);output+=formatNumber('o',doy,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"'":if(lookAhead("'"))
+output+="'";else
+literal=true;break;default:output+=format.charAt(iFormat);}}
+return output;},_possibleChars:function(format){var chars='';var literal=false;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;case"'":if(lookAhead("'"))
+chars+="'";else
+literal=true;break;default:chars+=format.charAt(iFormat);}
+return chars;},_get:function(inst,name){return inst.settings[name]!==undefined?inst.settings[name]:this._defaults[name];},_setDateFromField:function(inst){var dateFormat=this._get(inst,'dateFormat');var dates=inst.input?inst.input.val():null;inst.endDay=inst.endMonth=inst.endYear=null;var date=defaultDate=this._getDefaultDate(inst);var settings=this._getFormatConfig(inst);try{date=this.parseDate(dateFormat,dates,settings)||defaultDate;}catch(event){this.log(event);date=defaultDate;}
+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);},_getDefaultDate:function(inst){var date=this._determineDate(this._get(inst,'defaultDate'),new Date());var minDate=this._getMinMaxDate(inst,'min',true);var maxDate=this._getMinMaxDate(inst,'max');date=(minDate&&date<minDate?minDate:date);date=(maxDate&&date>maxDate?maxDate:date);return date;},_determineDate:function(date,defaultDate){var offsetNumeric=function(offset){var date=new Date();date.setDate(date.getDate()+offset);return date;};var offsetString=function(offset,getDaysInMonth){var date=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,getDaysInMonth(year,month));break;case'y':case'Y':year+=parseInt(matches[1],10);day=Math.min(day,getDaysInMonth(year,month));break;}
+matches=pattern.exec(offset);}
+return new Date(year,month,day);};date=(date==null?defaultDate:(typeof date=='string'?offsetString(date,this._getDaysInMonth):(typeof date=='number'?(isNaN(date)?defaultDate:offsetNumeric(date)):date)));date=(date&&date.toString()=='Invalid Date'?defaultDate:date);if(date){date.setHours(0);date.setMinutes(0);date.setSeconds(0);date.setMilliseconds(0);}
+return this._daylightSavingAdjust(date);},_daylightSavingAdjust:function(date){if(!date)return null;date.setHours(date.getHours()>12?date.getHours()+2:0);return date;},_setDate:function(inst,date,endDate){var clear=!(date);var origMonth=inst.selectedMonth;var origYear=inst.selectedYear;date=this._determineDate(date,new Date());inst.selectedDay=inst.currentDay=date.getDate();inst.drawMonth=inst.selectedMonth=inst.currentMonth=date.getMonth();inst.drawYear=inst.selectedYear=inst.currentYear=date.getFullYear();if(origMonth!=inst.selectedMonth||origYear!=inst.selectedYear)
+this._notifyChange(inst);this._adjustInstDate(inst);if(inst.input){inst.input.val(clear?'':this._formatDate(inst));}},_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;},_generateHTML:function(inst){var today=new Date();today=this._daylightSavingAdjust(new Date(today.getFullYear(),today.getMonth(),today.getDate()));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 stepBigMonths=this._get(inst,'stepBigMonths');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',true);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[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" onclick="DP_jQuery.datepicker._adjustDate(\'#'+inst.id+'\', -'+stepMonths+', \'M\');"'+' 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" onclick="DP_jQuery.datepicker._adjustDate(\'#'+inst.id+'\', +'+stepMonths+', \'M\');"'+' 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" onclick="DP_jQuery.datepicker._hideDatepicker();">'+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" onclick="DP_jQuery.datepicker._gotoToday(\'#'+inst.id+'\');"'+'>'+currentText+'</button>':'')+(isRTL?'':controls)+'</div>':'';var firstDay=parseInt(this._get(inst,'firstDay'),10);firstDay=(isNaN(firstDay)?0:firstDay);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 calculateWeek=this._get(inst,'calculateWeek')||this.iso8601Week;var endDate=inst.endDay?this._daylightSavingAdjust(new Date(inst.endYear,inst.endMonth,inst.endDay)):currentDate;var defaultDate=this._getDefaultDate(inst);var html='';for(var row=0;row<numMonths[0];row++){var group='';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 ui-datepicker-group-';switch(col){case 0:calender+='first';cornerClass=' ui-corner-'+(isRTL?'right':'left');break;case numMonths[1]-1:calender+='last';cornerClass=' ui-corner-'+(isRTL?'left':'right');break;default:calender+='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,selectedDate,row>0||col>0,monthNames,monthNamesShort)+'</div><table class="ui-datepicker-calendar"><thead>'+'<tr>';var thead='';for(var dow=0;dow<7;dow++){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 numRows=(isMultiMonth?6:Math.ceil((leadDays+daysInMonth)/7));var printDate=this._daylightSavingAdjust(new Date(drawYear,drawMonth,1-leadDays));for(var dRow=0;dRow<numRows;dRow++){calender+='<tr>';var tbody='';for(var dow=0;dow<7;dow++){var daySettings=(beforeShowDay?beforeShowDay.apply((inst.input?inst.input[0]:null),[printDate]):[true,'']);var otherMonth=(printDate.getMonth()!=drawMonth);var unselectable=otherMonth||!daySettings[0]||(minDate&&printDate<minDate)||(maxDate&&printDate>maxDate);tbody+='<td class="'+
+((dow+firstDay+6)%7>=5?' ui-datepicker-week-end':'')+
+(otherMonth?' ui-datepicker-other-month':'')+
+((printDate.getTime()==selectedDate.getTime()&&drawMonth==inst.selectedMonth&&inst._keyEvent)||(defaultDate.getTime()==printDate.getTime()&&defaultDate.getTime()==selectedDate.getTime())?' '+this._dayOverClass:'')+
+(unselectable?' '+this._unselectableClass+' ui-state-disabled':'')+
+(otherMonth&&!showOtherMonths?'':' '+daySettings[1]+
+(printDate.getTime()>=currentDate.getTime()&&printDate.getTime()<=endDate.getTime()?' '+this._currentClass:'')+
+(printDate.getTime()==today.getTime()?' ui-datepicker-today':''))+'"'+
+((!otherMonth||showOtherMonths)&&daySettings[2]?' title="'+daySettings[2]+'"':'')+
+(unselectable?'':' onclick="DP_jQuery.datepicker._selectDay(\'#'+
+inst.id+'\','+drawMonth+','+drawYear+', this);return false;"')+'>'+
+(otherMonth?(showOtherMonths?printDate.getDate():'&#xa0;'):(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()&&printDate.getTime()<=endDate.getTime()?' ui-state-active':'')+'" href="#">'+printDate.getDate()+'</a>'))+'</td>';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;},_generateMonthYearHeader:function(inst,drawMonth,drawYear,minDate,maxDate,selectedDate,secondary,monthNames,monthNamesShort){minDate=(inst.rangeStart&&minDate&&selectedDate<minDate?selectedDate:minDate);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='';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" '+'onchange="DP_jQuery.datepicker._selectMonthYear(\'#'+inst.id+'\', this, \'M\');" '+'onclick="DP_jQuery.datepicker._clickMonthYear(\'#'+inst.id+'\');"'+'>';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)&&(!(changeMonth&&changeYear))?'&#xa0;':'');if(secondary||!changeYear)
+html+='<span class="ui-datepicker-year">'+drawYear+'</span>';else{var years=this._get(inst,'yearRange').split(':');var year=0;var endYear=0;if(years.length!=2){year=drawYear-10;endYear=drawYear+10;}else if(years[0].charAt(0)=='+'||years[0].charAt(0)=='-'){year=drawYear+parseInt(years[0],10);endYear=drawYear+parseInt(years[1],10);}else{year=parseInt(years[0],10);endYear=parseInt(years[1],10);}
+year=(minDate?Math.max(year,minDate.getFullYear()):year);endYear=(maxDate?Math.min(endYear,maxDate.getFullYear()):endYear);html+='<select class="ui-datepicker-year" '+'onchange="DP_jQuery.datepicker._selectMonthYear(\'#'+inst.id+'\', this, \'Y\');" '+'onclick="DP_jQuery.datepicker._clickMonthYear(\'#'+inst.id+'\');"'+'>';for(;year<=endYear;year++){html+='<option value="'+year+'"'+
+(year==drawYear?' selected="selected"':'')+'>'+year+'</option>';}
+html+='</select>';}
+if(showMonthAfterYear)
+html+=(secondary||changeMonth||changeYear?'&#xa0;':'')+monthHtml;html+='</div>';return html;},_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._daylightSavingAdjust(new Date(year,month,day));var minDate=this._getMinMaxDate(inst,'min',true);var maxDate=this._getMinMaxDate(inst,'max');date=(minDate&&date<minDate?minDate:date);date=(maxDate&&date>maxDate?maxDate:date);inst.selectedDay=date.getDate();inst.drawMonth=inst.selectedMonth=date.getMonth();inst.drawYear=inst.selectedYear=date.getFullYear();if(period=='M'||period=='Y')
+this._notifyChange(inst);},_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]);},_getNumberOfMonths:function(inst){var numMonths=this._get(inst,'numberOfMonths');return(numMonths==null?[1,1]:(typeof numMonths=='number'?[1,numMonths]:numMonths));},_getMinMaxDate:function(inst,minMax,checkRange){var date=this._determineDate(this._get(inst,minMax+'Date'),null);return(!checkRange||!inst.rangeStart?date:(!date||inst.rangeStart>date?inst.rangeStart:date));},_getDaysInMonth:function(year,month){return 32-new Date(year,month,32).getDate();},_getFirstDayOfMonth:function(year,month){return new Date(year,month,1).getDay();},_canAdjustMonth:function(inst,offset,curYear,curMonth){var numMonths=this._getNumberOfMonths(inst);var date=this._daylightSavingAdjust(new Date(curYear,curMonth+(offset<0?offset:numMonths[1]),1));if(offset<0)
+date.setDate(this._getDaysInMonth(date.getFullYear(),date.getMonth()));return this._isInRange(inst,date);},_isInRange:function(inst,date){var newMinDate=(!inst.rangeStart?null:this._daylightSavingAdjust(new Date(inst.selectedYear,inst.selectedMonth,inst.selectedDay)));newMinDate=(newMinDate&&inst.rangeStart<newMinDate?inst.rangeStart:newMinDate);var minDate=newMinDate||this._getMinMaxDate(inst,'min');var maxDate=this._getMinMaxDate(inst,'max');return((!minDate||date>=minDate)&&(!maxDate||date<=maxDate));},_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')};},_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));}});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;};function isArray(a){return(a&&(($.browser.safari&&typeof a=='object'&&a.length)||(a.constructor&&a.constructor.toString().match(/\Array\(\)/))));};$.fn.datepicker=function(options){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'))
+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();$.datepicker.initialized=false;$.datepicker.uuid=new Date().getTime();$.datepicker.version="1.7.2";window.DP_jQuery=$;})(jQuery);if(!gMsg)var gMsg={};function loadGM(msgSet){for(var i in msgSet){gMsg[i]=msgSet[i];}}
+function gM(key,args){var ms='';if(key in gMsg){ms=gMsg[key];if(typeof args=='object'||typeof args=='array'){for(var v in args){var rep='\$'+(parseInt(v)+1);ms=ms.replace(rep,args[v]);}}else if(typeof args=='string'||typeof args=='number'){ms=ms.replace(/\$1/,args);}
+return ms;}else{return'['+key+']';}}
+$j=jQuery.noConflict();function js2AddOnloadHook(func){$j(document).ready(func);}
+mvJsLoader={doLoad:function(deps,callback){callback();}};
\ No newline at end of file
diff --git a/js2/mwEmbed/README b/js2/mwEmbed/README
new file mode 100644 (file)
index 0000000..17f3a63
--- /dev/null
@@ -0,0 +1,90 @@
+***********************************************
+*
+* mwEmbed version 1.2
+* for details see: http://www.mediawiki.org/wiki/MwEmbed
+* For an overview of all mwEmbed files see: 
+* http://www.mediawiki.org/wiki/MwEmbed
+*
+* All Metavid Wiki code is Released under the GPL2
+*
+* @author Michael Dale, 
+* @email mdale@wikimedia.org
+*
+*********************************************
+
+v.1.1
+Major refactoring lots of new interfaces (full release info to follow shortly)
+
+v.6
+* added msg system for compatibility with translations
+* add support for relative file or path names for media files for cortado.
+* added support for safari
+** will force load javascript instead of DOM injection
+** slower on pages without video clips
+* added "experimental" support for "sequences" and editing. (see http://metavid.ucsc.edu/blog/
+* improved playlists usage
+
+v.5
+* add support for playlists, basic usage: <playlist id="plid" src="playlist.xml"/>
+       * see sample_page.php for example usage of playlist
+* better support for different resolutions.
+* inline playlist:
+
+
+
+
+v.4
+* adds support for oggplay with playhead: http://www.annodex.net/software/plugin/index.html
+* adds linkback support (for adding a link back to a particular page)
+* adds config value for selecting cortado in an iframe or loaded in the page
+
+v.3 an intermediary release: supports vlc, basic cortado, basic mplayer/totem
+well tested browsers are firefox & IE 6 (more testing needed for more browsers)
+
+
+the goal of mv_embed is to create a complete/wrapper fall back system for
+the liboggplay API:
+
+http://wiki.xiph.org/index.php/OggPlayJavascriptAPI
+
+& integrate the video element as close as possible with the html5 spec:
+http://www.whatwg.org/specs/web-apps/current-work/#video
+
+it attempts to wrap these calls for the following players:
+I try to include a link to their Javascript apis if I can find one:
+
+(initially just cortado and vlc)
+cortado applet: a custom build of the fluendos java based applet
+(included with the mv_embed package in the future we should get a signed applet hosted
+so that cross domain video playing does not require a copy of cortado+iframe on that server)
+    http://www.flumotion.net/cortado/
+
+vlc plugin: video lan client plugin
+    http://www.videolan.org/doc/play-howto/en/ch04.html#id293992
+
+mplayer plugin: the mplayer plugin
+    http://mplayerplug-in.cvs.sourceforge.net/mplayerplug-in/mplayerplug-in/DOCS/tech/javascript.txt?view=markup
+
+totem:
+    http://www.gnome.org/projects/totem/
+
+
+Sample Usage:
+<script type="text/javascript" src="mv_embed.js" />
+<video id="video_id" src="video_url"></video>
+
+once the page loads the video_id object is rewritten as an mv_embed object
+
+
+Supported Attributes for <video> tag:
+type   name            [default]       description
+bool    autoplay    [false]    if the clip should play on page load
+bool    controls       [true]          if the default interface should be displayed (see interface)
+string  id          null       the id of the html element useful for grabbing the video object
+string  src                    null            the url src for the video file
+string  thumbnail   logo       the thumbnail to be displayed a frame grab is ideal.
+string  linkback    link       a info link back for more info about this stream
+                                                               (useful for when the clip is embed externally)
+int     width       [320]      the video display width
+int     height      [240]      the video display height
+bool    embed_link  [ture]             if the html to embed this clip on an external page should be displayed
diff --git a/js2/mwEmbed/example_usage/Add_Media_Wizard.html b/js2/mwEmbed/example_usage/Add_Media_Wizard.html
new file mode 100644 (file)
index 0000000..b6cbfbb
--- /dev/null
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+       <title>sample mv embed</title>
+       <style type="text/css">
+               body{
+                       font-size:80%;
+               }
+               img  {
+                       border:medium none;
+               }
+       </style>
+       <script type="text/javascript" src="../mv_embed.js?debug=true"></script>         
+       <!--<script type="text/javascript" src="../jsScriptLoader.php?class=window.jQuery,mv_embed,remoteSearchDriver,$j.ui,$j.ui.resizable,$j.ui.draggable,$j.ui.dialog,$j.ui.tabs,$j.ui.sortable,$j.cookie,baseRemoteSearch&urid=1257728132531&debug=true&uselang=en"></script> -->            
+       <script type="text/javascript">
+       js2AddOnloadHook(function(){
+               $j('#add_media_link').addMediaWiz( {
+                       'profile':'html_edit',                  
+                       'target_textbox': '#wpTextbox1',
+                       'target_render_area':'#inline_append',                  
+                       'import_url_mode':'remote_link',        
+                       'remote_insert_description' : true,
+                       //note selections in the textbox will take over the default query
+                       'default_query': 'fish',        
+                       
+                       //we only enabled commons
+               //(since javascript includes from other servers would be problamatic ) in a default install
+            //** but you can set this to 'all' to pull from multiple repositories  
+            'enabled_cps':['wiki_commons'],            
+                       
+                       //the local wiki api url: 
+                       'local_wiki_api_url': 'none'
+               });                     
+       });     
+       
+       </script> 
+</head>
+<body>
+<h3> Sample Add Media Wizard </h3>
+
+<a id="add_media_link" href="#">Add Media</a><br>
+<b>note</b> only commons is enabled by default. For more options see source code.<br><br> 
+<table border="1" width="800">
+<tr>
+<td valign="top" width="50%" id="inline_append">Asset Output</td>
+<td  valign="top" width="50%" >Html Output:<textarea id="wpTextbox1" cols="60" rows="6" id="code_append" name="wpTextbox1" tabindex="3"/></textarea></td>
+</tr>
+</table>
+</body>
+</html>
+
diff --git a/js2/mwEmbed/example_usage/Firefogg_Make_Advanced.html b/js2/mwEmbed/example_usage/Firefogg_Make_Advanced.html
new file mode 100644 (file)
index 0000000..d22744e
--- /dev/null
@@ -0,0 +1,96 @@
+<!DOCTYPE HTML>
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+    <title>Firefogg - Make Ogg Video in your Browser</title>
+       <script type="text/javascript" src="../jsScriptLoader.php?urid=r58125&class=mv_embed,window.jQuery,mvBaseUploadInterface,mvFirefogg,mvAdvFirefogg,$j.ui,$j.ui.progressbar,$j.ui.dialog,$j.cookie,$j.ui.accordion,$j.ui.slider,$j.ui.datepicker,$j.ui.draggable"></script>       
+       <!--  <script type="text/javascript" src="../mv_embed.js"></script> -->
+<style type="text/css" media="all">body {
+  margin: 0;
+  padding: 0;
+  font-family: Vera Sans, sans-serif;
+  font-size: 12px;
+  color: #000;
+  background: #fff;
+}
+
+a {
+  color: #000;
+}
+img {
+  border: 0;
+}
+h1, h2 {
+  text-align: center;
+}
+h1 {
+  font-size: 48px;
+  letter-spacing: 0.25em;
+  margin-bottom: 0;
+  line-height: 0.8em;
+}
+h2 {
+  margin-left: -11px;
+  font-size: 12px;
+  font-weight: normal;
+  letter-spacing: 0.1em;
+}
+
+#main {
+  margin-top: 10px;
+}
+
+.install {
+  margin-left: auto;
+  margin-right: auto;
+  width: 180px;
+  padding: 8px;
+  background-color: #fe0000;
+  font-size: 12px;
+  font-weight: bold;
+  text-align: center;
+}
+
+.install a {
+  color: #000;
+}
+
+#nav {
+  margin-left: -11px;
+  text-align: center;
+  padding-bottom: 20px;
+}
+</style>
+<style type="text/css" media="all">
+.install{
+display:none;
+}
+</style>
+<script type="text/javascript">
+mwAddOnloadHook(function(){
+       $j('#firefogg_app').firefogg({
+                       'encoder_interface'     : true,
+                       'encode_local'          : true
+       },function(){
+               $j('#loadFogg').hide();
+       });
+});
+</script>
+</head><body>
+<div id="main">
+  <h1>
+<a href="http://firefogg.org/index.html">
+       <img alt="Firefogg" src="../skins/mvpcf/images/firefogg_logo.png"/>
+</a><br>
+Make Ogg Video</h1>
+<br>   
+       <br>
+       <div style="margin-right:auto;margin-left:auto;width:500px;" id="loadFogg">Loading firefogg...</div>    
+       <div style="margin-right:auto;margin-left:auto;width:500px;height:230px"  id="firefogg_app"></div>
+       
+       <div style="height:295px"></div>
+       <center><span style="font:size:80%">Built using <a href="http://firefogg.org">firefogg</a>, <a href="http://www.mediawiki.org/wiki/Media_Projects_Overview#MwEmbed">MwEmbed</a> and <a href="http://jqueryui.com/">jquery.ui</a>. Supports  
+               custom themes via the <a href="http://jqueryui.com/themeroller/developertool/">ThemeRoller Dev Tool</a>
+       </span>
+       </center>
+</body></html>
+
diff --git a/js2/mwEmbed/example_usage/Multi_Upload.html b/js2/mwEmbed/example_usage/Multi_Upload.html
new file mode 100644 (file)
index 0000000..5a81028
--- /dev/null
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+       <title>Sample Themed Player</title>
+       <script type="text/javascript" src="../mv_embed.js"></script>    
+</head>
+<script type="text/javascript">
+mwAddOnloadHook(function(){
+       //bind the upload drag and drop
+       
+       //bind the multiple Files               
+});
+</script>
+<body>
+<h3> Multiple File Upload:</h3>
+<div style="-moz-border-radius:15px 15px 15px 15px;padding:10px;border:2px dotted #AAA;width:400px;height:200px">
+<h3>Drag and Drop Files here</h3>
+</div>
+<h3> Or select multiple Files here</h3>
+<form action='#' method='post' enctype='multipart/form-data'>
+  <input name='uploads[]' type=file multiple>
+  <input type='submit'>
+</form>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/js2/mwEmbed/example_usage/Player_Audio.html b/js2/mwEmbed/example_usage/Player_Audio.html
new file mode 100644 (file)
index 0000000..81e89f9
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+       <script type="text/javascript" src="../mv_embed.js?debug=true"></script>
+<title>Audio Player sample</title>
+</head>
+<body>
+<h3> Audio Player </h3>
+<audio src="http://upload.wikimedia.org/wikipedia/commons/4/4c/Faurepiece.ogg" durationHint="164"></audio>
+</body>
+</html>
\ No newline at end of file
diff --git a/js2/mwEmbed/example_usage/Player_RelatedVideos.html b/js2/mwEmbed/example_usage/Player_RelatedVideos.html
new file mode 100644 (file)
index 0000000..26f5180
--- /dev/null
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+       <title>Simple Video Tag Usage</title>
+       <script type="text/javascript" src="../mv_embed.js?debug=true"></script>
+</head>
+<body>
+<h3> Related Videos </h3>
+
+<span id="default_attr">
+</span> <br />
+<br />
+  <table border="1" cellpadding="6" width="600">
+                   <tr>
+             <td valign="top"> 
+             <video wikiTitleKey="B-36_bomber.ogg" durationHint="2" poster="http://upload.wikimedia.org/wikipedia/commons/thumb/0/0d/B-36_bomber.ogg/mid-B-36_bomber.ogg.jpg&size=400x300" src="http://upload.wikimedia.org/wikipedia/commons/0/0d/B-36_bomber.ogg"></video></td>
+             <td valign="top"><b>Sample Related Videos</b><br />
+               <pre>The Example Code ::: </pre>
+               &lt;video wikiTitleKey="File:B-36_bomber.ogg" durationHint="2"
+                    poster="http://upload.wikimedia.org/wikipedia/commons/thumb/0/0d/B-36_bomber.ogg/mid-B-36_bomber.ogg.jpg&size=400x300"
+               src="http://upload.wikimedia.org/wikipedia/commons/0/0d/B-36_bomber.ogg"&gt;&lt;/video&gt;
+               </br>
+             </td>
+             </table>
+       <br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />&nbsp;
+  </body>
+</html>        
+
diff --git a/js2/mwEmbed/example_usage/Player_Themable.html b/js2/mwEmbed/example_usage/Player_Themable.html
new file mode 100644 (file)
index 0000000..eb9439b
--- /dev/null
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+       <title>Sample Themed Player</title>
+       <!-- <script type="text/javascript" src="../jsScriptLoader.php?class=mv_embed,embedVideo&urid=1"></script> -->   
+       <script type="text/javascript" src="../mv_embed.js?debug=true"></script>         
+</head>
+<script type="text/javascript">
+</script>
+<body>
+<h3> Sample Themable Player:</h3>
+To play with dynamic Themes install <a href="http://jqueryui.com/themeroller/developertool/">Themeroller</a><p><p>
+
+<div style="width:450px;float:left">
+<video src="http://upload.wikimedia.org/wikipedia/commons/2/29/Charles_Lindbergh_flight_to_Brussels.ogg" 
+               poster="http://upload.wikimedia.org/wikipedia/commons/thumb/2/29/Charles_Lindbergh_flight_to_Brussels.ogg/mid-Charles_Lindbergh_flight_to_Brussels.ogg.jpg" durationHint="15"></video>
+<video style="width:208px;height:160px;float:left" src="http://upload.wikimedia.org/wikipedia/commons/2/29/Charles_Lindbergh_flight_to_Brussels.ogg" 
+               poster="http://upload.wikimedia.org/wikipedia/commons/thumb/2/29/Charles_Lindbergh_flight_to_Brussels.ogg/mid-Charles_Lindbergh_flight_to_Brussels.ogg.jpg" durationHint="15"></video>
+<b>Source Code used:</b><br>
+<textarea cols="50" rows="7"><video style="width:400px;height:288px" poster="http://upload.wikimedia.org/wikipedia/commons/thumb/2/29/Charles_Lindbergh_flight_to_Brussels.ogg/mid-Charles_Lindbergh_flight_to_Brussels.ogg.jpg" 
+src="http://upload.wikimedia.org/wikipedia/commons/2/29/Charles_Lindbergh_flight_to_Brussels.ogg"></video></textarea>
+</div>
+
+<div style="width:450px;float:left">
+<video class="kskin" src="http://upload.wikimedia.org/wikipedia/commons/2/29/Charles_Lindbergh_flight_to_Brussels.ogg" 
+               poster="http://upload.wikimedia.org/wikipedia/commons/thumb/2/29/Charles_Lindbergh_flight_to_Brussels.ogg/mid-Charles_Lindbergh_flight_to_Brussels.ogg.jpg" durationHint="15"></video>
+<video class="kskin" style="width:208px;height:160px;float:left;" src="http://upload.wikimedia.org/wikipedia/commons/2/29/Charles_Lindbergh_flight_to_Brussels.ogg" 
+               poster="http://upload.wikimedia.org/wikipedia/commons/thumb/2/29/Charles_Lindbergh_flight_to_Brussels.ogg/mid-Charles_Lindbergh_flight_to_Brussels.ogg.jpg" durationHint="15"></video>
+<b>(kskin) Source Code used:</b><br>
+<textarea cols="50" rows="7"><video class="kskin" style="width:400px;height:288px" poster="http://upload.wikimedia.org/wikipedia/commons/thumb/2/29/Charles_Lindbergh_flight_to_Brussels.ogg/mid-Charles_Lindbergh_flight_to_Brussels.ogg.jpg" 
+src="http://upload.wikimedia.org/wikipedia/commons/2/29/Charles_Lindbergh_flight_to_Brussels.ogg"></video></textarea>
+</div>
+
+
+</body>
+</html>
+
diff --git a/js2/mwEmbed/example_usage/Player_Timed_Text.html b/js2/mwEmbed/example_usage/Player_Timed_Text.html
new file mode 100644 (file)
index 0000000..bd7ea6c
--- /dev/null
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+       <title>sample mv embed</title>
+       <script type="text/javascript" src="../mv_embed.js?debug=true"></script>                 
+</head>
+<body>
+<h3> Mv_Embed Timed Text Examples:</h3>
+Click on the little lower right "CC" icon to expose the timed text
+ <table border="1" cellpadding="6" width="950">
+       <tr>            
+               <td valign="top" width="410">
+
+                       <video roe="http://metavid.org/w/index.php?title=Special:MvExportStream&stream_name=House_proceeding_07-18-06_00&t=1:23:16/1:23:44&feed_format=roe" ></video>           </td>
+               <td valign="top">
+                       Metavid based ROE file using CMML<br> <pre>&lt;video roe=&quot;http://metavid.org/w/index.php?title=Special:MvExportStream&amp;stream_name=House_proceeding_07-18-06_00&amp;t=1:23:16/1:23:44&amp;feed_format=roe&quot; &gt;&lt;/video&gt;</pre><iframe width="600" height="250" src="http://metavid.org/w/index.php?title=Special:MvExportStream&stream_name=House_proceeding_07-18-06_00&t=1:23:16/1:23:44&feed_format=roe" ></iframe>                </td>
+
+       </tr>
+       <tr>            
+               <td valign="top" width="410">
+               <video poster="http://ia340929.us.archive.org/0/items/princess_iron_fan/princess_iron_fan.thumbs/princess_iron_fan_000360.jpg"
+               duration="1:13:0" linkback="http://www.archive.org/details/princess_iron_fan" >
+                       <source type="video/ogg" src="http://www.archive.org/download/princess_iron_fan/princess_iron_fan.ogv" ></source>
+                       <source type="video/h264" src="http://www.archive.org/download/princess_iron_fan/princess_iron_fan_512kb.mp4"></source>
+                       <text category="SUB" lang="en" type="text/x-srt" default="true"
+                               title="English subtitles" src="media/princess_archive_org/princess_iron_fan.srt">
+                       </text>
+                       <text category="SUB" lang="cs" type="text/x-srt"
+                               title="Czech subtitles" src="media/princess_archive_org/princess_iron_fan-cs.srt">
+                       </text>
+                       <text category="SUB" lang="ru" type="text/x-srt"
+                               title="Russian subtitles" src="media/princess_archive_org/princess_iron_fan-ru.srt">
+                       </text>
+               </video>                
+               </td>
+
+               <td valign="top">
+                       <h4>Archive.org video with local SRTs (copied locally until we get srt over json for archive.org ;)</h4> 
+                       <textarea cols="120" rows="12">
+<video poster="http://www.archive.org/download/princess_iron_fan/format=thumbnail"  URLTimeEncoding="true"
+       durationHint="1:13:0" linkback="http://www.archive.org/details/princess_iron_fan">
+               <source type="video/ogg" src="http://www.archive.org/download/princess_iron_fan/princess_iron_fan.ogv"></source>
+               <source type="video/h264" src="http://www.archive.org/download/princess_iron_fan/princess_iron_fan_512kb.mp4"></source>
+       <text category="SUB" lang="en" type="text/x-srt" default="true"
+               title="English subtitles" src="media/princess_archive_org/princess_iron_fan.srt">
+       </text>
+       <text category="SUB" lang="cs" type="text/x-srt"
+               title="Czech subtitles" src="media/princess_archive_org/princess_iron_fan-cs.srt">
+       </text>
+       <text category="SUB" lang="ru" type="text/x-srt"
+               title="Russian subtitles" src="media/princess_archive_org/princess_iron_fan-ru.srt">
+       </text>
+</video> 
+                       </textarea>             </td>
+       </tr>
+ </table>
+
+</body>
+</html>
+
diff --git a/js2/mwEmbed/example_usage/Sequence_Editor.html b/js2/mwEmbed/example_usage/Sequence_Editor.html
new file mode 100644 (file)
index 0000000..48014cd
--- /dev/null
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+       <title>SMIL Sequence Editor example</title>
+       <script type="text/javascript" src="../mv_embed.js?debug=true"></script>
+       <script type="text/javascript">
+               mwAddOnloadHook(function(){
+                       $j('#seqcontainer').sequencer({
+                       'mv_pl_src':'media/sample_smil.xml',
+                       //set the add media wizard to only include commons:   
+                       'amw_conf':{
+                                'enabled_cps':['wiki_commons']
+                       }               
+               });
+               });
+       </script>
+<style>
+       body {
+               font: x-small sans-serif;
+               background: #f9f9f9 url(headbg.jpg) 0 0 no-repeat;
+               color: black;
+               margin: 0;
+               padding: 0;
+       }
+       img {
+                       border:medium none;
+               }
+</style>
+       
+</head>
+<body>
+       <div id="seqcontainer" style="position:absolute;top:5px;bottom:10px;left:10px;right:10px;">
+               Loading sequence editor ...
+       </div>
+       
+  </body>
+</html>
+
diff --git a/js2/mwEmbed/example_usage/Sequence_Render.html b/js2/mwEmbed/example_usage/Sequence_Render.html
new file mode 100644 (file)
index 0000000..9d9c1f2
--- /dev/null
@@ -0,0 +1,68 @@
+<!doctype html>
+<html>
+<head>
+    <title>Seeking Render Example</title>
+         <script type="text/javascript" src="../mv_embed.js?debug=true"></script>      
+  <style>
+    #render_box {
+      position:absolute;
+      width:320px;
+      height:240px;
+    }    
+
+  </style>
+  <script>  
+mwAddOnloadHook(function(){
+
+       $j('#render_player').firefoggRender({
+               'render_options':{
+                       "framerate" : 30 
+               },
+               'target_startRender':'#buttonStart',
+               'target_stopRender': '#buttonStop',
+               'target_timeStatus': '#time_status'
+               
+       },function( foggRender ){
+               $j('#loading_text').hide();
+               if( foggRender.enabled ){
+                       $j('#info_control').show();
+               }else{
+                       $j('#info_control').html( 
+                               foggRender.myFogg.getTargetHtml('target_please_install')
+                       );
+                       if(!($j.browser.mozilla && $j.browser.version >= '1.9.1')) {
+                               $j('#info_control').html(
+                                       foggRender.myFogg.getTargetHtml('target_use_latest_fox')
+                               );                                      
+                       }
+               }
+       });
+       
+});
+  </script>
+</head>
+<body>
+<playlist id="render_player" src="media/sample_smil.xml" controls="false" width="320" height="240"></playlist>
+
+<!-- <video id="render_player"
+ durationHint="27" 
+ src="http://upload.wikimedia.org/wikipedia/commons/4/41/Panthera_tigris8.ogg" 
+ style="width:320px;height:240px;" 
+ controls="false"
+ poster="http://upload.wikimedia.org/wikipedia/commons/thumb/4/41/Panthera_tigris8.ogg/mid-Panthera_tigris8.ogg.jpg">
+</video>
+-->
+
+
+<span id="loading_text" style="position:absolute; top:320px;">
+loading render system <blink>...</blink>
+</span>
+<div id="info_control" style="display:none;">
+       <button id="buttonStart">Do Render</button>
+       <button id="buttonStop">Stop</button>
+       Current Time: <input type="text" id="time_status" value="0.0" />
+       <span id="status"></span><br>
+</div>
+
+</body>
+</html>
diff --git a/js2/mwEmbed/example_usage/media/princess_archive_org/princess_iron_fan-cs.srt b/js2/mwEmbed/example_usage/media/princess_archive_org/princess_iron_fan-cs.srt
new file mode 100644 (file)
index 0000000..6cc0494
--- /dev/null
@@ -0,0 +1,1397 @@
+1
+00:00:01,080 --> 00:00:09,070
+Princezna Železný Vějíř
+
+2
+00:02:03,109 --> 00:02:09,280
+Cesta na Východ je báječný dětský příběh,
+
+3
+00:02:09,280 --> 00:02:15,280
+ale svět ho často chybně označuje jako fantasy román.
+
+4
+00:02:15,280 --> 00:02:19,240
+Tento film byl vyroben za účelem
+
+5
+00:02:19,240 --> 00:02:24,240
+tréninku dětských srdcí a myslí.
+
+6
+00:02:24,240 --> 00:02:29,280
+Příběh je pravý, nezkažený fantazií.
+
+7
+00:02:29,280 --> 00:02:32,560
+Ohnivá hora, která brání v cestě skupině Tanga Senga
+
+8
+00:02:32,560 --> 00:02:41,039
+je metafora pro obtíže v životě.
+
+9
+00:02:41,039 --> 00:02:46,439
+Abychom je překonali, musíme si uchovat víru.
+Musíme spolupracovat
+
+10
+00:02:46,439 --> 00:02:52,430
+abychom získali vějíř z palmových listů a udusili plameny.
+
+11
+00:02:52,839 --> 00:02:58,178
+Tripikata True Sutra
+
+12
+00:03:34,479 --> 00:03:37,789
+Už je přece podzim. Jakto, že je pořád takové vedro?
+
+13
+00:03:37,840 --> 00:03:42,349
+Hlupáku, neplácej nesmysly. Musíme si pospíšit a postupovat dál.
+
+14
+00:04:06,919 --> 00:04:09,349
+Wukongu, kde je to místo?
+
+15
+00:04:09,400 --> 00:04:13,669
+Musíme přejít tudy a dál na západ. Zaručeně.
+
+16
+00:04:13,719 --> 00:04:18,110
+A nemohli jsme zabloudit? 
+
+17
+00:04:18,149 --> 00:04:21,700
+Proč je tu takové horko?
+
+18
+00:04:30,029 --> 00:04:31,649
+Mistře, podívejte!
+
+19
+00:04:31,650 --> 00:04:33,779
+Není to domek? Tam nahoře...
+
+20
+00:04:33,829 --> 00:04:38,100
+Pojďme si dovnitř na chvilku odpočinout. Souhlasíte?
+
+21
+00:04:59,389 --> 00:05:02,899
+Tohle místo se nazývá Ohnivá hora.
+
+22
+00:05:02,949 --> 00:05:06,019
+Oheň dosahuje stovky mil daleko.
+
+23
+00:05:06,069 --> 00:05:08,740
+Ani jediné stéblo trávy zde nemůže vyrůst.
+
+24
+00:05:08,790 --> 00:05:11,620
+Všechny čtyři roční období je tu horko.
+
+25
+00:05:11,680 --> 00:05:19,629
+Přes horu by nešlo projít ani s měděnou hlavou ani s železnýma rukama.
+
+26
+00:05:19,670 --> 00:05:23,579
+Co je tohle jenom za místo? Mistře, nebojte.
+
+27
+00:05:23,629 --> 00:05:27,139
+My tři jsme dost silní abychom dokázali projít.
+
+28
+00:05:27,189 --> 00:05:30,699
+Mistře, půjdu a podívám se na to.
+
+29
+00:08:06,310 --> 00:08:09,579
+Wukongu, jaké to bylo?
+
+30
+00:08:09,629 --> 00:08:11,819
+Špatné, špatné, moc špatné.
+
+31
+00:08:11,879 --> 00:08:15,910
+Kdybych byl jenom trochu pomalejší, měl bych kůži na ocase spálenou.
+
+32
+00:08:42,720 --> 00:08:47,600
+Urozený hostiteli, ohně jsou zde tak velké.
+
+33
+00:08:47,600 --> 00:08:49,669
+Jak zde mohou vyrůst nějaké plodiny?
+
+34
+00:08:49,710 --> 00:08:53,980
+Tisíc mil odsud žije princezna Železný Vějíř.
+
+35
+00:08:54,039 --> 00:08:56,500
+Ona má vějíř z palmových listů.
+
+36
+00:08:56,559 --> 00:08:59,070
+Zamávej s ním jednou a oheň ustane.
+
+37
+00:08:59,120 --> 00:09:01,629
+Dvakrát a začne foukat vítr.
+
+38
+00:09:01,679 --> 00:09:03,980
+Třikrát a spustí se déšť.
+
+39
+00:09:04,039 --> 00:09:07,509
+V nadcházejícím období pak pěstujeme a sklízíme.
+
+40
+00:09:07,559 --> 00:09:11,340
+Nicméně... požádat, aby princezna přišla
+
+41
+00:09:11,399 --> 00:09:14,870
+není tak úplně jednoduché.
+
+42
+00:09:14,909 --> 00:09:16,820
+Kde ona žije?
+
+43
+00:09:16,879 --> 00:09:20,190
+Žije v jeskyni Palmových Listů v hoře Smaragdových Mračen.
+
+44
+00:09:20,240 --> 00:09:23,669
+Žije tam sama?
+
+45
+00:09:23,720 --> 00:09:25,750
+Ona nemá manžela?
+
+46
+00:09:25,799 --> 00:09:29,580
+Její manžel je Král, Býčí Démon.
+
+47
+00:09:29,639 --> 00:09:32,200
+Cože? Její manžel je Starý Býk?
+
+48
+00:09:32,240 --> 00:09:36,789
+Hlupáku, ty ho znáš? Pojď si se mnou vypůjčit ten vějíř!
+
+49
+00:09:36,840 --> 00:09:41,750
+Vlastně... Starý Býk tam nežije.
+
+50
+00:09:41,799 --> 00:09:46,350
+Vyhledávat jeho ženu, když on není doma
+
+51
+00:09:46,399 --> 00:09:51,519
+není moc ... vhodné.
+
+52
+00:09:51,559 --> 00:09:58,309
+Ty... ty... Vy dva, jděte už.
+
+53
+00:09:58,360 --> 00:10:04,290
+Já... Já zůstanu a postarám se o mistra.
+
+54
+00:10:04,440 --> 00:10:11,269
+Sha Wujingu, jdi se svými dvěma učedníky.
+
+55
+00:10:38,571 --> 00:10:44,978
+jeskyně Palmových Listů
+
+56
+00:10:47,200 --> 00:10:51,549
+Hlupáku. První jdu vždy já.
+
+57
+00:10:51,600 --> 00:10:54,350
+Tentokrát jsi na řadě ty.
+
+58
+00:10:58,519 --> 00:11:04,909
+Juniore. Vždycky jdu první já, tak teď jsi na řadě ty.
+
+59
+00:11:04,960 --> 00:11:06,830
+Seniore...
+
+60
+00:11:06,879 --> 00:11:10,990
+Žádám tě, abys pro mistra udělal malou službu. Nemůžeš to udělat?
+
+61
+00:11:11,039 --> 00:11:14,309
+Dělej!
+
+62
+00:11:39,639 --> 00:11:43,039
+Prostý mnichu, odkud jsi přišel?
+
+63
+00:11:43,039 --> 00:11:49,870
+Velký Mudrc... Tang Seng... si žádá vaši princeznu...
+
+64
+00:11:49,919 --> 00:11:52,480
+Nesmysl!
+
+65
+00:12:47,549 --> 00:12:52,059
+Seniore... proč raději nejde vy?
+
+66
+00:12:52,120 --> 00:12:56,950
+Hlupáku, jdi ty!
+
+67
+00:12:57,000 --> 00:13:00,700
+Seiore, proč vy ne?
+
+68
+00:13:04,029 --> 00:13:07,460
+Líný hlupáku!
+
+69
+00:13:54,279 --> 00:13:57,899
+Velká Matko Hromů! Nezabíjejte mě, nechte mě jít!
+
+70
+00:13:57,960 --> 00:13:59,950
+Jdi a řekni tvé princezně, 
+
+71
+00:14:00,000 --> 00:14:03,279
+že Sun Wukong si přišel půjčit její vějíř.
+
+72
+00:14:03,279 --> 00:14:08,399
+Ano, ano! Nech mě zmizet. Já hned půjdu.
+
+73
+00:14:29,559 --> 00:14:37,059
+Babičko, venku je Sun Wukong a ptá se na půjčení vějíře.
+
+74
+00:14:41,519 --> 00:14:44,149
+Rychle, přines mi můj meč.
+
+75
+00:15:01,639 --> 00:15:04,149
+Sune Wukongu, ty jsi zranil mého syna!
+
+76
+00:15:04,200 --> 00:15:08,549
+Ty se odvažuješ přijít si sem pro svou smrt?
+
+77
+00:15:08,600 --> 00:15:12,039
+Nikdy jsem tě nepotkal. Jak bych mohl ublížit tvému synovi?
+
+78
+00:15:12,039 --> 00:15:15,789
+Život mého syna Červeného Dítěte byl zničen. Není to to co děláš? 
+
+79
+00:15:15,840 --> 00:15:20,389
+Tvůj syn je nyní s Bohyní Milosrdenství. Jak můžeš říci, že jsem ho zranil?
+
+80
+00:15:20,440 --> 00:15:23,750
+Dost řečí! Pojď sem ať tě můžu seknout svým mečem.
+
+81
+00:15:23,799 --> 00:15:26,149
+Pokud to podstoupíš tak ti půjčím svůj vějíř.
+
+82
+00:15:26,200 --> 00:15:28,549
+Opravdu?
+
+83
+00:15:56,799 --> 00:16:00,629
+Zastav! Rychle, dej mi vějíř.
+
+84
+00:17:53,630 --> 00:18:00,099
+Velký mudrci, nešli jste na západ? Proč jste se vrátili?
+
+85
+00:18:11,150 --> 00:18:17,140
+Princezna Železný Vějíř mě sem odfoukla jedním mávnutím svého vějíře.
+
+86
+00:18:17,190 --> 00:18:23,859
+To je skutečně úžasné, velký mudrci. Něco pro Vás mám.
+
+87
+00:18:28,509 --> 00:18:33,450
+Tohle je větrná perla. Když ji použijete
+
+88
+00:18:33,509 --> 00:18:36,140
+vaše srdce se zastaví jako kámen.
+
+89
+00:18:36,190 --> 00:18:39,180
+Princezna Železný Vějíř nebude schopná s Vámi vůbec pohnout.
+
+90
+00:18:39,230 --> 00:18:42,849
+Velký mudrci, podívejte se.
+
+91
+00:19:00,430 --> 00:19:02,539
+Děkuji.
+
+92
+00:19:06,069 --> 00:19:12,299
+Seniore... kde...
+
+93
+00:19:12,349 --> 00:19:18,690
+Kam ho to odfouklo?
+
+94
+00:19:18,750 --> 00:19:26,099
+Kdo by se o něj staral. Ať se opičák postará sám o sebe. Pojďme.
+
+95
+00:19:35,190 --> 00:19:37,259
+Seniore... seniore...
+
+96
+00:19:37,309 --> 00:19:43,470
+Vy... vy...
+
+97
+00:19:43,470 --> 00:19:50,220
+Kam vás ta stará paní odfoukla?
+
+98
+00:19:50,269 --> 00:19:57,180
+Hlupáku, teď je rozhodně řada na tobě abys šel.
+
+99
+00:19:57,230 --> 00:20:00,930
+Já nejdu. Jediné mávnutí vějíře
+
+100
+00:20:00,990 --> 00:20:03,450
+by mě mohlo odfouknout do nějaké daleké země.
+
+101
+00:20:03,509 --> 00:20:09,710
+Možná by bylo lepší, kdyby jste šel znovu.
+
+102
+00:20:09,710 --> 00:20:12,220
+Já nepůjdu.
+
+103
+00:20:17,789 --> 00:20:22,779
+Příště už tě nenechám odpálit.
+
+104
+00:20:56,150 --> 00:21:00,140
+Tentokrát se nepohnu a nezáleží na tom jak moc máchneš.
+
+105
+00:21:00,190 --> 00:21:05,210
+Buď si jistá mým slovem, slovem muže.
+
+106
+00:21:33,670 --> 00:21:38,579
+Seniore, jakto že její vějíř vás neodfouknul?
+
+107
+00:21:46,829 --> 00:21:50,099
+Dostaňme se dovnitř.
+
+108
+00:23:59,630 --> 00:24:04,180
+Rychle, dones vějíř Sunu Wukongovi.
+
+109
+00:24:14,869 --> 00:24:16,900
+Sune Wukongu, kde jsi?
+
+110
+00:24:16,950 --> 00:24:19,980
+Jsem ve tvém žaludku!
+
+111
+00:24:45,750 --> 00:24:48,539
+Sune Wukongu, ušetři mě!
+
+112
+00:24:48,589 --> 00:24:51,180
+Jenom tehdy, když mi dáš ten vějíř.
+
+113
+00:24:51,230 --> 00:24:56,539
+Slibuji. Dám ti to. Prosím, jdi ven!
+
+114
+00:25:00,230 --> 00:25:02,819
+Honem a přines vějíř.
+
+115
+00:25:07,430 --> 00:25:09,220
+Přinesli jsme vějíř.
+
+116
+00:25:09,279 --> 00:25:12,069
+Porč jsi ještě nevylezl?
+
+117
+00:25:12,109 --> 00:25:16,619
+Otevři ústa a já vylezu.
+
+118
+00:25:25,349 --> 00:25:29,420
+Sune Wukongu, proč jsi dosud nevylezl?
+
+119
+00:25:50,349 --> 00:25:55,579
+Já jsem zde. Půjč mi na chvíli ten vějíř a já ti ho vrátím.
+
+120
+00:26:32,549 --> 00:26:36,579
+Mistr už čekal dost dlouho. Pojďme už.
+
+121
+00:27:01,869 --> 00:27:04,900
+Posvátná kniha... Co je to posvátná kniha?
+
+122
+00:27:04,950 --> 00:27:10,029
+Posvátná kniha je zásadní pro spojení mezi nebem a zemí.
+
+123
+00:27:10,029 --> 00:27:14,180
+To je princip lidí.
+
+124
+00:27:14,230 --> 00:27:18,700
+Jenom ten, kdo se těch principů drží,
+
+125
+00:27:18,750 --> 00:27:25,339
+se může zbavit bolesti a žije dobrý život.
+
+126
+00:27:25,390 --> 00:27:29,940
+Žije správný a čestný život.
+
+127
+00:27:34,680 --> 00:27:36,349
+Naproti tomu...
+
+128
+00:27:36,390 --> 00:27:40,089
+ten, kdo tyto zásady nezná,
+
+129
+00:27:40,150 --> 00:27:46,380
+bude žít život plný utrpení.
+
+130
+00:27:46,430 --> 00:27:52,609
+A dokonce ani jeho syn a vnuk nedosáhnou štěstí.
+
+131
+00:27:52,670 --> 00:27:55,660
+Proč já chci dosáhnout posvátné knihy?
+
+132
+00:27:55,710 --> 00:28:01,299
+Protože lidé jsou nyní chyceni v utrpení.
+
+133
+00:28:01,349 --> 00:28:04,180
+Abychom dosáhni tohoto cíle, jdeme...
+
+134
+00:28:04,230 --> 00:28:12,500
+navštívit císaře Tangu a povíme mu o této komplikované záležitosti.
+
+135
+00:28:15,670 --> 00:28:17,819
+Dostali jste vějíř z palmových listů?
+
+136
+00:28:17,869 --> 00:28:19,400
+Máme ho.
+
+137
+00:28:19,401 --> 00:28:20,779
+To je ono?
+
+138
+00:28:22,829 --> 00:28:27,980
+Vznešený hostiteli, teď, když máme vějíř,
+
+139
+00:28:28,029 --> 00:28:32,140
+můžeme již jít.
+
+140
+00:28:32,190 --> 00:28:34,039
+Počkejte.
+
+141
+00:28:34,039 --> 00:28:39,789
+Všichni. Rád bych požádal Sage Senga, aby jste na pár dní zůstali.
+
+142
+00:28:39,829 --> 00:28:41,339
+Souhlasíte?
+
+143
+00:28:41,390 --> 00:28:43,460
+Ujednáno!
+
+144
+00:28:43,509 --> 00:28:45,890
+Děkuji Vám za Vaši laskavost.
+
+145
+00:28:45,950 --> 00:28:51,779
+Ale odejdeme dříve abychom dokončili náš úkol.
+
+146
+00:28:51,829 --> 00:28:56,180
+Dobrá tedy. Čestný učeň půjde nejprve k Ohnivé hoře. 
+
+147
+00:28:56,230 --> 00:29:02,140
+Až uhasíš plameny, následuj Sage Senga.
+
+148
+00:29:02,190 --> 00:29:05,460
+V pořádku. Pokračujte.
+
+149
+00:30:24,470 --> 00:30:30,029
+Princezna Železný Vějíř je opravdu opovrženíhodná. Dala nám falešný vějíř!
+
+150
+00:30:30,029 --> 00:30:32,779
+Já ji zabiju! To je jisté.
+
+151
+00:30:32,829 --> 00:30:36,299
+Ne, zabíjení je špatná věc.
+
+152
+00:30:36,349 --> 00:30:39,579
+Nedovolím ti nikoho zabít.
+
+153
+00:30:39,630 --> 00:30:42,980
+Vymysleme něco jiného.
+
+154
+00:30:52,150 --> 00:30:56,220
+Seniore, jakto že Vás oklamala?
+
+155
+00:30:56,269 --> 00:30:58,539
+Po vší té námaze
+
+156
+00:30:58,589 --> 00:31:02,099
+jediné co jsme získali je falešný vějíř.
+
+157
+00:31:02,150 --> 00:31:06,500
+Směšné, směšné.
+
+158
+00:31:08,910 --> 00:31:10,420
+Pak tedy jděte!
+
+159
+00:31:10,470 --> 00:31:14,380
+Ano, půjdu, jdu, odcházím!
+
+160
+00:31:14,430 --> 00:31:16,908
+Jdu najít Krále Býčího Démona.
+
+161
+00:31:16,909 --> 00:31:19,940
+To je dobré řešení.
+
+162
+00:31:21,390 --> 00:31:24,439
+Parťáku, co si o tom myslíš?
+
+163
+00:31:24,440 --> 00:31:27,380
+Uvidíme jak to půjde.
+
+164
+00:33:07,190 --> 00:33:11,150
+Co myslíš, jsem dnes půvabná?
+
+165
+00:33:11,150 --> 00:33:13,779
+Nádherná, má drahá.
+
+166
+00:33:13,829 --> 00:33:17,059
+Doprovoď mě na procházku mimo jeskyni, ano?
+
+167
+00:33:17,109 --> 00:33:21,539
+Má drahá, proč nejdeš sama?
+
+168
+00:33:21,589 --> 00:33:24,819
+To je jasné proč. Jsem obyčejná venkovská holka.
+
+169
+00:33:24,869 --> 00:33:28,019
+Když půjdu ven tak to může způsobit, že ztratíš tvář.
+
+170
+00:33:28,069 --> 00:33:32,029
+Miláčku, proč to říkáš?
+
+171
+00:33:32,029 --> 00:33:37,500
+Pokračuj a já přijdu ven za chvilku, ano?
+
+172
+00:33:39,852 --> 00:33:44,557
+Jeskyně Smaragdových Mračen
+
+173
+00:35:28,030 --> 00:35:35,659
+Bohyně, ty jsi skutečný anděl co slétl dolů z nebes.
+
+174
+00:35:35,710 --> 00:35:37,900
+Kdo... kdo jsi?
+
+175
+00:35:37,949 --> 00:35:41,460
+Přišel jsem z jeskyně Palmových Listů abych našel krále Býčího Démona.
+
+176
+00:35:41,519 --> 00:35:43,980
+Jdi ode mě!
+
+177
+00:35:49,550 --> 00:35:52,940
+Bohyně, zpomal!
+
+178
+00:36:38,768 --> 00:36:40,133
+Jeskyně Smaragdových Mračen
+
+179
+00:36:44,230 --> 00:36:49,219
+Miláčku, kdo tě vystrašil?
+
+180
+00:36:49,269 --> 00:36:50,820
+Ty!
+
+181
+00:36:50,869 --> 00:36:54,340
+Jak bych tě mohl vystrašit?
+
+182
+00:36:56,909 --> 00:36:59,260
+Proč nejdeš zpátky do jeskyně Palmových Listů?
+
+183
+00:36:59,320 --> 00:37:01,699
+To by ti ušetřilo rozpaky.
+
+184
+00:37:01,750 --> 00:37:07,659
+Oni často posílají lidi aby tě našli a vystrašili mě.
+
+185
+00:37:07,710 --> 00:37:11,059
+Tady byl někdo kdo mě hledal?
+
+186
+00:37:11,110 --> 00:37:15,059
+Venku je prasečí mnich, který tě hledá.
+
+187
+00:37:15,119 --> 00:37:18,510
+On mě k smrti vyděsil.
+
+188
+00:37:18,550 --> 00:37:22,739
+Jak je tohle možné? Počkej chvíli. Půjdu se podívat ven.
+
+189
+00:37:50,670 --> 00:37:53,780
+Býku, starý příteli.
+
+190
+00:37:53,829 --> 00:37:58,139
+Tady vevnitř je nějaká moc krásná mladá dáma.
+
+191
+00:37:58,199 --> 00:38:03,889
+Hej, to je moje paní. Neopovažuj se ji obtěžovat.
+
+192
+00:38:03,930 --> 00:38:08,550
+Oh, to jsem nevěděl, prosím promiň mi!
+
+193
+00:38:08,550 --> 00:38:11,940
+Ty's to nevěděl, tak tě nemůžu obviňovat. A teď už jdi.
+
+194
+00:38:11,989 --> 00:38:16,099
+Ne, ne. Stále mám něco s čím potřebuji tvou pomoc.
+
+195
+00:38:18,469 --> 00:38:24,710
+Byli jsme na cestě získat posvátnou knihu když v tom jsme dorazili k Ohnivé hoře.
+
+196
+00:38:24,710 --> 00:38:27,300
+Prosím, požádej svou choť,
+
+197
+00:38:27,349 --> 00:38:30,820
+aby nám na chvíli půjčila vějíř z palmových listů.
+
+198
+00:38:30,880 --> 00:38:33,510
+V žádném případě! Tang Seng a Sun Wukong
+
+199
+00:38:33,510 --> 00:38:35,179
+jsou nepřátelé mého syna.
+
+200
+00:38:35,230 --> 00:38:38,739
+Moc rád bych na nich vykonal svou pomstu.
+
+201
+00:38:38,789 --> 00:38:44,969
+Tvůj syn je nyní s Bohyní Milosrdenství. Prosím, nebojuj.
+
+202
+00:38:45,030 --> 00:38:48,940
+Dobrá. Jsme staří přátelé tak s tebou nebudu bojovat.
+
+203
+00:38:49,000 --> 00:38:51,710
+Nyní jdi pryč!
+
+204
+00:39:38,389 --> 00:39:44,179
+Miláčku, ten prasečí mnich je můj přítel.
+
+205
+00:39:44,230 --> 00:39:46,500
+On vůbec nebyl poslán z jeskyně Palmových Listů.
+
+206
+00:39:46,550 --> 00:39:47,739
+Nevěřím ti.
+
+207
+00:39:47,789 --> 00:39:50,940
+Já ti nelžu!
+
+208
+00:39:50,989 --> 00:39:54,019
+Kde je ten mnich teď?
+
+209
+00:39:54,110 --> 00:39:57,780
+Už jsem ho zastrašil.
+
+210
+00:43:34,814 --> 00:43:40,987
+Jeskyně Palmových Listů
+
+211
+00:43:58,630 --> 00:44:01,340
+Král se vrátil.
+
+212
+00:44:01,389 --> 00:44:02,369
+Kde je babička?
+
+213
+00:44:02,429 --> 00:44:04,780
+Je uvnitř.
+
+214
+00:44:42,989 --> 00:44:48,219
+Jaká čest, že nás dnes navštívil král.
+
+215
+00:44:48,269 --> 00:44:52,260
+Slyšel jsem, že sem jsou Sun Wukong a Tang Seng.
+
+216
+00:44:52,320 --> 00:44:56,909
+Obávám se, že chtějí použít vějíř z palmových listů a přejít Ohnivou horu.
+
+217
+00:44:56,949 --> 00:45:00,860
+Ten opičák je jeden z těch co zranil našeho syna.
+
+218
+00:45:00,909 --> 00:45:08,489
+Dostanu ho dříve či později. Dosáhnu naší msty.
+
+219
+00:45:08,550 --> 00:45:12,699
+Miláčku, proč pláčeš?
+
+220
+00:45:12,750 --> 00:45:15,699
+Ten opičák už tady byl.
+
+221
+00:45:15,750 --> 00:45:18,860
+Odmítla jsem mu vějíř dát.
+
+222
+00:45:18,909 --> 00:45:22,260
+Nevím jak, ale dostal se mi do žaludku.
+
+223
+00:45:22,309 --> 00:45:25,500
+Bolelo to tak strašně, že jsem myslela že umřu.
+
+224
+00:45:25,550 --> 00:45:30,589
+Nakonec jsem neměla na výběr a dala jsem mu vějíř.
+
+225
+00:45:30,789 --> 00:45:35,260
+To je strašné. Jak's mu mohla dát vějíř?
+
+226
+00:45:38,320 --> 00:45:40,469
+Dala jsem mu falešný.
+
+227
+00:45:40,720 --> 00:45:43,019
+Falešný?
+
+228
+00:46:14,190 --> 00:46:19,860
+Večírek na oslavu návratu krále
+
+229
+00:46:19,909 --> 00:46:25,619
+Prosím, napijte se dobrého vína. 
+
+230
+00:46:25,670 --> 00:46:34,179
+Kuřecí je voňavé, kachna je skvostná a vepřové je tučné. 
+
+231
+00:46:34,239 --> 00:46:45,670
+Zkusím si zazpívat. Zkusím si dobře zatančit.
+
+232
+00:46:45,710 --> 00:46:54,500
+Musíš také ochutnat náš nejlepší nápoj.
+
+233
+00:47:03,590 --> 00:47:16,389
+Můj králi. Ty's pustil k vodě tu starou.
+
+234
+00:47:16,429 --> 00:47:22,610
+Ty miluješ jinou ženu.
+
+235
+00:47:22,670 --> 00:47:34,659
+Nespočet slz jsem pro tebe naplakala.
+
+236
+00:47:46,710 --> 00:47:55,699
+Když světlo zhasne a spustí se závěs,
+
+237
+00:47:55,750 --> 00:48:00,869
+budeš spát sám.
+
+238
+00:48:00,869 --> 00:48:05,510
+Ty také okusíš samotu.
+
+239
+00:48:05,510 --> 00:48:13,420
+Omluv mě, že ti nedělám společnost.
+
+240
+00:48:18,550 --> 00:48:24,619
+Dokonce i když jsme ve stejné posteli,
+
+241
+00:48:24,670 --> 00:48:34,340
+budeme spát pod oddělenými přikrývkami.
+
+242
+00:48:38,389 --> 00:48:42,380
+Králi. Jsem opilá.
+
+243
+00:48:55,070 --> 00:48:58,139
+Miláčku, kam jsi dala skutečný vějíř?
+
+244
+00:48:58,190 --> 00:49:05,460
+Ten opičák je velmi podvodný a prase je dokonce mnohem nadanější.
+
+245
+00:49:05,510 --> 00:49:09,780
+Když si nebudeš dávat pozor tak tě mohou obelstít.
+
+246
+00:49:18,360 --> 00:49:21,980
+Náš poklad je přímo tady.
+
+247
+00:49:31,429 --> 00:49:39,309
+Králi, na co myslíš? Proč si jej nevezmeš?
+
+248
+00:49:39,309 --> 00:49:40,847
+Můj poklade.
+
+249
+00:49:41,514 --> 00:49:44,150
+Jeskyně Smaragdových Mračen
+
+250
+00:49:44,250 --> 00:49:49,019
+Miláčku, dej si další pohár. Pij.
+
+251
+00:49:53,909 --> 00:49:59,510
+Zlatý drak mě požádal abych s ním dnes večer pil.
+
+252
+00:49:59,510 --> 00:50:01,420
+Potom bys měl jít.
+
+253
+00:50:01,469 --> 00:50:02,860
+Dobrá.
+
+254
+00:50:02,909 --> 00:50:06,610
+Měl bys pro dědečka připravit zlatooké zvíře.
+
+255
+00:50:06,670 --> 00:50:08,260
+Připravím.
+
+256
+00:50:08,320 --> 00:50:12,590
+Měl bys dnes večer pít trochu méně.
+
+257
+00:50:12,630 --> 00:50:15,739
+Jinak tě nebudu moci probudit.
+
+258
+00:50:15,800 --> 00:50:19,110
+To je strašné. Dědečkova zlatooká nestvůra zmizela!
+
+259
+00:50:19,150 --> 00:50:20,900
+Jste všichni hluší a slepí?
+
+260
+00:50:20,949 --> 00:50:24,030
+Jak mohla zmizet?
+
+261
+00:50:24,030 --> 00:50:27,900
+Miláčku, nestrachuj se o ně.
+
+262
+00:50:27,960 --> 00:50:31,710
+Bojím se, že Zhu Bajie ho mohl ukrást.
+
+263
+00:50:31,750 --> 00:50:35,260
+Možná bych měl prohledat jeskyni Palmových Listů.
+
+264
+00:50:35,320 --> 00:50:39,309
+Cože? Ty's to plánoval celou dobu.
+
+265
+00:50:42,280 --> 00:50:48,150
+Stále to chceš prohledat u té nestoudné ženy?
+
+266
+00:50:48,190 --> 00:50:50,699
+Prosím miláčku, neplakej.
+
+267
+00:50:50,750 --> 00:50:54,059
+Vrátím se brzy.
+
+268
+00:50:57,624 --> 00:51:01,194
+Jeskyně Palmových Listů
+
+269
+00:51:02,670 --> 00:51:07,300
+Pojď sem, napij se trochu!
+
+270
+00:51:10,349 --> 00:51:12,460
+Teď si můžu odpočinout.
+
+271
+00:51:12,510 --> 00:51:16,699
+Nemusíme se obávat, že jsme byli oloupeni o náš poklad.
+
+272
+00:51:16,750 --> 00:51:21,300
+Dokonce i když ho ukradli, tak nebudou vědět, že mají zatáhnout za hedvábnou nit.
+
+273
+00:51:21,360 --> 00:51:26,269
+Mají perlu, ale nebudou ji moci použít.
+
+274
+00:51:26,309 --> 00:51:31,780
+Zatáhnutí za nit ji promění na vějíř, že?
+
+275
+00:51:35,119 --> 00:51:38,070
+Králi, jsi opilý.
+
+276
+00:51:38,110 --> 00:51:44,019
+Zapomněl jsi na svůj vlastní poklad a ptáš se mě...
+
+277
+00:51:49,989 --> 00:51:53,690
+Madam, podívej se kdo já jsem.
+
+278
+00:52:00,320 --> 00:52:03,750
+Kdo jsi?
+
+279
+00:52:03,789 --> 00:52:09,889
+Já jsem Zhu Bajie, druhý pomocník Tanga Senga.
+
+280
+00:52:09,949 --> 00:52:14,780
+Omlouvám se, že jsem Vás rušil a díky!
+
+281
+00:52:19,079 --> 00:52:21,710
+Na shledanou!
+
+282
+00:53:06,829 --> 00:53:10,699
+Býkova žena je příliš koketní.
+
+283
+00:53:10,760 --> 00:53:14,710
+Všichni její podřízení jsou krásní.
+
+284
+00:53:14,750 --> 00:53:24,809
+Starý Čuník to skoro nedokázal.
+
+285
+00:53:24,869 --> 00:53:28,860
+Použil jsem chytré triky a taktiky.
+
+286
+00:53:28,909 --> 00:53:32,820
+Uloupil jsem jejich poklad.
+
+287
+00:53:32,880 --> 00:53:36,789
+To je ohromný výkon.
+
+288
+00:53:36,829 --> 00:53:38,300
+Písečný by měl klečet.
+
+289
+00:53:38,349 --> 00:53:40,730
+Opice by se měla učit ode mě.
+
+290
+00:53:40,789 --> 00:53:45,219
+Dokonce i Mistr bude v úžasu.
+
+291
+00:53:45,280 --> 00:53:49,190
+Starý Čuník je skutečně mistrovský.
+
+292
+00:53:49,230 --> 00:53:54,349
+Starý Čuník je skutečně mistrovský.
+
+293
+00:54:36,719 --> 00:54:40,469
+Hlupáku, jak to jde?
+
+294
+00:54:40,510 --> 00:54:42,809
+Nejen že jsem získal vějíř,
+
+295
+00:54:42,880 --> 00:54:48,789
+ale princezna Železný Vějíř byla půl dne mou ženou.
+
+296
+00:54:48,829 --> 00:54:51,699
+Udělal jsi to dobře.
+
+297
+00:54:58,150 --> 00:55:01,579
+Hej, ukaž mi ten vějíř.
+
+298
+00:55:16,030 --> 00:55:20,219
+Proč jsi ho smrštil?
+
+299
+00:55:40,550 --> 00:55:45,340
+Starý Čuníku, ty mě nepoznáváš, že?
+
+300
+00:55:45,389 --> 00:55:49,170
+Nedělej si ze mě legraci.
+
+301
+00:55:49,230 --> 00:55:52,139
+A kdo si z tebe dělá legraci?
+
+302
+00:56:42,869 --> 00:56:45,380
+Hlupáku, jak se to stalo?
+
+303
+00:56:45,429 --> 00:56:47,099
+Všechno bylo k ničemu.
+
+304
+00:56:47,150 --> 00:56:49,980
+Wunengu, vypůjčil jsi ten vějíř?
+
+305
+00:56:50,030 --> 00:56:53,340
+Našel jsem krále Býčího démona, ale on odmítl.
+
+306
+00:56:53,400 --> 00:56:59,190
+Potom jsem na sebe vzal jeho podobu.
+
+307
+00:56:59,230 --> 00:57:03,539
+Oklamal jsem princeznu Železný Vějíř aby mi dala vějíř.
+
+308
+00:57:03,590 --> 00:57:10,590
+Ale potom si Starý Býk vzal tvou podobu a vylákal ho na mě zpátky.
+
+309
+00:57:10,590 --> 00:57:12,739
+Schopnosti Starého Býka jsou vynikající.
+
+310
+00:57:12,800 --> 00:57:16,150
+Potom mě ještě zbil.
+
+311
+00:57:16,190 --> 00:57:21,380
+Jak jsi mohl získat vějíř a přitom zůstat tak hloupý?
+
+312
+00:57:21,429 --> 00:57:25,659
+Všechno se neotáčí kolem tebe!
+
+313
+00:57:30,750 --> 00:57:34,369
+Nebojuj. Musíme rychle vymyslet nějaké řešení.
+
+314
+00:57:34,429 --> 00:57:40,260
+Ve kterém směru není oheň?
+
+315
+00:57:40,320 --> 00:57:47,070
+Východ, jih, západ, sever. Oheň není jenom na západě.
+
+316
+00:57:47,119 --> 00:57:50,739
+Tak to nemáme jinou možnost než se vrátit.
+
+317
+00:57:50,789 --> 00:57:52,940
+Tato stezka je zablokovaná. Jaké máme jiné možnosti?
+
+318
+00:57:52,989 --> 00:57:55,219
+Bajie, nemluv tak.
+
+319
+00:57:55,269 --> 00:57:59,139
+Na naší cestě budou vždy překážky.
+
+320
+00:57:59,190 --> 00:58:04,539
+Abychom dokončili náš posvátný úkol, musíme být silní v naší víře.
+
+321
+00:58:04,590 --> 00:58:09,219
+Nemůžeme změnit náš plán jenom kvůli tomu, že jsme narazili na pár překážek.
+
+322
+00:58:09,280 --> 00:58:14,590
+Důvod proč jsme byli poraženi je ten, že jsme nespolupracovali.
+
+323
+00:58:14,630 --> 00:58:17,139
+Pokud tři z nás budou jako jeden,
+
+324
+00:58:17,190 --> 00:58:20,500
+dáme síly dohromady a zdoláme krále Býčího Démona.
+
+325
+00:58:20,550 --> 00:58:22,849
+A vítězství bude naše.
+
+326
+00:58:22,909 --> 00:58:26,030
+Slyšeli jsme Mistrův rozkaz 
+
+327
+00:58:26,030 --> 00:58:30,139
+a budeme s králem Býčím Démonem bojovat až do konce.
+
+328
+00:58:30,190 --> 00:58:34,260
+až... až do konce.
+
+329
+00:58:34,320 --> 00:58:37,710
+To je skvělé!
+
+330
+00:58:37,750 --> 00:58:40,980
+Všichni jsme dokázali překonat nesnáze.
+
+331
+00:58:41,039 --> 00:58:43,869
+Doufám, že každý vynaloží veškeré úsilí
+
+332
+00:58:43,869 --> 00:58:49,579
+společně s mými učedníky k porážce krále Býčího Démona a uhasíme plameny Ohnivé hory.
+
+333
+00:58:49,630 --> 00:58:52,820
+Jinak toto neštěstí nikdy neskončí.
+
+334
+00:58:53,869 --> 00:58:57,489
+Slyšeli jsme Mistrovo nařízení na dosažení štěstí pro všechny.
+
+335
+00:58:57,550 --> 00:58:58,860
+Společně to dokážeme!
+
+336
+00:58:58,909 --> 00:59:00,519
+Hurá!
+
+337
+01:08:23,229 --> 01:08:25,609
+Babičko, to je strašné!
+
+338
+01:08:25,670 --> 01:08:30,789
+Dědeček je chycen. Pojď se rychle podívat.
+
+339
+01:08:54,470 --> 01:08:56,699
+Ještě není po boji. Ještě ne.
+
+340
+01:08:56,760 --> 01:08:58,710
+Pozor. Opatrně.
+
+341
+01:08:59,760 --> 01:09:05,789
+Nestvůro, jediné co musíš udělat je dát nám vějíř a ušetříme tvůj život.
+
+342
+01:09:05,840 --> 01:09:12,750
+Starý Býku, kde je vějíř? Odevzdej ho!
+
+343
+01:09:12,789 --> 01:09:19,340
+Moje ... moje choť... jej má.
+
+344
+01:09:25,239 --> 01:09:27,989
+Drahoušku, drahoušku!
+
+345
+01:09:28,029 --> 01:09:32,260
+Zachraň mě, rychle!
+
+346
+01:09:32,319 --> 01:09:35,109
+Dej jim vějíř.
+
+347
+01:09:35,149 --> 01:09:39,619
+Králi! Ano, ano.
+
+348
+01:09:43,399 --> 01:09:47,229
+Wukongu, jdi na to ještě jednou!
+
+349
+01:12:30,850 --> 01:12:46,599
+Konec
+
diff --git a/js2/mwEmbed/example_usage/media/princess_archive_org/princess_iron_fan-ru.srt b/js2/mwEmbed/example_usage/media/princess_archive_org/princess_iron_fan-ru.srt
new file mode 100644 (file)
index 0000000..9a9f8ab
--- /dev/null
@@ -0,0 +1,1414 @@
+1
+00:00:01,080 --> 00:00:09,070
+Принцесса Железный Веер
+
+2
+00:02:03,109 --> 00:02:09,280
+Путешествие на Запад это замечательная детская история
+
+3
+00:02:09,280 --> 00:02:15,280
+но мир часто неправильно воспринимает ее, как фантастическую.
+
+4
+00:02:15,280 --> 00:02:19,240
+Этот фильм был сделан для того, чтобы
+
+5
+00:02:19,240 --> 00:02:24,240
+воспитать сердца и ума детей.
+
+6
+00:02:24,240 --> 00:02:29,280
+История чиста, не испорчена фантазией.
+
+7
+00:02:29,280 --> 00:02:32,560
+Огненная Гора, преграждающая дорогу Танскому монаху и его ученикам -  
+
+8
+00:02:32,560 --> 00:02:41,039
+это аллегория жизненных трудностей.
+
+9
+00:02:41,039 --> 00:02:46,439
+Чтобы преодолеть их, нужно хранить веру. 
+Каждый должен сделать все, 
+
+10
+00:02:46,439 --> 00:02:52,430
+чтобы получить веер пальмового листа и потушить огонь.
+
+11
+00:02:52,839 --> 00:02:58,178
+Tрипитака Истинная Сутра
+
+12
+00:03:34,479 --> 00:03:37,789
+Уже осень, как еще может быть так жарко?
+
+13
+00:03:37,840 --> 00:03:42,349
+Дурень, не болтай ерунды! Нам надо поспешить и найти верную дорогу.
+
+14
+00:04:06,919 --> 00:04:09,349
+Укун, где мы?
+
+15
+00:04:09,400 --> 00:04:13,669
+Наш путь на Запад лежит через эту местность, это уж точно.
+
+16
+00:04:13,719 --> 00:04:18,110
+Может, мы идем не в ту сторону ?
+
+17
+00:04:18,149 --> 00:04:21,700
+Почему здесь так жарко?
+
+18
+00:04:30,029 --> 00:04:31,649
+Наставник, смотрите!
+
+19
+00:04:31,650 --> 00:04:33,779
+Разве там не дом, впереди?
+
+20
+00:04:33,829 --> 00:04:38,100
+Давайте, зайдем и отдохнем немного, ладно?
+
+21
+00:04:59,389 --> 00:05:02,899
+Это место носит название Огненная Гора.
+
+22
+00:05:02,949 --> 00:05:06,019
+Огонь распространяется на сотни миль.
+
+23
+00:05:06,069 --> 00:05:08,740
+Ни одна травинка не может расти здесь.
+
+24
+00:05:08,790 --> 00:05:11,620
+Целый год жарко.
+
+25
+00:05:11,680 --> 00:05:19,629
+Вы не сможете пройти через эту гору даже если у вас голова из меди, а тело из железа.
+
+26
+00:05:19,670 --> 00:05:23,579
+Что это за место? Наставник, не волнуйся!
+
+27
+00:05:23,629 --> 00:05:27,139
+Трое из нас достаточно сильны, чтобы прокладывать дорогу!
+
+28
+00:05:27,189 --> 00:05:30,699
+Наставник, я пойду взглянуть!
+
+29
+00:08:06,310 --> 00:08:09,579
+Укун, ну что?
+
+30
+00:08:09,629 --> 00:08:11,819
+Плохо, плохо, очень плохо.
+
+31
+00:08:11,879 --> 00:08:15,910
+Если бы я немного замешкался, мой хвост бы сгорел. 
+
+32
+00:08:42,720 --> 00:08:47,600
+Почтеный хозяин, огонь в ваших краях так велик. 
+
+33
+00:08:47,600 --> 00:08:49,669
+Как вы можете что-то выращивать? 
+
+34
+00:08:49,710 --> 00:08:53,980
+Тысяча миль отсюда живет принцесса Железный Веер. 
+
+35
+00:08:54,039 --> 00:08:56,500
+У нее есть веер из листа пальмы.
+
+36
+00:08:56,559 --> 00:08:59,070
+Махнешь им раз, и огонь прекращается. 
+
+37
+00:08:59,120 --> 00:09:01,629
+Два раза, и поднимается ветер. 
+
+38
+00:09:01,679 --> 00:09:03,980
+Три раза, и начинает идти дождь.
+
+39
+00:09:04,039 --> 00:09:07,509
+И вот тогда, мы сеем и собираем урожай.
+
+40
+00:09:07,559 --> 00:09:11,340
+Однако уговорить эту принцессу прийти
+
+41
+00:09:11,399 --> 00:09:14,870
+довольно трудно.
+
+42
+00:09:14,909 --> 00:09:16,820
+Где она живет? 
+
+43
+00:09:16,879 --> 00:09:20,190
+Она живет в Пещере Листа Пальмы на Горе Изумрудных Облаков.
+
+44
+00:09:20,240 --> 00:09:23,669
+Она там одна живет?
+
+45
+00:09:23,720 --> 00:09:25,750
+Разве у нее нет мужа?
+
+46
+00:09:25,799 --> 00:09:29,580
+Ее муж - Князь демонов с головой быка.
+
+47
+00:09:29,639 --> 00:09:32,200
+Значит, ее муж - Старый Бык?
+
+48
+00:09:32,240 --> 00:09:36,789
+Ты знаком с ним, дурень? Иди со мной за веером! 
+
+49
+00:09:36,840 --> 00:09:41,750
+Фактически... Старый Бык не живет там.
+
+50
+00:09:41,799 --> 00:09:46,350
+Прийти к его жене, когда он не дома -
+
+51
+00:09:46,399 --> 00:09:51,519
+не очень ... осторожный поступок.
+
+52
+00:09:51,559 --> 00:09:58,309
+Вы ... вы ... двое идите
+
+53
+00:09:58,360 --> 00:10:04,290
+А я... я останусь здесь и буду охранять учителя.
+
+54
+00:10:04,440 --> 00:10:11,269
+Ша Удзин, иди вместе с братьями.
+
+
+
+55
+00:10:38,571 --> 00:10:44,978
+Пещера Листа Пальмы
+
+56
+00:10:47,200 --> 00:10:51,549
+Дурень, я всегда иду первым.
+
+57
+00:10:51,600 --> 00:10:54,350
+Теперь твоя очередь!
+
+58
+00:10:58,519 --> 00:11:04,909
+Младший! Я всегда иду первым, теперь твоя очередь!
+
+59
+00:11:04,960 --> 00:11:06,830
+Старший...
+
+60
+00:11:06,879 --> 00:11:10,990
+Я хочу, чтобы ты тоже немного постарался для наставника. Неужели это так трудно? 
+
+61
+00:11:11,039 --> 00:11:14,309
+Веселей!
+
+62
+00:11:39,639 --> 00:11:43,039
+Бедный монах, откуда ты пришел?
+
+63
+00:11:43,039 --> 00:11:49,870
+Великий Мудрец... Танский монах ... хочет вашу принцессу...
+
+64
+00:11:49,919 --> 00:11:52,480
+Глупости!
+
+65
+00:12:47,549 --> 00:12:52,059
+Старший ... может тебе пойти следующим?
+
+66
+00:12:52,120 --> 00:12:56,950
+Дурень, иди ты!
+
+67
+00:12:57,000 --> 00:13:00,700
+Старший, почему не идешь? 
+
+68
+00:13:04,029 --> 00:13:07,460
+Ленивый дурень!
+
+69
+00:13:54,279 --> 00:13:57,899
+Великий Бог Грома! Не убивай меня, позволь мне уйти!
+
+70
+00:13:57,960 --> 00:13:59,950
+Иди и доложи своей принцессе,
+
+71
+00:14:00,000 --> 00:14:03,279
+что явился Сунь Укун одолжить у нее веер. 
+
+72
+00:14:03,279 --> 00:14:08,399
+Да, да! Отпусти, я сразу пойду.
+
+73
+00:14:29,559 --> 00:14:37,059
+Госпожа, пришел Сунь Укун, чтобы одолжить веер. 
+
+74
+00:14:41,519 --> 00:14:44,149
+Живо принесите мне мой меч.
+
+75
+00:15:01,639 --> 00:15:04,149
+Сунь Укун, ты погубил моего сына!
+
+76
+00:15:04,200 --> 00:15:08,549
+И ты еще смеешь являться сюда на свою погибель?
+
+77
+00:15:08,600 --> 00:15:12,039
+Я никогда не встречал тебя прежде, как же я мог навредить твоему сыну? 
+
+78
+00:15:12,039 --> 00:15:15,789
+Разве жизнь моего сына, Красного Ребенка, была разрушена не из-за тебя? 
+
+79
+00:15:15,840 --> 00:15:20,389
+Твой сын теперь во власти Богини Милосердия, как ты можешь говорить, что я погубил его? 
+
+80
+00:15:20,440 --> 00:15:23,750
+Довольно болтовни! Иди сюда и нагнись, я разрублю тебя своим мечом.
+
+81
+00:15:23,799 --> 00:15:26,149
+Если останешься жив, отдам тебе веер.
+
+82
+00:15:26,200 --> 00:15:28,549
+Правда? 
+
+83
+00:15:56,799 --> 00:16:00,629
+Стой! Сейчас же отдавай веер!
+
+
+84
+00:17:53,630 --> 00:18:00,099
+Великий Мудрец, разве вы не на Запад шли? Почему вы вернулись сюда? 
+
+85
+00:18:11,150 --> 00:18:17,140
+Принцесса махнула веером, и поднялся страшный ветер, который принес меня сюда.
+
+86
+00:18:17,190 --> 00:18:23,859
+Это действительно странно, Великий Мудрец. У меня есть кое-что для тебя. 
+
+87
+00:18:28,509 --> 00:18:33,450
+Это жемчужина против ветра. Когда ты примешь ее, 
+
+88
+00:18:33,509 --> 00:18:36,140
+твое сердце станет устойчивым, как скала.
+
+89
+00:18:36,190 --> 00:18:39,180
+Веер принцессы не сможет сдвинуть тебя с места.
+
+90
+00:18:39,230 --> 00:18:42,849
+Великий Мудрец, подойди и посмотри. 
+
+91
+00:19:00,430 --> 00:19:02,539
+Спасибо тебе.
+
+92
+00:19:06,069 --> 00:19:12,299
+Старший... где... к? 
+
+93
+00:19:12,349 --> 00:19:18,690
+где его... носит? 
+
+94
+00:19:18,750 --> 00:19:26,099
+Кто заботится о нем? Спасение обезьяны в ее руках. Пойдем.
+
+95
+00:19:35,190 --> 00:19:37,259
+Старший ... старший...
+
+96
+00:19:37,309 --> 00:19:43,470
+Ты... ты...
+
+97
+00:19:43,470 --> 00:19:50,220
+Куда тебя унесло из за той старухи?
+
+98
+00:19:50,269 --> 00:19:57,180
+Дурень, теперь определенно твоя очередь идти.
+
+99
+00:19:57,230 --> 00:20:00,930
+Я не пойду, одна воздушная волна ее веера 
+
+100
+00:20:00,990 --> 00:20:03,450
+может унести меня на край света.
+
+101
+00:20:03,509 --> 00:20:09,710
+Наверное, лучше, если ты снова пойдешь.
+
+102
+00:20:09,710 --> 00:20:12,220
+Я не пойду. 
+
+103
+00:20:17,789 --> 00:20:22,779
+В следующий раз я тебя не отпущу!
+
+104
+00:20:56,150 --> 00:21:00,140
+На сей раз я с места не сдвинусь, сколько бы ты ни махала, 
+
+105
+00:21:00,190 --> 00:21:05,210
+это так же верно, как то, что я - человек! 
+
+106
+00:21:33,670 --> 00:21:38,579
+Старший, почему ветер в этот раз не унес тебя? 
+
+107
+00:21:46,829 --> 00:21:50,099
+Давай, взломим дверь.
+
+108
+00:23:59,630 --> 00:24:04,180
+Живо доставайте веер для Сунь Укуна! 
+
+109
+00:24:14,869 --> 00:24:16,900
+Сунь Укун, где ты? 
+
+110
+00:24:16,950 --> 00:24:19,980
+Я у тебя в животе! 
+
+111
+00:24:45,750 --> 00:24:48,539
+Сунь Укун, смилуйся надо мной! 
+
+112
+00:24:48,589 --> 00:24:51,180
+Только, если отдашь веер! 
+
+113
+00:24:51,230 --> 00:24:56,539
+Я клянусь, я отдам. Пожалуйста, выходи!
+
+114
+00:25:00,230 --> 00:25:02,819
+Живо принесите веер. 
+
+115
+00:25:07,430 --> 00:25:09,220
+Мы принесли веер.
+
+116
+00:25:09,279 --> 00:25:12,069
+Почему же ты не выходишь? 
+
+117
+00:25:12,109 --> 00:25:16,619
+Открой рот, и я выйду.
+
+118
+00:25:25,349 --> 00:25:29,420
+Сунь Укун, почему ты не вышел? 
+
+119
+00:25:50,349 --> 00:25:55,579
+Я здесь. Одолжи мне веер ненадолго и я верну его.
+
+120
+00:26:32,549 --> 00:26:36,579
+Наставник заждался, давайте поспешим!
+
+
+
+121
+00:27:01,869 --> 00:27:04,900
+Что такое священные книги?
+
+122
+00:27:04,950 --> 00:27:10,029
+Священные книги это законы неба и земли.
+
+123
+00:27:10,029 --> 00:27:14,180
+Они являются принципами человека. 
+
+124
+00:27:14,230 --> 00:27:18,700
+Только тот, кто признает эти принципы,  
+
+125
+00:27:18,750 --> 00:27:25,339
+сможет избавить себя от боли и жить хорошо,
+
+126
+00:27:25,390 --> 00:27:29,940
+жить честной, истинной жизнью. 
+
+127
+00:27:34,680 --> 00:27:36,349
+И наоборот, 
+
+128
+00:27:36,390 --> 00:27:40,089
+тот, кто не знает эти принципы, 
+
+129
+00:27:40,150 --> 00:27:46,380
+будет жить жизнью, полной страдания.
+
+130
+00:27:46,430 --> 00:27:52,609
+Даже его сын или внук не достигнут счастья.
+
+131
+00:27:52,670 --> 00:27:55,660
+Почему я надеюсь получить священные книги? 
+
+132
+00:27:55,710 --> 00:28:01,299
+Люди в наше время пойманы в ловушку страданий.
+
+133
+00:28:01,349 --> 00:28:04,180
+И чтобы это изменить, мы идем поклониться
+
+134
+00:28:04,230 --> 00:28:12,500
+Танскому императору и обсудить этот очень сложный вопрос.
+
+
+
+
+135
+00:28:15,670 --> 00:28:17,819
+Вы добыли веер?  
+
+136
+00:28:17,869 --> 00:28:19,400
+Он у нас. 
+
+137
+00:28:19,401 --> 00:28:20,779
+Что это?
+
+138
+00:28:22,829 --> 00:28:27,980
+Благородные хозяева, теперь, когда у нас есть веер, 
+
+139
+00:28:28,029 --> 00:28:32,140
+мы можем отдохнуть.
+
+140
+00:28:32,190 --> 00:28:34,039
+Держитесь. 
+
+141
+00:28:34,039 --> 00:28:39,789
+Народ, я хотел бы попросить мудрого Сэнга погостить у нас еще нескольких дней. 
+
+142
+00:28:39,829 --> 00:28:41,339
+Вы согласны? 
+
+143
+00:28:41,390 --> 00:28:43,460
+Согласны! 
+
+144
+00:28:43,509 --> 00:28:45,890
+Спасибо вам за вашу доброту.
+
+145
+00:28:45,950 --> 00:28:51,779
+Но чем скорее я уеду, тем скорее мы сможем завершить нашу задачу.
+
+146
+00:28:51,829 --> 00:28:56,180
+Очень хорошо, пусть благородный ученик сначала пойдет на Огненную Гору. 
+
+147
+00:28:56,230 --> 00:29:02,140
+После гашения огней, продолжите следовать за мудрым Сэнгом. 
+
+148
+00:29:02,190 --> 00:29:05,460
+Хорошо, вперед! 
+
+149
+00:30:24,470 --> 00:30:30,029
+Принцесса действительно коварна, она дала нам фальшивый веер! 
+
+150
+00:30:30,029 --> 00:30:32,779
+Я точно убью ее! 
+
+151
+00:30:32,829 --> 00:30:36,299
+Нет, убивать нельзя. 
+
+152
+00:30:36,349 --> 00:30:39,579
+Я не позволю вам никого убивать.
+
+153
+00:30:39,630 --> 00:30:42,980
+Давайте придумаем что-нибудь другое. 
+
+154
+00:30:52,150 --> 00:30:56,220
+Старший, как она могла тебя одурачить? 
+
+155
+00:30:56,269 --> 00:30:58,539
+После стольких усилий
+156
+00:30:58,589 --> 00:31:02,099
+все, чего мы достигли, оказалось фальшивым веером. 
+
+157
+00:31:02,150 --> 00:31:06,500
+Смешно, смешно. 
+
+158
+00:31:08,910 --> 00:31:10,420
+Тогда идешь ты! 
+
+159
+00:31:10,470 --> 00:31:14,380
+Хорошо, я пойду, я пойду, я иду! 
+
+160
+00:31:14,430 --> 00:31:16,908
+Я пойду искать Князя Демонов с головой быка. 
+
+161
+00:31:16,909 --> 00:31:19,940
+Это хорошее решение.
+
+162
+00:31:21,390 --> 00:31:24,439
+Братец, что скажешь?
+
+163
+00:31:24,440 --> 00:31:27,380
+Мы будем следить за тобой.
+
+
+
+164
+00:33:07,190 --> 00:33:11,150
+Как ты считаешь, я хороша сегодня? 
+
+165
+00:33:11,150 --> 00:33:13,779
+Ты красавица, крошка. 
+
+166
+00:33:13,829 --> 00:33:17,059
+Пойди со мной на прогулку, ладно? 
+
+167
+00:33:17,109 --> 00:33:21,539
+Моя крошка, может тебе лучше пойти одной.
+
+168
+00:33:21,589 --> 00:33:24,819
+Конечно, я всего лишь бедная девушка страны. 
+
+169
+00:33:24,869 --> 00:33:28,019
+Сопровождение меня вне пещеры может скомпрометировать тебя. 
+
+170
+00:33:28,069 --> 00:33:32,029
+Милая, что ты говоришь?
+
+171
+00:33:32,029 --> 00:33:37,500
+Иди вперед, а я выйду следом, хорошо?
+
+172
+00:33:39,852 --> 00:33:44,557
+Пещера Изумрудных Облаков
+
+173
+00:35:28,030 --> 00:35:35,659
+Божественная, вы и вправду ангел, сошедший с небес. 
+
+174
+00:35:35,710 --> 00:35:37,900
+Кто ... кто вы? 
+
+175
+00:35:37,949 --> 00:35:41,460
+Я пришел из Пещеры Листа Пальмы к Князю Демонов с головой быка. 
+
+176
+00:35:41,519 --> 00:35:43,980
+Пустите меня! 
+
+177
+00:35:49,550 --> 00:35:52,940
+Божественная, подожди! 
+
+178
+00:36:38,768 --> 00:36:40,133
+Пещера Изумрудных Облаков
+
+179
+00:36:44,230 --> 00:36:49,219
+Крошка, кто тебя обидел? 
+
+180
+00:36:49,269 --> 00:36:50,820
+Ты!
+
+181
+00:36:50,869 --> 00:36:54,340
+Чем я мог обидеть тебя?
+
+182
+00:36:56,909 --> 00:36:59,260
+Почему ты не возвращаешься в Пещеру Листа Пальмы?
+
+183
+00:36:59,320 --> 00:37:01,699
+У тебя было бы меньше хлопот. 
+
+184
+00:37:01,750 --> 00:37:07,659
+За вами специально посылают людей, чтобы измываться надо мной. 
+
+185
+00:37:07,710 --> 00:37:11,059
+За мной кто-то приходил? 
+
+186
+00:37:11,110 --> 00:37:15,059
+Пришел монах с мордой свиньи, он ищет вас. 
+
+187
+00:37:15,119 --> 00:37:18,510
+Он почти испугал меня до смерти.
+
+188
+00:37:18,550 --> 00:37:22,739
+Как это может быть? Подожди, я выйду взглянуть.
+
+189
+00:37:50,670 --> 00:37:53,780
+Бык, старина!
+
+190
+00:37:53,829 --> 00:37:58,139
+Здесь есть очень красивая девушка.
+
+191
+00:37:58,199 --> 00:38:03,889
+Эй, это же моя женщина! Зачем ты ее тиранишь?
+
+192
+00:38:03,930 --> 00:38:08,550
+Ой, я не знал, прости меня!
+
+193
+00:38:08,550 --> 00:38:11,940
+Ну раз не знал, не могу тебя винить. Можешь идти!
+
+194
+00:38:11,989 --> 00:38:16,099
+Нет, нет. Мне все еще нужна твоя помощь в одном деле.
+
+195
+00:38:18,469 --> 00:38:24,710
+Мы продолжаем наш путь за священными книгами и дошли до Огненной Горы. 
+
+196
+00:38:24,710 --> 00:38:27,300
+Пожалуйста, попроси свою жену
+
+197
+00:38:27,349 --> 00:38:30,820
+одолжить нам пальмовый веер ненадолго.
+
+198
+00:38:30,880 --> 00:38:33,510
+Абсолютно нет! Танский монах Сенг и Сунь Укун -
+
+199
+00:38:33,510 --> 00:38:35,179
+враги моего сына. 
+
+200
+00:38:35,230 --> 00:38:38,739
+Я жажду им отомстить.
+
+201
+00:38:38,789 --> 00:38:44,969
+Ваш сын теперь служит Богини Милосердия, пожалуйста, успокойся.  
+
+202
+00:38:45,030 --> 00:38:48,940
+Хорошо, так как мы старые друзья, я не буду драться с тобой. 
+
+203
+00:38:49,000 --> 00:38:51,710
+А теперь уходи!
+
+204
+00:39:38,389 --> 00:39:44,179
+Крошка, тот монах с мордой свиньи мой друг. 
+
+205
+00:39:44,230 --> 00:39:46,500
+Его вообще не посылали из Пещеры Листа Пальмы. 
+
+206
+00:39:46,550 --> 00:39:47,739
+Я не верю вам. 
+
+207
+00:39:47,789 --> 00:39:50,940
+Я тебя не обманываю!
+
+208
+00:39:50,989 --> 00:39:54,019
+Где же он теперь?
+
+209
+00:39:54,110 --> 00:39:57,780
+Я уже прогнал его.
+
+
+
+210
+00:43:34,814 --> 00:43:40,987
+Пещера Листа Пальмы
+
+211
+00:43:58,630 --> 00:44:01,340
+Повелитель вернулся!
+
+212
+00:44:01,389 --> 00:44:02,369
+Где госпожа?
+
+213
+00:44:02,429 --> 00:44:04,780
+Она там.
+
+214
+00:44:42,989 --> 00:44:48,219
+Почему повелитель оказал такую честь и пришел сегодня?
+
+215
+00:44:48,269 --> 00:44:52,260
+Я услышал, что Сунь Укун и танский монах Сэнг идут сюда.
+
+216
+00:44:52,320 --> 00:44:56,909
+Я боюсь, что они хотят добыть веер пальмового листа, чтобы перейти Огненную Гору.
+
+217
+00:44:56,949 --> 00:45:00,860
+Та обезьяна  - именно тот, кто вредил нашему сыну.
+
+218
+00:45:00,909 --> 00:45:08,489
+Рано или поздно я поймаю его, и мы отомстим.
+
+219
+00:45:08,550 --> 00:45:12,699
+Дорогая, почему ты плачешь?
+
+220
+00:45:12,750 --> 00:45:15,699
+Эта обезьяна уже была здесь.
+
+221
+00:45:15,750 --> 00:45:18,860
+Я отказалась дать ему веер.
+
+222
+00:45:18,909 --> 00:45:22,260
+Я не знаю как, но он проник ко мне в живот. 
+
+223
+00:45:22,309 --> 00:45:25,500
+Мне было так плохо, я думала, что умру.
+
+224
+00:45:25,550 --> 00:45:30,589
+В итоге, мне пришлось отдать веер.
+
+225
+00:45:30,789 --> 00:45:35,260
+Какой ужас, как ты могла отдать ему веер?
+
+226
+00:45:38,320 --> 00:45:40,469
+Я дала ему поддельный.
+
+227
+00:45:40,720 --> 00:45:43,019
+Поддельный?
+
+
+228
+00:46:14,190 --> 00:46:19,860
+Пир в честь повелителя  
+
+229
+00:46:19,909 --> 00:46:25,619
+Пожалуйста выпей прекрасное вино. 
+
+230
+00:46:25,670 --> 00:46:34,179
+Цыпленок ароматен, утка красива, и свинья жирна. 
+
+231
+00:46:34,239 --> 00:46:45,670
+Я изо всех сил пытаюсь петь и танцевать. 
+
+232
+00:46:45,710 --> 00:46:54,500
+Ты должна также изо всех сил пить.
+
+233
+00:47:03,590 --> 00:47:16,389
+Мой повелитель! Ты оставил прошлое. 
+
+234
+00:47:16,429 --> 00:47:22,610
+Ты любишь другую женщину. 
+
+235
+00:47:22,670 --> 00:47:34,659
+Бесчисленные слезы были пролиты ради тебя.
+
+236
+00:47:46,710 --> 00:47:55,699
+Когда свет погаснет и опустят занавески, 
+
+237
+00:47:55,750 --> 00:48:00,869
+ты будешь спать один.
+
+238
+00:48:00,869 --> 00:48:05,510
+Ты также почувствуешь одинокость. 
+
+239
+00:48:05,510 --> 00:48:13,420
+Извини, что не могу составить тебе компанию. 
+
+240
+00:48:18,550 --> 00:48:24,619
+Даже если мы будем на той же кровати,
+
+241
+00:48:24,670 --> 00:48:34,340
+мы будем спать под отдельными листами. 
+
+242
+00:48:38,389 --> 00:48:42,380
+Король, я пьяна. 
+
+243
+00:48:55,070 --> 00:48:58,139
+Супруженька, куда же ты спрятала настоящий веер?
+
+244
+00:48:58,190 --> 00:49:05,460
+Эта обезьяна очень коварна, а кабан еще хитрее.
+
+245
+00:49:05,510 --> 00:49:09,780
+Если не будешь осторожной, они тебя могут обмануть.
+
+246
+00:49:18,360 --> 00:49:21,980
+Наше драгоценность прямо здесь. 
+
+247
+00:49:31,429 --> 00:49:39,309
+Повелитель, о чем ты задумался? Почему не берешь ее?
+
+248
+00:49:39,309 --> 00:49:40,847
+Моя драгоценность.
+
+249
+00:49:41,514 --> 00:49:44,150
+Пещера Изумрудных Облаков
+
+250
+00:49:44,250 --> 00:49:49,019
+Крошка, бери другую чашку. Пей.
+
+251
+00:49:53,909 --> 00:49:59,510
+Золотой царь драконов попросил, чтобы я выпил с ним сегодня вечером. 
+
+252
+00:49:59,510 --> 00:50:01,420
+Тогда вы должны пойти. 
+
+253
+00:50:01,469 --> 00:50:02,860
+Правильно. 
+
+254
+00:50:02,909 --> 00:50:06,610
+Подготовь золотое животное к дедушке.
+
+255
+00:50:06,670 --> 00:50:08,260
+Я мигом. 
+
+256
+00:50:08,320 --> 00:50:12,590
+Вы должны выпить поменьше сегодня вечером. 
+
+257
+00:50:12,630 --> 00:50:15,739
+Иначе я не смогу разбудить вас. 
+
+258
+00:50:15,800 --> 00:50:19,110
+Какой ужас, золотое глазастое животное дедушки исчезло!
+
+259
+00:50:19,150 --> 00:50:20,900
+Действительно ли вы - все тугоухие и слепые? 
+
+260
+00:50:20,949 --> 00:50:24,030
+Как оно могло просто исчезнуть? 
+
+261
+00:50:24,030 --> 00:50:27,900
+Крошка, не спорь. 
+
+262
+00:50:27,960 --> 00:50:31,710
+Я боюсь, что Джу Бацзе, возможно, украл его. 
+
+263
+00:50:31,750 --> 00:50:35,260
+Может мне лучше пойти к Пещере Листа Пальмы. 
+
+264
+00:50:35,320 --> 00:50:39,309
+Что? Все это заранее планировалось вами. 
+
+265
+00:50:42,280 --> 00:50:48,150
+Вы все еще хотите вернуться к той бессовестной женщине? 
+
+266
+00:50:48,190 --> 00:50:50,699
+Пожалуйста, крошка, не плачь.
+
+267
+00:50:50,750 --> 00:50:54,059
+Я скоро вернусь.
+
+
+268
+00:50:57,624 --> 00:51:01,194
+Пещера Листа Пальмы
+
+269
+00:51:02,670 --> 00:51:07,300
+Иди сюда, выпей немного! 
+
+270
+00:51:10,349 --> 00:51:12,460
+Теперь я могу быть спокоен. 
+
+271
+00:51:12,510 --> 00:51:16,699
+Мы можем не волноваться по поводу нашей драгоценности. 
+
+272
+00:51:16,750 --> 00:51:21,300
+Даже если бы они похитили веер, они бы все-равно не знали что надо тянуть шелковую нить. 
+
+273
+00:51:21,360 --> 00:51:26,269
+Одна жемчужина ни на что не способна.
+
+274
+00:51:26,309 --> 00:51:31,780
+Натягивание нити превращает ее в веер, правильно? 
+
+275
+00:51:35,119 --> 00:51:38,070
+Повелитель, ты пьян. 
+
+276
+00:51:38,110 --> 00:51:44,019
+Ты забыл как пользоваться собственной драгоценностью и спрашиваешь у меня. 
+
+277
+00:51:49,989 --> 00:51:53,690
+Женщина, посмотри, кто перед тобой.
+
+278
+00:52:00,320 --> 00:52:03,750
+Кто вы? 
+
+279
+00:52:03,789 --> 00:52:09,889
+Я - второй ученик танского монаха, Джу Бацзе.
+
+280
+00:52:09,949 --> 00:52:14,780
+Извини за беспокойство, и спасибо!
+
+281
+00:52:19,079 --> 00:52:21,710
+Пока!
+
+
+282
+00:53:06,829 --> 00:53:10,699
+Жена быка слишком кокетливая.
+
+283
+00:53:10,760 --> 00:53:14,710
+Все ее служанки красивы.
+
+284
+00:53:14,750 --> 00:53:24,809
+Старый Кабан почти не справился.
+
+285
+00:53:24,869 --> 00:53:28,860
+Используя умные уловки и тактику, 
+
+286
+00:53:28,909 --> 00:53:32,820
+я украл их драгоценность.
+
+287
+00:53:32,880 --> 00:53:36,789
+Это большой подвиг.
+
+288
+00:53:36,829 --> 00:53:38,300
+Монах Песков должен мне поклониться.
+
+289
+00:53:38,349 --> 00:53:40,730
+Обезьяне следует у меня поучиться.
+
+290
+00:53:40,789 --> 00:53:45,219
+Даже наставник будет удивлен.
+
+291
+00:53:45,280 --> 00:53:49,190
+Старый Кабан действительно лучше всех.
+
+292
+00:53:49,230 --> 00:53:54,349
+Старый Кабан действительно лучше всех.
+
+
+293
+00:54:36,719 --> 00:54:40,469
+Дурень, как идут дела?
+
+294
+00:54:40,510 --> 00:54:42,809
+Мало того, что я получил веер, 
+
+295
+00:54:42,880 --> 00:54:48,789
+Еще и принцесса Железный Веер полдня была моей женой. 
+
+296
+00:54:48,829 --> 00:54:51,699
+Тебе повезло.
+
+297
+00:54:58,150 --> 00:55:01,579
+Эй, покажи мне веер.
+
+298
+00:55:16,030 --> 00:55:20,219
+Почему ты уменьшил его?
+
+299
+00:55:40,550 --> 00:55:45,340
+Старая Свинья, ты узнаешь меня, верно? 
+
+300
+00:55:45,389 --> 00:55:49,170
+Прекрати шутить со мной.
+
+301
+00:55:49,230 --> 00:55:52,139
+А разве с тобой кто-нибудь шутит?
+
+
+302
+00:56:42,869 --> 00:56:45,380
+Дурень, как прошло?  
+
+303
+00:56:45,429 --> 00:56:47,099
+Ничего не вышло.
+
+304
+00:56:47,150 --> 00:56:49,980
+Унэн, ты достал веер? 
+
+305
+00:56:50,030 --> 00:56:53,340
+Я нашел Князя демонов, но он отказался. 
+
+306
+00:56:53,400 --> 00:56:59,190
+Тогда я превратился в него.
+
+307
+00:56:59,230 --> 00:57:03,539
+Хитростью я выманил веер у Принцессы. 
+
+308
+00:57:03,590 --> 00:57:10,590
+Но тогда Старый Бык превратился в тебя и тоже меня обманул. 
+
+309
+00:57:10,590 --> 00:57:12,739
+Старый Бык обладает большой волшебной силой. 
+
+310
+00:57:12,800 --> 00:57:16,150
+Он еще и меня побил.
+
+311
+00:57:16,190 --> 00:57:21,380
+Как же ты мог получить веер и оказаться таким дурнем? 
+
+312
+00:57:21,429 --> 00:57:25,659
+Не воображай! 
+
+313
+00:57:30,750 --> 00:57:34,369
+Не ссорьтесь, мы должны срочно что-то придумать. 
+
+314
+00:57:34,429 --> 00:57:40,260
+Найти какой... какой-нибудь обход, где нет огня? 
+
+315
+00:57:40,320 --> 00:57:47,070
+Из востока, юга, запада, севера, огонь распространяется только на Запад.  
+
+316
+00:57:47,119 --> 00:57:50,739
+Поэтому мы можем только повернуть.
+
+317
+00:57:50,789 --> 00:57:52,940
+Эта дорога закрыта для нас, что еще можно делать? 
+
+318
+00:57:52,989 --> 00:57:55,219
+Бадзе, не говори так. 
+
+319
+00:57:55,269 --> 00:57:59,139
+На нашей дороге всегда будут преграды. 
+
+320
+00:57:59,190 --> 00:58:04,539
+Чтобы завершить нашу священную задачу, мы должны быть сильными в нашей вере. 
+
+321
+00:58:04,590 --> 00:58:09,219
+Мы не можем повернуть на полпути, если мы столкнулись с препятствиями.
+
+322
+00:58:09,280 --> 00:58:14,590
+Причина нашего поражения в том, что мы не боремся вместе.
+
+323
+00:58:14,630 --> 00:58:17,139
+Если вы, трое, объединитесь, 
+
+324
+00:58:17,190 --> 00:58:20,500
+и общими усилиями будете сражаться с Князем Демонов, 
+
+325
+00:58:20,550 --> 00:58:22,849
+вы обязательно победите. 
+
+326
+00:58:22,909 --> 00:58:26,030
+Мы услышали наказ наставника 
+
+327
+00:58:26,030 --> 00:58:30,139
+и будем сражаться с Князем Демонов до конца. 
+
+328
+00:58:30,190 --> 00:58:34,260
+до...  до конца
+
+329
+00:58:34,320 --> 00:58:37,710
+Замечательно! 
+
+330
+00:58:37,750 --> 00:58:40,980
+Мы все справились с трудностями. 
+
+331
+00:58:41,039 --> 00:58:43,869
+Я надеюсь, каждый будет стараться 
+
+332
+00:58:43,869 --> 00:58:49,579
+вместе с моими учениками победить Князя Демонов и потушить пламя Огненной Горы. 
+
+333
+00:58:49,630 --> 00:58:52,820
+Иначе страдание никогда не кончится. 
+
+334
+00:58:53,869 --> 00:58:57,489
+Мы услышали наказ наставника, искать счастье для всех.  
+
+335
+00:58:57,550 --> 00:58:58,860
+Все объединяйтесь!
+
+336
+00:58:58,909 --> 00:59:00,519
+Хорошо!
+
+337
+01:08:23,229 --> 01:08:25,609
+Госпожа, какой ужас!
+
+338
+01:08:25,670 --> 01:08:30,789
+Господин пойман в ловушку, идите скорее! 
+
+339
+01:08:54,470 --> 01:08:56,699
+Борьба еще не решена, не решена.
+
+340
+01:08:56,760 --> 01:08:58,710
+Осторожно, осторожно.
+
+341
+01:08:59,760 --> 01:09:05,789
+Животное, все что ты должен - это отдать нам веер, и мы сохраним тебе жизнь.
+
+342
+01:09:05,840 --> 01:09:12,750
+Старый Бык, где веер? Отдай его!
+
+343
+01:09:12,789 --> 01:09:19,340
+Он... у моей жены.
+
+344
+01:09:25,239 --> 01:09:27,989
+Дорогая, милая.
+
+345
+01:09:28,029 --> 01:09:32,260
+Спаси меня скорее.
+
+346
+01:09:32,319 --> 01:09:35,109
+Отдай им веер.
+
+347
+01:09:35,149 --> 01:09:39,619
+Мой повелитель! Хорошо, хорошо!
+
+348
+01:09:43,399 --> 01:09:47,229
+Укун, иди еще раз!
+
+349
+01:12:30,850 --> 01:12:46,599
+Конец
+
diff --git a/js2/mwEmbed/example_usage/media/princess_archive_org/princess_iron_fan-zh-hant.srt b/js2/mwEmbed/example_usage/media/princess_archive_org/princess_iron_fan-zh-hant.srt
new file mode 100644 (file)
index 0000000..734c4bf
--- /dev/null
@@ -0,0 +1,1392 @@
+1
+00:00:01,080 --> 00:00:09,078
+片名:鐵扇公主
+
+2
+00:02:03,119 --> 00:02:09,280
+西遊記,本為一部絕妙之童話
+
+3
+00:02:09,280 --> 00:02:15,280
+特以世多誤解,致被目為神怪小說
+
+4
+00:02:15,280 --> 00:02:19,240
+本片取材於是
+
+5
+00:02:19,240 --> 00:02:24,240
+實為培育兒童心理而作
+
+6
+00:02:24,240 --> 00:02:29,280
+故內容刪蕪存精,不涉神怪
+
+7
+00:02:29,280 --> 00:02:32,560
+僅以唐僧等四人路阻火焰山
+
+8
+00:02:32,560 --> 00:02:41,040
+以示人生途徑中之磨難
+
+9
+00:02:41,040 --> 00:02:46,440
+欲求經此磨難,則必須堅持信念
+大眾一心
+
+10
+00:02:46,440 --> 00:02:52,436
+始能獲得此撲滅凶焰之芭蕉扇
+
+11
+00:03:34,480 --> 00:03:37,790
+現在已經秋天了,怎麼還這麼熱
+
+12
+00:03:37,840 --> 00:03:42,356
+呆子,不要說廢話,趕路要緊
+
+13
+00:04:06,920 --> 00:04:09,354
+悟空,這是到了什麼地方
+
+14
+00:04:09,400 --> 00:04:13,678
+反正是我們上西天必定要經過的地方
+
+15
+00:04:13,720 --> 00:04:18,111
+我們沒有走錯路線吧
+
+16
+00:04:18,159 --> 00:04:22,311
+為什麼這個地方這麼樣的熱呢
+
+17
+00:04:30,039 --> 00:04:31,711
+師傅,你看
+
+18
+00:04:31,759 --> 00:04:33,795
+前面那兒,不是有一座房子了嗎
+
+19
+00:04:33,839 --> 00:04:38,117
+我們大家進去歇息一會兒好吧
+
+20
+00:04:59,399 --> 00:05:02,914
+這個地方名叫火焰山
+
+21
+00:05:02,959 --> 00:05:06,031
+周圍有幾百里的火焰
+
+22
+00:05:06,079 --> 00:05:08,752
+一根草都不生
+
+23
+00:05:08,799 --> 00:05:11,632
+一年四季都是熱的
+
+24
+00:05:11,680 --> 00:05:19,633
+就是銅頭鐵臂要經過那個山
+也得融化成水
+
+25
+00:05:19,679 --> 00:05:23,592
+哪有這種事,師傅,你請放心
+
+26
+00:05:23,639 --> 00:05:27,154
+我們三個人都有法子可以過去
+
+27
+00:05:27,199 --> 00:05:30,714
+師傅,我去看看好吧
+
+28
+00:08:06,319 --> 00:08:09,595
+悟空,你去看了怎麼樣
+
+29
+00:08:09,639 --> 00:08:11,834
+厲害,厲害,真厲言
+
+30
+00:08:11,880 --> 00:08:15,919
+要不是我跑得快,尾巴都燒光了
+
+31
+00:08:42,720 --> 00:08:47,600
+老施主,這裡的火這樣大
+
+32
+00:08:47,600 --> 00:08:49,670
+這五穀從哪兒來的
+
+33
+00:08:49,719 --> 00:08:53,997
+你看這兒有一千多里的路
+有一位鐵扇公主
+
+34
+00:08:54,040 --> 00:08:56,508
+她有一把芭蕉扇
+
+35
+00:08:56,560 --> 00:08:59,074
+一扇呢,火就熄了
+
+36
+00:08:59,120 --> 00:09:01,634
+兩扇呢,風就來了
+
+37
+00:09:01,680 --> 00:09:03,989
+三扇呢,就下雨了
+
+38
+00:09:04,040 --> 00:09:07,510
+我們就從這個時候播種收割
+
+39
+00:09:07,560 --> 00:09:11,348
+不過,要請那位公主來
+
+40
+00:09:11,400 --> 00:09:14,870
+可不是一件容易的事
+
+41
+00:09:14,919 --> 00:09:16,830
+她住在什麼地方
+
+42
+00:09:16,880 --> 00:09:20,190
+她住在翠雲山芭蕉洞
+
+43
+00:09:20,240 --> 00:09:23,676
+是她一個人住在那兒嗎
+
+44
+00:09:23,720 --> 00:09:25,756
+她有沒有丈夫啊
+
+45
+00:09:25,800 --> 00:09:29,588
+她的丈夫是牛魔王
+
+46
+00:09:29,640 --> 00:09:32,200
+原來是老牛
+
+47
+00:09:32,240 --> 00:09:36,791
+呆子,你竟然認識他嗎?
+跟我一塊兒借扇子去
+
+48
+00:09:36,840 --> 00:09:41,755
+我…我知道老牛不住在那兒的
+
+49
+00:09:41,800 --> 00:09:46,351
+在他男人不在家的時候
+我們去找他的女人
+
+50
+00:09:46,400 --> 00:09:51,520
+這…這有點不大方便吧
+
+51
+00:09:51,560 --> 00:09:58,318
+你們…兩個人…去吧
+
+52
+00:09:58,360 --> 00:10:05,198
+我…我在…這兒…伺候師父
+
+53
+00:10:05,240 --> 00:10:11,270
+悟淨,你也跟你兩個師兄一同去吧
+
+54
+00:10:47,200 --> 00:10:51,557
+呆子,每次都是我去打頭陣的
+
+55
+00:10:51,600 --> 00:10:54,353
+這次該你去了
+
+56
+00:10:58,520 --> 00:11:04,914
+三弟,每次都是我去打頭陣
+這次該你去了
+
+57
+00:11:04,960 --> 00:11:06,837
+大師兄
+
+58
+00:11:06,880 --> 00:11:10,998
+我叫你去給師父出一點力
+你都不肯嗎
+
+59
+00:11:11,040 --> 00:11:14,316
+快去…
+
+60
+00:11:39,640 --> 00:11:43,040
+你是哪兒跑來的野和尚
+
+61
+00:11:43,040 --> 00:11:49,878
+大唐…聖僧…要你家…大公主…
+
+62
+00:11:49,920 --> 00:11:52,480
+胡說
+
+63
+00:12:47,559 --> 00:12:52,075
+大…大師兄,還是你去吧
+
+64
+00:12:52,120 --> 00:12:56,955
+呆子,你去
+
+65
+00:12:57,000 --> 00:13:00,709
+大師兄,還是你去吧
+
+66
+00:13:04,039 --> 00:13:07,475
+偷懶的東西
+
+67
+00:13:54,280 --> 00:13:57,909
+好雷公菩薩,你饒了我放了我吧
+
+68
+00:13:57,960 --> 00:13:59,951
+你跟你們公主說
+
+69
+00:14:00,000 --> 00:14:03,280
+我孫悟空要來借芭蕉扇
+
+70
+00:14:03,280 --> 00:14:08,400
+好,好,你放了我,我就去
+
+71
+00:14:29,560 --> 00:14:37,069
+奶奶,外面有一個孫悟空
+要來借芭蕉扇
+
+72
+00:14:41,520 --> 00:14:44,159
+快拿我的劍來
+
+73
+00:15:01,640 --> 00:15:04,154
+孫悟空,害我兒子的仇人
+
+74
+00:15:04,200 --> 00:15:08,557
+你今天也敢自己來送死嗎
+
+75
+00:15:08,600 --> 00:15:12,040
+我是從來沒見過你,怎麼會害你的兒子
+
+76
+00:15:12,040 --> 00:15:15,794
+我的孩子紅孩兒不是你害死的嗎
+
+77
+00:15:15,840 --> 00:15:20,391
+令郎已成正果,怎麼說老孫害他呢
+
+78
+00:15:20,440 --> 00:15:23,750
+少說廢話,伸過頭來讓我砍幾劍
+
+79
+00:15:23,800 --> 00:15:26,155
+受得住我就把芭蕉扇借給你
+
+80
+00:15:26,200 --> 00:15:28,555
+真的嗎
+
+81
+00:15:56,800 --> 00:16:00,634
+慢著,快把扇子借給我
+
+82
+00:17:53,639 --> 00:18:00,112
+大聖不保唐僧到西天去
+來到這兒做什麼
+
+83
+00:18:11,159 --> 00:18:17,155
+我被鐵扇公主一扇扇到這兒來的
+
+84
+00:18:17,199 --> 00:18:23,877
+大聖你來得巧極了
+我有一樣東西送給你
+
+85
+00:18:28,519 --> 00:18:33,468
+這裡是一粒定風珠,大聖你有了這珠子
+
+86
+00:18:33,519 --> 00:18:36,158
+可以使你的心堅定了
+
+87
+00:18:36,199 --> 00:18:39,191
+保那鐵扇公主扇不動你了
+
+88
+00:18:39,239 --> 00:18:42,868
+大聖你來看
+
+89
+00:19:00,439 --> 00:19:02,555
+謝謝
+
+90
+00:19:06,079 --> 00:19:12,314
+大…大師兄…不知給…
+
+91
+00:19:12,359 --> 00:19:18,707
+吹到什麼…地方去了
+
+92
+00:19:18,759 --> 00:19:26,109
+管他呢,讓猴子也吃點舌頭,我們走
+
+93
+00:19:35,199 --> 00:19:37,269
+大…大…師兄
+
+94
+00:19:37,319 --> 00:19:43,479
+你…被…被…那…
+
+95
+00:19:43,479 --> 00:19:50,237
+大師兄,你被那個婆娘扇到
+什麼地方去了
+
+96
+00:19:50,279 --> 00:19:57,196
+呆子,現在總該你去了
+
+97
+00:19:57,239 --> 00:20:00,948
+我不去,我要是被她一扇
+
+98
+00:20:00,999 --> 00:20:03,467
+簡直就認不得回來了
+
+99
+00:20:03,519 --> 00:20:09,719
+還是…你再去一趟吧
+
+100
+00:20:09,719 --> 00:20:12,233
+不去,不去
+
+101
+00:20:17,799 --> 00:20:22,793
+下次輪到你,可不准再偷懶了
+
+102
+00:20:56,159 --> 00:21:00,152
+這次你儘管扇,扇得我動一動
+
+103
+00:21:00,199 --> 00:21:05,227
+我不算男子漢大丈夫
+
+104
+00:21:33,679 --> 00:21:38,594
+大師兄,怎麼這回
+她的扇子沒有用啊
+
+105
+00:21:46,839 --> 00:21:50,115
+我們來打進去
+
+106
+00:23:59,639 --> 00:24:04,190
+快把芭蕉拿出來,給我孫悟空用一用
+
+107
+00:24:14,879 --> 00:24:16,915
+孫悟空,你在什麼地方
+
+108
+00:24:16,959 --> 00:24:19,996
+我在你肚子裡呢
+
+109
+00:24:45,759 --> 00:24:48,557
+孫悟空,你饒了我的命吧
+
+110
+00:24:48,599 --> 00:24:51,193
+你把扇子拿出來就是了
+
+111
+00:24:51,239 --> 00:24:56,552
+我答應你就是了,請你快點出來吧
+
+112
+00:25:00,239 --> 00:25:02,833
+快把扇子拿來
+
+113
+00:25:07,439 --> 00:25:09,236
+扇子已經來了
+
+114
+00:25:09,280 --> 00:25:12,078
+孫悟空你怎麼還不出來呢
+
+115
+00:25:12,119 --> 00:25:16,635
+你把嘴張開來,我就出來了
+
+116
+00:25:25,359 --> 00:25:29,432
+孫祖宗,你怎麼還不出來呢
+
+117
+00:25:50,359 --> 00:25:55,592
+我在這兒呢,借給我用用就還你的
+
+118
+00:26:32,559 --> 00:26:36,598
+師父等了好久了,我們快去吧
+
+119
+00:27:01,879 --> 00:27:04,916
+經,經是什麼
+
+120
+00:27:04,959 --> 00:27:10,039
+經是天地之間不能辨易的道理
+
+121
+00:27:10,039 --> 00:27:14,191
+這個道理也就是做人的道理
+
+122
+00:27:14,239 --> 00:27:18,710
+任何一個人有了這個道理
+
+123
+00:27:18,759 --> 00:27:25,358
+才可以免去諸般痛苦
+好好的安居樂業
+
+124
+00:27:25,399 --> 00:27:29,950
+實實在在的過日子
+
+125
+00:27:34,680 --> 00:27:36,352
+反過來說
+
+126
+00:27:36,399 --> 00:27:40,108
+要是做人不曉得這個道理
+
+127
+00:27:40,159 --> 00:27:46,394
+就跟沉陷在苦海裡頭一樣
+一生一世
+
+128
+00:27:46,439 --> 00:27:52,628
+甚至於子孫孫,都得不到幸福
+
+129
+00:27:52,679 --> 00:27:55,671
+我為什麼要去取經
+
+130
+00:27:55,719 --> 00:28:01,316
+就是因為現在的人都陷在苦海裡了
+
+131
+00:28:01,359 --> 00:28:04,192
+要想成就這此些人
+
+132
+00:28:04,239 --> 00:28:12,510
+所以在大唐皇帝面前討下這
+重大繁難的差事
+
+133
+00:28:15,679 --> 00:28:17,829
+芭蕉扇借到了沒有
+
+134
+00:28:17,879 --> 00:28:19,517
+借來了
+
+135
+00:28:19,559 --> 00:28:22,790
+是不是這個
+
+136
+00:28:22,839 --> 00:28:27,993
+諸位施主,現在扇子既然借到了
+
+137
+00:28:28,039 --> 00:28:32,157
+貧僧師徒就要告辭了
+
+138
+00:28:32,199 --> 00:28:34,040
+慢一點
+
+139
+00:28:34,040 --> 00:28:39,797
+諸位,我想留聖僧在這兒多住幾天
+
+140
+00:28:39,839 --> 00:28:41,352
+好不好啊
+
+141
+00:28:41,399 --> 00:28:43,469
+好的,好的
+
+142
+00:28:43,519 --> 00:28:45,908
+謝謝諸位的好意
+
+143
+00:28:45,959 --> 00:28:51,795
+我早走一步就是早一步完成
+我們的任務
+
+144
+00:28:51,839 --> 00:28:56,196
+那麼就請令高徒先到火焰山
+
+145
+00:28:56,239 --> 00:29:02,155
+扇滅了火之後,再陪聖僧同行
+
+146
+00:29:02,199 --> 00:29:05,475
+好,你就去吧
+
+147
+00:30:24,479 --> 00:30:30,039
+鐵扇公主真可惡,拿假的芭蕉扇
+來騙我
+
+148
+00:30:30,039 --> 00:30:32,792
+我非殺了她不可
+
+149
+00:30:32,839 --> 00:30:36,309
+不,殺了她也是枉然
+
+150
+00:30:36,359 --> 00:30:39,590
+我素來不願意你多殺人
+
+151
+00:30:39,639 --> 00:30:42,995
+我們再想辦法
+
+152
+00:30:52,159 --> 00:30:56,232
+師兄,怎麼你也會上她的當
+
+153
+00:30:56,279 --> 00:30:58,554
+費了這麼許多的力氣
+
+154
+00:30:58,599 --> 00:31:02,114
+卻弄了一把假的扇子來
+
+155
+00:31:02,159 --> 00:31:06,516
+笑話,笑話
+
+156
+00:31:08,919 --> 00:31:10,432
+那麼你去
+
+157
+00:31:10,479 --> 00:31:14,392
+好好,我去我去,我就去
+
+158
+00:31:14,439 --> 00:31:17,033
+我去找牛魔王
+
+159
+00:31:17,119 --> 00:31:19,952
+這倒是一個好辦法
+
+160
+00:31:21,399 --> 00:31:24,550
+師兄,你看好不好
+
+161
+00:31:24,599 --> 00:31:27,397
+好,看你的了
+
+162
+00:33:07,199 --> 00:33:11,159
+你看我今天化妝得好嗎
+
+163
+00:33:11,159 --> 00:33:13,798
+好極了,我的小寶貝
+
+164
+00:33:13,839 --> 00:33:17,070
+你陪我到洞外頭去走走,好不好
+
+165
+00:33:17,119 --> 00:33:21,556
+我的寶貝,還是你一個人去吧
+
+166
+00:33:21,599 --> 00:33:24,830
+本來嘛,我們這種草婆子
+
+167
+00:33:24,879 --> 00:33:28,030
+跟你出去了會使你丟臉的
+
+168
+00:33:28,079 --> 00:33:32,039
+小寶貝,這是什麼話呢
+
+169
+00:33:32,039 --> 00:33:37,511
+你先去,我隨後就來好不好
+
+170
+00:35:28,039 --> 00:35:35,673
+女菩薩,你真是天仙下凡
+
+171
+00:35:35,719 --> 00:35:37,914
+你…你是什麼人
+
+172
+00:35:37,959 --> 00:35:41,474
+我是從芭蕉洞來找牛魔王的
+
+173
+00:35:41,520 --> 00:35:43,988
+快放手
+
+174
+00:35:49,559 --> 00:35:52,949
+女菩薩,你慢點走
+
+175
+00:36:44,239 --> 00:36:49,233
+小寶貝,誰來欺負你
+
+176
+00:36:49,279 --> 00:36:50,837
+是你
+
+177
+00:36:50,879 --> 00:36:54,349
+我哪裡捨得欺負你呢
+
+178
+00:36:56,919 --> 00:36:59,274
+你還是回芭蕉洞去吧
+
+179
+00:36:59,320 --> 00:37:01,709
+省得那個不要臉的東西
+
+180
+00:37:01,759 --> 00:37:07,675
+時常派人來請你,欺負我
+
+181
+00:37:07,719 --> 00:37:11,075
+你說有人來找我
+
+182
+00:37:11,119 --> 00:37:15,078
+外邊有一個豬臉的和尚來請你
+
+183
+00:37:15,120 --> 00:37:18,510
+差一點把我嚇死了
+
+184
+00:37:18,559 --> 00:37:22,757
+真有這回事嗎?待我出去看一看
+
+185
+00:37:50,679 --> 00:37:53,796
+牛大哥
+
+186
+00:37:53,839 --> 00:37:58,151
+這裡頭有個頂漂亮的小娘們
+
+187
+00:37:58,200 --> 00:38:03,991
+呸,那是我的女人,你為什麼要欺負她
+
+188
+00:38:04,039 --> 00:38:08,559
+大哥,我不知那就是二嫂,請原瓊
+
+189
+00:38:08,559 --> 00:38:11,949
+不知道不見罪,好啊,你走啊
+
+190
+00:38:11,999 --> 00:38:16,117
+不不不,我還有事情請大哥幫忙
+
+191
+00:38:18,479 --> 00:38:24,719
+小弟保唐僧取經,路過火焰山
+
+192
+00:38:24,719 --> 00:38:27,313
+請大哥跟嫂子說一聲
+
+193
+00:38:27,359 --> 00:38:30,829
+把這個芭蕉扇借來用一用
+
+194
+00:38:30,880 --> 00:38:33,519
+不成,那唐僧和孫悟空
+
+195
+00:38:33,519 --> 00:38:35,191
+是我孩子的仇人
+
+196
+00:38:35,239 --> 00:38:38,754
+我正要抓他們報仇
+
+197
+00:38:38,799 --> 00:38:44,988
+令郎已成正果,請大哥不必再計較吧
+
+198
+00:38:45,039 --> 00:38:48,952
+好,看在我們從前的交情
+我不跟你計較
+
+199
+00:38:49,000 --> 00:38:51,719
+那麼去吧
+
+200
+00:39:38,399 --> 00:39:44,190
+寶貝,那個豬臉和尚
+是我從前一個朋友
+
+201
+00:39:44,239 --> 00:39:46,514
+並不是芭蕉洞派來的
+
+202
+00:39:46,559 --> 00:39:47,753
+我不相信
+
+203
+00:39:47,799 --> 00:39:50,950
+我不騙你
+
+204
+00:39:50,999 --> 00:39:54,036
+現在那個和尚到哪兒去了呢
+
+205
+00:39:54,119 --> 00:39:57,794
+已經被我打走了
+
+206
+00:43:58,639 --> 00:44:01,358
+大王回來了
+
+207
+00:44:01,399 --> 00:44:02,388
+奶奶呢
+
+208
+00:44:02,439 --> 00:44:04,794
+在裡邊
+
+209
+00:44:42,999 --> 00:44:48,232
+今天是什麼風會把大王吹到這兒來的
+
+210
+00:44:48,279 --> 00:44:52,272
+聽到孫悟空保唐僧快到這兒
+
+211
+00:44:52,320 --> 00:44:56,916
+恐怕他要來借芭蕉扇過火焰山
+
+212
+00:44:56,959 --> 00:45:00,872
+那猴子是害我們兒子的仇人
+
+213
+00:45:00,919 --> 00:45:08,507
+早晚來了抓著他,讓我們夫妻出出恨
+
+214
+00:45:08,559 --> 00:45:12,711
+夫人,你為什麼哭
+
+215
+00:45:12,759 --> 00:45:15,717
+那猴子已經來過了
+
+216
+00:45:15,759 --> 00:45:18,876
+是我不肯把扇子借給他
+
+217
+00:45:18,919 --> 00:45:22,275
+不知道怎麼會跑到我的肚子裡來
+
+218
+00:45:22,319 --> 00:45:25,516
+弄得我肚子痛得要命
+
+219
+00:45:25,559 --> 00:45:31,399
+後來我沒有法子,只好把扇子借給他
+
+220
+00:45:31,399 --> 00:45:38,271
+可惜可惜,你怎麼把扇子借給他
+
+221
+00:45:38,320 --> 00:45:40,470
+拿去的是假的
+
+222
+00:45:40,519 --> 00:45:43,033
+假的
+
+223
+00:46:14,199 --> 00:46:19,876
+開筵慶祝大王歸
+
+224
+00:46:19,919 --> 00:46:25,630
+好酒殷勤勸幾杯
+
+225
+00:46:25,679 --> 00:46:34,189
+雞又香,鴨又美,豬又肥
+
+226
+00:46:34,240 --> 00:46:45,674
+我盡量的歌,我盡量的舞
+
+227
+00:46:45,719 --> 00:46:54,514
+你也要盡量的醉
+
+228
+00:47:03,599 --> 00:47:16,399
+大王啊,你把舊人丟
+
+229
+00:47:16,439 --> 00:47:22,628
+你愛新人媚
+
+230
+00:47:22,679 --> 00:47:36,673
+為你淌了多少相思淚
+
+231
+00:47:46,719 --> 00:47:55,718
+等一會燈兒吹帳兒垂
+
+232
+00:47:55,759 --> 00:48:00,879
+你獨自兒睡
+
+233
+00:48:00,879 --> 00:48:05,519
+也嘗嘗這個淒涼味
+
+234
+00:48:05,519 --> 00:48:13,437
+恕我不奉陪
+
+235
+00:48:18,559 --> 00:48:24,634
+就是同床
+
+236
+00:48:24,679 --> 00:48:34,350
+我們各人蓋著各人的被
+
+237
+00:48:38,399 --> 00:48:42,392
+大王,我醉了
+
+238
+00:48:55,079 --> 00:48:58,151
+夫人,那真扇子你放在什麼地方
+
+239
+00:48:58,199 --> 00:49:05,469
+那猴子花樣很多,而且那豬八戒
+本事更大
+
+240
+00:49:05,519 --> 00:49:09,797
+當心給他們騙了去
+
+241
+00:49:18,360 --> 00:49:21,989
+寶貝不是在這兒嗎
+
+242
+00:49:31,439 --> 00:49:39,319
+大王,你出神想什麼呢?
+還是收了吧
+
+243
+00:49:39,319 --> 00:49:43,551
+小寶貝
+
+244
+00:49:43,599 --> 00:49:49,037
+寶貝,你多喝一杯,你喝啊
+
+245
+00:49:53,919 --> 00:49:59,519
+今兒晚上,金龍大王
+還要請我去喝酒呢
+
+246
+00:49:59,519 --> 00:50:01,430
+那你就該去了
+
+247
+00:50:01,479 --> 00:50:02,878
+是的
+
+248
+00:50:02,919 --> 00:50:06,628
+你去替爺爺把金睛獸牽出去預備好
+
+249
+00:50:06,679 --> 00:50:08,271
+是
+
+250
+00:50:08,320 --> 00:50:12,598
+可是,你今兒個晚上去要少喝一點兒
+
+251
+00:50:12,639 --> 00:50:15,756
+免得回來睡著叫不醒你
+
+252
+00:50:15,800 --> 00:50:19,110
+不好了,爺爺那個金隋獸不見了
+
+253
+00:50:19,159 --> 00:50:20,911
+你們全都是死人嗎
+
+254
+00:50:20,959 --> 00:50:24,039
+家裡頭的東西怎麼會不見了呢
+
+255
+00:50:24,039 --> 00:50:27,918
+寶貝,不要管他們吧
+
+256
+00:50:27,960 --> 00:50:31,714
+恐怕是那豬八戒偷了去了
+
+257
+00:50:31,759 --> 00:50:35,274
+說不定我要到芭蕉洞去一趟
+
+258
+00:50:35,320 --> 00:50:39,313
+原來是你們做好了的圈套
+
+259
+00:50:42,280 --> 00:50:48,150
+你還是要到那個不要臉的女人那兒去
+
+260
+00:50:48,199 --> 00:50:50,713
+好寶貝,你不要哭了
+
+261
+00:50:50,759 --> 00:50:54,069
+我去去就來的
+
+262
+00:51:02,679 --> 00:51:07,309
+來來,喝喝
+
+263
+00:51:10,359 --> 00:51:12,475
+我現在放心了
+
+264
+00:51:12,519 --> 00:51:16,717
+不怕他們偷我們的寶貝
+
+265
+00:51:16,759 --> 00:51:21,310
+他們就是偷了去
+不知道把那絲線一拉
+
+266
+00:51:21,360 --> 00:51:26,275
+單是一顆珠子也沒有用處啊
+
+267
+00:51:26,319 --> 00:51:31,791
+是不是那麼一拉就變成扇子
+
+268
+00:51:35,120 --> 00:51:38,078
+大王,你今天喝醉了
+
+269
+00:51:38,119 --> 00:51:44,035
+自己的寶貝都忘了,還來問我
+
+270
+00:51:49,999 --> 00:51:53,708
+娘子,你看看我是誰
+
+271
+00:52:00,320 --> 00:52:03,756
+你是什麼人
+
+272
+00:52:03,799 --> 00:52:09,908
+我是唐僧的二徒弟,豬八戒
+
+273
+00:52:09,959 --> 00:52:14,794
+對不住,謝謝你,打擾了
+
+274
+00:52:19,080 --> 00:52:21,719
+再見
+
+275
+00:53:06,839 --> 00:53:10,718
+牛大嫂太風騷
+
+276
+00:53:10,760 --> 00:53:14,719
+眾小妖都俊俏
+
+277
+00:53:14,759 --> 00:53:24,828
+老豬真有點受不了
+
+278
+00:53:24,879 --> 00:53:28,872
+心機巧,手段妙
+
+279
+00:53:28,919 --> 00:53:32,832
+居然騙得了無價寶
+
+280
+00:53:32,880 --> 00:53:36,793
+這一番勞苦功高
+
+281
+00:53:36,839 --> 00:53:38,318
+沙僧該拜倒
+
+282
+00:53:38,359 --> 00:53:40,748
+猴兒該領教
+
+283
+00:53:40,799 --> 00:53:45,236
+師父也要嚇一跳
+
+284
+00:53:45,280 --> 00:53:49,193
+我老豬也有今朝
+
+285
+00:53:49,239 --> 00:53:54,359
+我老豬也有今朝
+
+286
+00:54:36,720 --> 00:54:40,474
+呆子,事情辦得怎麼樣了
+
+287
+00:54:40,519 --> 00:54:42,828
+不僅扇子到手
+
+288
+00:54:42,880 --> 00:54:48,796
+鐵扇公主並且還做了我
+半天的老婆
+
+289
+00:54:48,839 --> 00:54:51,717
+這倒便宜了你了
+
+290
+00:54:58,159 --> 00:55:01,595
+扇子拿來給我看看
+
+291
+00:55:16,039 --> 00:55:20,237
+你怎麼會把它縮小了的呀
+
+292
+00:55:40,559 --> 00:55:45,349
+老豬,你可認識我嗎
+
+293
+00:55:45,399 --> 00:55:49,187
+你不要跟我開玩笑了
+
+294
+00:55:49,239 --> 00:55:52,151
+誰跟你開玩笑
+
+295
+00:56:42,879 --> 00:56:45,393
+呆子,你去了怎麼樣
+
+296
+00:56:45,439 --> 00:56:47,111
+白跑了一趟
+
+297
+00:56:47,159 --> 00:56:49,992
+悟能,扇子借來沒有
+
+298
+00:56:50,039 --> 00:56:53,349
+我去找牛魔王,他不肯借
+
+299
+00:56:53,400 --> 00:56:59,191
+後來,我又變成老牛的樣子
+
+300
+00:56:59,239 --> 00:57:03,551
+在鐵扇公主那兒把扇子已經騙過來了
+
+301
+00:57:03,599 --> 00:57:10,599
+誰知道他又變成你的樣子又給他騙回去了
+
+302
+00:57:10,599 --> 00:57:12,749
+老牛的本領大
+
+303
+00:57:12,800 --> 00:57:16,156
+我還被他揍了一頓呢
+
+304
+00:57:16,199 --> 00:57:21,398
+呆子,你能辦這樣大的事那
+還算是呆子嗎
+
+305
+00:57:21,439 --> 00:57:25,671
+事情不都環在你頭上
+
+306
+00:57:30,759 --> 00:57:34,388
+你們不要吵了,趕緊再想辦法
+
+307
+00:57:34,439 --> 00:57:40,275
+哪一方…沒…沒有火啊
+
+308
+00:57:40,320 --> 00:57:47,078
+東南西北,只有西方有火
+
+309
+00:57:47,120 --> 00:57:50,749
+那我們不是要走回去了嗎
+
+310
+00:57:50,799 --> 00:57:52,949
+這路不通,不回去怎麼樣呢
+
+311
+00:57:52,999 --> 00:57:55,229
+八戒,你不要這樣說
+
+312
+00:57:55,279 --> 00:57:59,158
+要成功一件事情總是有阻礙的
+
+313
+00:57:59,199 --> 00:58:04,557
+我們要做這樣神聖的事情
+就要堅定我們的信念
+
+314
+00:58:04,599 --> 00:58:09,229
+不能因為有一點兒困難
+就中適改變我們的宗旨
+
+315
+00:58:09,280 --> 00:58:14,593
+你們這次失敗的原因是由於
+既不同心又不合力
+
+316
+00:58:14,639 --> 00:58:17,153
+假使你們三個人一條心
+
+317
+00:58:17,199 --> 00:58:20,509
+合起力量,共同跟牛魔王決鬥
+
+318
+00:58:20,559 --> 00:58:22,868
+事情一定可以成功的
+
+319
+00:58:22,919 --> 00:58:26,039
+我們謹遵師父的命令
+
+320
+00:58:26,039 --> 00:58:30,157
+去跟牛魔王爭一個誰勝誰敗
+
+321
+00:58:30,199 --> 00:58:34,272
+誰…誰…誰勝誰敗
+
+322
+00:58:34,320 --> 00:58:37,710
+那就好極了
+
+323
+00:58:37,759 --> 00:58:40,990
+各位受他的害處也不小了
+
+324
+00:58:41,040 --> 00:58:43,879
+希望各位也出此些力量
+
+325
+00:58:43,879 --> 00:58:49,590
+跟小徒們共同征服牛魔王,消滅火焰山
+
+326
+00:58:49,639 --> 00:58:53,837
+免除永遠的禍害
+
+327
+00:58:53,879 --> 00:58:57,508
+我們聽從師父的命令,為大家謀幸福
+
+328
+00:58:57,559 --> 00:58:58,878
+大家一起出力去
+
+329
+00:58:58,919 --> 00:59:01,035
+好
+
+330
+01:08:23,239 --> 01:08:25,628
+奶奶,不好了
+
+331
+01:08:25,679 --> 01:08:30,799
+爺爺給人家抓住了,你快點去看看吧
+
+332
+01:08:54,479 --> 01:08:56,709
+還不過來打,過來打
+
+333
+01:08:56,760 --> 01:08:59,718
+慢一點,慢一點
+
+334
+01:08:59,760 --> 01:09:05,790
+孽畜,只要你把扇子交出來,饒你不死
+
+335
+01:09:05,840 --> 01:09:12,757
+老牛,扇子在什麼地方?快拿出來啊
+
+336
+01:09:12,799 --> 01:09:19,352
+在我老…老婆那兒
+
+337
+01:09:25,240 --> 01:09:27,993
+夫人,夫人,夫人
+
+338
+01:09:28,039 --> 01:09:32,271
+你快點來救救我
+
+339
+01:09:32,320 --> 01:09:35,118
+把扇子拿出來吧
+
+340
+01:09:35,159 --> 01:09:39,630
+大王,好,好的
+
+341
+01:09:43,400 --> 01:09:47,234
+悟空,你再去一趟吧
+
diff --git a/js2/mwEmbed/example_usage/media/princess_archive_org/princess_iron_fan.srt b/js2/mwEmbed/example_usage/media/princess_archive_org/princess_iron_fan.srt
new file mode 100644 (file)
index 0000000..0852d36
--- /dev/null
@@ -0,0 +1,1396 @@
+1
+00:00:01,080 --> 00:00:09,070
+Princess Iron Fan
+
+2
+00:02:03,109 --> 00:02:09,280
+Journey to the West is a wonderful children's story,
+
+3
+00:02:09,280 --> 00:02:15,280
+but the world often misunderstands it as a fantasy novel.
+
+4
+00:02:15,280 --> 00:02:19,240
+This film was made for the purpose of
+
+5
+00:02:19,240 --> 00:02:24,240
+training the hearts and minds of children.
+
+6
+00:02:24,240 --> 00:02:29,280
+The story is pure, untainted by fantasy.
+
+7
+00:02:29,280 --> 00:02:32,560
+Fiery Mountain blocking the path of Tang Seng's company
+
+8
+00:02:32,560 --> 00:02:41,039
+is a metaphor for the difficulties in life.
+
+9
+00:02:41,039 --> 00:02:46,439
+In order to overcome them, one must keep faith.
+Everybody must work together
+
+10
+00:02:46,439 --> 00:02:52,430
+in order to obtain the palm leaf fan and put out the flames.
+
+11
+00:02:52,839 --> 00:02:58,178
+Tripikata True Sutra
+
+12
+00:03:34,479 --> 00:03:37,789
+It's already autumn, how can it still be so warm?
+
+13
+00:03:37,840 --> 00:03:42,349
+Fool, don't talk rubbish. We should hurry and get on our way.
+
+14
+00:04:06,919 --> 00:04:09,349
+Wukong, where is this place?
+
+15
+00:04:09,400 --> 00:04:13,669
+We must pass through here to continue westwards, that much is certain.
+
+16
+00:04:13,719 --> 00:04:18,110
+Might we have taken the wrong path?
+
+17
+00:04:18,149 --> 00:04:21,700
+Why is it so hot here?
+
+18
+00:04:30,029 --> 00:04:31,649
+Master, look!
+
+19
+00:04:31,650 --> 00:04:33,779
+Isn't that a house up ahead?
+
+20
+00:04:33,829 --> 00:04:38,100
+Let's go in and rest for a while, OK?
+
+21
+00:04:59,389 --> 00:05:02,899
+This place is called Fiery Mountain.
+
+22
+00:05:02,949 --> 00:05:06,019
+The fire stretches for hundreds of miles.
+
+23
+00:05:06,069 --> 00:05:08,740
+Not single straw of grass can grow here.
+
+24
+00:05:08,790 --> 00:05:11,620
+The four seasons of the year are all warm.
+
+25
+00:05:11,680 --> 00:05:19,629
+You couldn't pass through the mountain even with a head of copper and arms of iron.
+
+26
+00:05:19,670 --> 00:05:23,579
+What kind of place is this? Master, don't worry!
+
+27
+00:05:23,629 --> 00:05:27,139
+The three of us are all strong enough to pass!
+
+28
+00:05:27,189 --> 00:05:30,699
+Master, I'll go and have a look!
+
+29
+00:08:06,310 --> 00:08:09,579
+Wukong, what was it like?
+
+30
+00:08:09,629 --> 00:08:11,819
+Bad, bad, very bad.
+
+31
+00:08:11,879 --> 00:08:15,910
+If I were any slower the fur on my tail would have been burned off.
+
+32
+00:08:42,720 --> 00:08:47,600
+Noble host, the fires here are so big.
+
+33
+00:08:47,600 --> 00:08:49,669
+How can you grow any crops?
+
+34
+00:08:49,710 --> 00:08:53,980
+A thousand miles from here lives Princess Iron Fan.
+
+35
+00:08:54,039 --> 00:08:56,500
+She has a palm leaf fan.
+
+36
+00:08:56,559 --> 00:08:59,070
+Wave the fan once and the fire goes out.
+
+37
+00:08:59,120 --> 00:09:01,629
+Twice and the wind starts blowing.
+
+38
+00:09:01,679 --> 00:09:03,980
+Three times and the rain starts coming down.
+
+39
+00:09:04,039 --> 00:09:07,509
+In the following period we plant and harvest.
+
+40
+00:09:07,559 --> 00:09:11,340
+However, asking that princess to come
+
+41
+00:09:11,399 --> 00:09:14,870
+is certainly no simple matter.
+
+42
+00:09:14,909 --> 00:09:16,820
+Where does she live?
+
+43
+00:09:16,879 --> 00:09:20,190
+She lives in Palm Leaf Cave at Emerald Cloud Mountain.
+
+44
+00:09:20,240 --> 00:09:23,669
+Does she live there alone?
+
+45
+00:09:23,720 --> 00:09:25,750
+Doesn't she have a husband?
+
+46
+00:09:25,799 --> 00:09:29,580
+Her husband is Bull Demon King.
+
+47
+00:09:29,639 --> 00:09:32,200
+What, her husband is Old Bull?
+
+48
+00:09:32,240 --> 00:09:36,789
+Fool, you know him? Come with me to borrow the fan!
+
+49
+00:09:36,840 --> 00:09:41,750
+Actually... Old Bull doesn't live there.
+
+50
+00:09:41,799 --> 00:09:46,350
+Looking for his woman when he isn't home
+
+51
+00:09:46,399 --> 00:09:51,519
+isn't very... appropriate.
+
+52
+00:09:51,559 --> 00:09:58,309
+You... you... the two of you go.
+
+53
+00:09:58,360 --> 00:10:04,290
+I... I'll stay here and serve Master.
+
+54
+00:10:04,440 --> 00:10:11,269
+Sha Wujing, go with your two fellow apprentices.
+
+55
+00:10:38,571 --> 00:10:44,978
+Palm Leaf Cave
+
+56
+00:10:47,200 --> 00:10:51,549
+Fool, I always go first.
+
+57
+00:10:51,600 --> 00:10:54,350
+This time it's your turn!
+
+58
+00:10:58,519 --> 00:11:04,909
+Junior! I always go first, this time it's your turn!
+
+59
+00:11:04,960 --> 00:11:06,830
+Senior...
+
+60
+00:11:06,879 --> 00:11:10,990
+I'm asking you to make a small effort for Master. Can't you do that?
+
+61
+00:11:11,039 --> 00:11:14,309
+Hurry up!
+
+62
+00:11:39,639 --> 00:11:43,039
+Simple monk, where did you come from?
+
+63
+00:11:43,039 --> 00:11:49,870
+The Great Sage... Tang Seng... wants your princess...
+
+64
+00:11:49,919 --> 00:11:52,480
+Nonsense!
+
+65
+00:12:47,549 --> 00:12:52,059
+Senior... why don't you go instead?
+
+66
+00:12:52,120 --> 00:12:56,950
+Fool, you go!
+
+67
+00:12:57,000 --> 00:13:00,700
+Senior, why don't you go?
+
+68
+00:13:04,029 --> 00:13:07,460
+Lazy fool!
+
+69
+00:13:54,279 --> 00:13:57,899
+Great God of Thunder! Don't kill me, let me go!
+
+70
+00:13:57,960 --> 00:13:59,950
+Go tell your princess
+
+71
+00:14:00,000 --> 00:14:03,279
+that Sun Wukong has come to borrow the fan.
+
+72
+00:14:03,279 --> 00:14:08,399
+Yes, yes! Let me loose, I'll go at once.
+
+73
+00:14:29,559 --> 00:14:37,059
+Grandma, there's a Sun Wukong outside asking to borrow the fan.
+
+74
+00:14:41,519 --> 00:14:44,149
+Quickly fetch my sword.
+
+75
+00:15:01,639 --> 00:15:04,149
+Sun Wukong, you hurt my son!
+
+76
+00:15:04,200 --> 00:15:08,549
+You dare come here to meet your death?
+
+77
+00:15:08,600 --> 00:15:12,039
+I've never met you before, how could I have harmed your son?
+
+78
+00:15:12,039 --> 00:15:15,789
+My son Red Child's life was ruined, wasn't that your doing?
+
+79
+00:15:15,840 --> 00:15:20,389
+Your son is with the Goddess of Mercy now, how can you say that I hurt him?
+
+80
+00:15:20,440 --> 00:15:23,750
+Enough rubbish! Come here and let me chop you with my sword.
+
+81
+00:15:23,799 --> 00:15:26,149
+If you can take it I'll lend you the fan.
+
+82
+00:15:26,200 --> 00:15:28,549
+Really?
+
+83
+00:15:56,799 --> 00:16:00,629
+Stop! Quickly give me the fan!
+
+84
+00:17:53,630 --> 00:18:00,099
+Great Sage, weren't you going west? Why have you come back here?
+
+85
+00:18:11,150 --> 00:18:17,140
+Princess Iron Fan blew me here with a single wave of her fan.
+
+86
+00:18:17,190 --> 00:18:23,859
+That's truly amazing, Great Sage. I have something for you.
+
+87
+00:18:28,509 --> 00:18:33,450
+This is a wind pearl. When you use it,
+
+88
+00:18:33,509 --> 00:18:36,140
+your heart will become steady as a rock.
+
+89
+00:18:36,190 --> 00:18:39,180
+Princess Iron Fan won't be able to move you.
+
+90
+00:18:39,230 --> 00:18:42,849
+Great Sage, come and have a look.
+
+91
+00:19:00,430 --> 00:19:02,539
+Thank you.
+
+92
+00:19:06,069 --> 00:19:12,299
+Senior... where...
+
+93
+00:19:12,349 --> 00:19:18,690
+where has he... been blown to?
+
+94
+00:19:18,750 --> 00:19:26,099
+Who cares about him? Let the monkey handle himself. Let's go.
+
+95
+00:19:35,190 --> 00:19:37,259
+Senior... senior...
+
+96
+00:19:37,309 --> 00:19:43,470
+You... you...
+
+97
+00:19:43,470 --> 00:19:50,220
+Where were you blown to by that old lady?
+
+98
+00:19:50,269 --> 00:19:57,180
+Fool, now it's definitely your turn to go.
+
+99
+00:19:57,230 --> 00:20:00,930
+I'm not going, a single wave of her fan
+
+100
+00:20:00,990 --> 00:20:03,450
+could blow me to some faraway land.
+
+101
+00:20:03,509 --> 00:20:09,710
+Maybe it's better if you go again.
+
+102
+00:20:09,710 --> 00:20:12,220
+I won't go.
+
+103
+00:20:17,789 --> 00:20:22,779
+Next time I won't let you off!
+
+104
+00:20:56,150 --> 00:21:00,140
+This time I won't move no matter how much you wave,
+
+105
+00:21:00,190 --> 00:21:05,210
+as sure as I call myself am a man!
+
+106
+00:21:33,670 --> 00:21:38,579
+Senior, how come this time her fan couldn't move you?
+
+107
+00:21:46,829 --> 00:21:50,099
+Let's break our way in.
+
+108
+00:23:59,630 --> 00:24:04,180
+Quickly bring out the fan for Sun Wukong!
+
+109
+00:24:14,869 --> 00:24:16,900
+Sun Wukong, where are you?
+
+110
+00:24:16,950 --> 00:24:19,980
+I'm in your stomach!
+
+111
+00:24:45,750 --> 00:24:48,539
+Sun Wukong, spare me!
+
+112
+00:24:48,589 --> 00:24:51,180
+Only if you give me the fan!
+
+113
+00:24:51,230 --> 00:24:56,539
+I promise, I'll give it to you. Please come out!
+
+114
+00:25:00,230 --> 00:25:02,819
+Hurry up and bring the fan.
+
+115
+00:25:07,430 --> 00:25:09,220
+We've brought out the fan.
+
+116
+00:25:09,279 --> 00:25:12,069
+Why haven't you come out?
+
+117
+00:25:12,109 --> 00:25:16,619
+Open your mouth and I'll come out.
+
+118
+00:25:25,349 --> 00:25:29,420
+Sun Wukong, why haven't you come out?
+
+119
+00:25:50,349 --> 00:25:55,579
+Here I am. Lend me the fan for a while, I'll return it.
+
+120
+00:26:32,549 --> 00:26:36,579
+Master has been waiting long enough, let's get going!
+
+121
+00:27:01,869 --> 00:27:04,900
+Scripture, what is scripture?
+
+122
+00:27:04,950 --> 00:27:10,029
+Scriptures are the principles that link heaven and earth.
+
+123
+00:27:10,029 --> 00:27:14,180
+They are the principles of man.
+
+124
+00:27:14,230 --> 00:27:18,700
+Only he who holds these principles
+
+125
+00:27:18,750 --> 00:27:25,339
+can rid himself of pain and live a good life,
+
+126
+00:27:25,390 --> 00:27:29,940
+live a true and honest life.
+
+127
+00:27:34,680 --> 00:27:36,349
+Conversely,
+
+128
+00:27:36,390 --> 00:27:40,089
+he who does not know these principles,
+
+129
+00:27:40,150 --> 00:27:46,380
+will live a life full of misery.
+
+130
+00:27:46,430 --> 00:27:52,609
+Even his son or grandson will not achieve happiness.
+
+131
+00:27:52,670 --> 00:27:55,660
+Why am I going to get the scripture?
+
+132
+00:27:55,710 --> 00:28:01,299
+Because men nowadays are trapped in misery.
+
+133
+00:28:01,349 --> 00:28:04,180
+In order to achieve this goal, we are going to
+
+134
+00:28:04,230 --> 00:28:12,500
+appear before the Tang emperor and discuss this very complicated matter.
+
+135
+00:28:15,670 --> 00:28:17,819
+Did you get the palm leaf fan?
+
+136
+00:28:17,869 --> 00:28:19,400
+We have it.
+
+137
+00:28:19,401 --> 00:28:20,779
+Is this it?
+
+138
+00:28:22,829 --> 00:28:27,980
+Noble hosts, now that we have the fan,
+
+139
+00:28:28,029 --> 00:28:32,140
+we will take our leave.
+
+140
+00:28:32,190 --> 00:28:34,039
+Hold on.
+
+141
+00:28:34,039 --> 00:28:39,789
+Everyone, I would like to ask Sage Seng to stay here for a few more days.
+
+142
+00:28:39,829 --> 00:28:41,339
+Do you agree?
+
+143
+00:28:41,390 --> 00:28:43,460
+Agreed!
+
+144
+00:28:43,509 --> 00:28:45,890
+Thank you for your kindness.
+
+145
+00:28:45,950 --> 00:28:51,779
+But the sooner I leave the sooner we can complete our task.
+
+146
+00:28:51,829 --> 00:28:56,180
+Very well, will the honorable apprentice first go to Fiery Mountain.
+
+147
+00:28:56,230 --> 00:29:02,140
+After extinguishing the flames, continue to follow Sage Seng.
+
+148
+00:29:02,190 --> 00:29:05,460
+All right, go ahead!
+
+149
+00:30:24,470 --> 00:30:30,029
+Princess Iron Fan is really despicable, she gave us a fake fan!
+
+150
+00:30:30,029 --> 00:30:32,779
+I'll kill her for sure!
+
+151
+00:30:32,829 --> 00:30:36,299
+No, killing her is the wrong thing to do.
+
+152
+00:30:36,349 --> 00:30:39,579
+I won't let you kill anyone.
+
+153
+00:30:39,630 --> 00:30:42,980
+Let's think of something else.
+
+154
+00:30:52,150 --> 00:30:56,220
+Senior, how could you be fooled by her?
+
+155
+00:30:56,269 --> 00:30:58,539
+After making such an effort
+
+156
+00:30:58,589 --> 00:31:02,099
+all we got was a fake fan.
+
+157
+00:31:02,150 --> 00:31:06,500
+Ridiculous, ridiculous.
+
+158
+00:31:08,910 --> 00:31:10,420
+Then you go!
+
+159
+00:31:10,470 --> 00:31:14,380
+OK, I'll go, I'll go, I'm going!
+
+160
+00:31:14,430 --> 00:31:16,908
+I'll go find Bull Demon King.
+
+161
+00:31:16,909 --> 00:31:19,940
+This is a good solution.
+
+162
+00:31:21,390 --> 00:31:24,439
+Partner, what do you think?
+
+163
+00:31:24,440 --> 00:31:27,380
+We'll see how you do.
+
+164
+00:33:07,190 --> 00:33:11,150
+What do you think, am I pretty today?
+
+165
+00:33:11,150 --> 00:33:13,779
+Beautiful, my baby.
+
+166
+00:33:13,829 --> 00:33:17,059
+Accompany me for a walk outside the cave, all right?
+
+167
+00:33:17,109 --> 00:33:21,539
+My baby, why don't you go by yourself.
+
+168
+00:33:21,589 --> 00:33:24,819
+Why of course, I'm just a plain country girl.
+
+169
+00:33:24,869 --> 00:33:28,019
+Taking me outside might cause you to lose face.
+
+170
+00:33:28,069 --> 00:33:32,029
+Baby, what are you saying?
+
+171
+00:33:32,029 --> 00:33:37,500
+You go ahead, I'll come out in a while, all right?
+
+172
+00:33:39,852 --> 00:33:44,557
+Emerald Cloud Cave
+
+173
+00:35:28,030 --> 00:35:35,659
+Goddess, you're truly an angel come down from heaven.
+
+174
+00:35:35,710 --> 00:35:37,900
+Who... who are you?
+
+175
+00:35:37,949 --> 00:35:41,460
+I've come from Palm Leaf Cave to look for Bull Demon King.
+
+176
+00:35:41,519 --> 00:35:43,980
+Let go of me!
+
+177
+00:35:49,550 --> 00:35:52,940
+Goddess, slow down!
+
+178
+00:36:38,768 --> 00:36:40,133
+Emerald Cloud Cave
+
+179
+00:36:44,230 --> 00:36:49,219
+Baby, who has bullied you?
+
+180
+00:36:49,269 --> 00:36:50,820
+You!
+
+181
+00:36:50,869 --> 00:36:54,340
+How could I bully you?
+
+182
+00:36:56,909 --> 00:36:59,260
+Why don't you go back to Palm Leaf Cave?
+
+183
+00:36:59,320 --> 00:37:01,699
+It would spare you some embarrassment.
+
+184
+00:37:01,750 --> 00:37:07,659
+They often send people to look for you, and bully me.
+
+185
+00:37:07,710 --> 00:37:11,059
+Has there been someone here to look for me?
+
+186
+00:37:11,110 --> 00:37:15,059
+There's a pig monk outside looking for you.
+
+187
+00:37:15,119 --> 00:37:18,510
+He almost scared me to death.
+
+188
+00:37:18,550 --> 00:37:22,739
+How can this be? Wait while I go out to have a look.
+
+189
+00:37:50,670 --> 00:37:53,780
+Bull, old friend!
+
+190
+00:37:53,829 --> 00:37:58,139
+There's a very beautiful young lady in here.
+
+191
+00:37:58,199 --> 00:38:03,889
+Hey, that's my woman! Why have you come to bother her?
+
+192
+00:38:03,930 --> 00:38:08,550
+Oh, I didn't know, please forgive me!
+
+193
+00:38:08,550 --> 00:38:11,940
+You didn't know, so I can't blame you. Off you go!
+
+194
+00:38:11,989 --> 00:38:16,099
+No, no. I still have something I need you to help me with.
+
+195
+00:38:18,469 --> 00:38:24,710
+We were on our way to retrieve the scriptures when we arrived at Fiery Mountain.
+
+196
+00:38:24,710 --> 00:38:27,300
+Please ask your wife
+
+197
+00:38:27,349 --> 00:38:30,820
+to lend us the palm leaf fan for a while.
+
+198
+00:38:30,880 --> 00:38:33,510
+Absolutely not! Tang Seng and Sun Wukong
+
+199
+00:38:33,510 --> 00:38:35,179
+are my son's enemies.
+
+200
+00:38:35,230 --> 00:38:38,739
+I'd love to take my revenge on them.
+
+201
+00:38:38,789 --> 00:38:44,969
+Your son is with the Goddess of Mercy now, please don't fight.
+
+202
+00:38:45,030 --> 00:38:48,940
+All right, since we are old friends, I won't fight you.
+
+203
+00:38:49,000 --> 00:38:51,710
+Now go away!
+
+204
+00:39:38,389 --> 00:39:44,179
+Baby, that pig monk is a friend of mine.
+
+205
+00:39:44,230 --> 00:39:46,500
+He wasn't sent from Palm Leaf Cave at all.
+
+206
+00:39:46,550 --> 00:39:47,739
+I don't believe you.
+
+207
+00:39:47,789 --> 00:39:50,940
+I'm not lying to you!
+
+208
+00:39:50,989 --> 00:39:54,019
+Where is that monk now?
+
+209
+00:39:54,110 --> 00:39:57,780
+I've already scared him away.
+
+210
+00:43:34,814 --> 00:43:40,987
+Palm Leaf Cave
+
+211
+00:43:58,630 --> 00:44:01,340
+The king has returned!
+
+212
+00:44:01,389 --> 00:44:02,369
+Where's grandma?
+
+213
+00:44:02,429 --> 00:44:04,780
+She's inside.
+
+214
+00:44:42,989 --> 00:44:48,219
+By what honor has the king come to visit today?
+
+215
+00:44:48,269 --> 00:44:52,260
+I heard that Sun Wukong and Tang Seng are coming here.
+
+216
+00:44:52,320 --> 00:44:56,909
+I'm afraid they want to use the palm leaf fan to pass Fiery Mountain.
+
+217
+00:44:56,949 --> 00:45:00,860
+That monkey is the one who harmed our son.
+
+218
+00:45:00,909 --> 00:45:08,489
+I'll get him sooner or later, we will have our revenge.
+
+219
+00:45:08,550 --> 00:45:12,699
+Darling, why are you crying?
+
+220
+00:45:12,750 --> 00:45:15,699
+That monkey has already been here.
+
+221
+00:45:15,750 --> 00:45:18,860
+I refused to give him the fan.
+
+222
+00:45:18,909 --> 00:45:22,260
+I don't know how, but he got inside my stomach.
+
+223
+00:45:22,309 --> 00:45:25,500
+It hurt so bad I thought I would die.
+
+224
+00:45:25,550 --> 00:45:30,589
+At last I had no choice but to give him the fan.
+
+225
+00:45:30,789 --> 00:45:35,260
+That's terrible, how could you give him the fan?
+
+226
+00:45:38,320 --> 00:45:40,469
+I gave him a false one.
+
+227
+00:45:40,720 --> 00:45:43,019
+A false one?
+
+228
+00:46:14,190 --> 00:46:19,860
+A banquet to celebrate the king's return
+
+229
+00:46:19,909 --> 00:46:25,619
+Please drink the fine wine.
+
+230
+00:46:25,670 --> 00:46:34,179
+The chicken is fragrant, the duck is beautiful, and the pig is fat.
+
+231
+00:46:34,239 --> 00:46:45,670
+I try my best to sing, I try my best to dance.
+
+232
+00:46:45,710 --> 00:46:54,500
+You must also try your best to drink.
+
+233
+00:47:03,590 --> 00:47:16,389
+My king! You dumped the old one.
+
+234
+00:47:16,429 --> 00:47:22,610
+You love another woman.
+
+235
+00:47:22,670 --> 00:47:34,659
+Countless tears were spilled for you.
+
+236
+00:47:46,710 --> 00:47:55,699
+When the light is out and the curtain is dropped,
+
+237
+00:47:55,750 --> 00:48:00,869
+you will sleep alone.
+
+238
+00:48:00,869 --> 00:48:05,510
+You too will taste loneliness.
+
+239
+00:48:05,510 --> 00:48:13,420
+Pardon me for not making you company.
+
+240
+00:48:18,550 --> 00:48:24,619
+Even if we are on the same bed,
+
+241
+00:48:24,670 --> 00:48:34,340
+we will sleep under separate sheets.
+
+242
+00:48:38,389 --> 00:48:42,380
+King, I'm drunk.
+
+243
+00:48:55,070 --> 00:48:58,139
+Darling, where did you put the real fan?
+
+244
+00:48:58,190 --> 00:49:05,460
+That monkey is very deceitful, and the pig has even greater skill.
+
+245
+00:49:05,510 --> 00:49:09,780
+If you're not careful they might trick you.
+
+246
+00:49:18,360 --> 00:49:21,980
+Our treasure is right here.
+
+247
+00:49:31,429 --> 00:49:39,309
+King, what are you thinking about? Why don't you take it?
+
+248
+00:49:39,309 --> 00:49:40,847
+My treasure.
+
+249
+00:49:41,514 --> 00:49:44,150
+Emerald Cloud Cave
+
+250
+00:49:44,250 --> 00:49:49,019
+Baby, have another cup. Drink.
+
+251
+00:49:53,909 --> 00:49:59,510
+Gold Dragon King has asked me to drink with him tonight
+
+252
+00:49:59,510 --> 00:50:01,420
+Then you should go.
+
+253
+00:50:01,469 --> 00:50:02,860
+That's right.
+
+254
+00:50:02,909 --> 00:50:06,610
+You should prepare the golden eyed beast for grandpa.
+
+255
+00:50:06,670 --> 00:50:08,260
+I will.
+
+256
+00:50:08,320 --> 00:50:12,590
+You should drink a little less tonight.
+
+257
+00:50:12,630 --> 00:50:15,739
+Otherwise I won't be able to wake you up.
+
+258
+00:50:15,800 --> 00:50:19,110
+It's terrible, grandpa's golden eyed beast has disappeared!
+
+259
+00:50:19,150 --> 00:50:20,900
+Are you all deaf and blind?
+
+260
+00:50:20,949 --> 00:50:24,030
+How could it just disappear?
+
+261
+00:50:24,030 --> 00:50:27,900
+Baby, don't mind them.
+
+262
+00:50:27,960 --> 00:50:31,710
+I'm afraid Zhu Bajie might have stolen it.
+
+263
+00:50:31,750 --> 00:50:35,260
+Maybe I should go over to Palm Leaf Cave.
+
+264
+00:50:35,320 --> 00:50:39,309
+What? You've had this planned all along.
+
+265
+00:50:42,280 --> 00:50:48,150
+You still want to go over to that shameless woman?
+
+266
+00:50:48,190 --> 00:50:50,699
+Please baby, don't cry.
+
+267
+00:50:50,750 --> 00:50:54,059
+I'll be back soon.
+
+268
+00:50:57,624 --> 00:51:01,194
+Palm Leaf Cave
+
+269
+00:51:02,670 --> 00:51:07,300
+Come over here, drink a little!
+
+270
+00:51:10,349 --> 00:51:12,460
+Now I can relax.
+
+271
+00:51:12,510 --> 00:51:16,699
+We don't have to worry about our treasure being stolen.
+
+272
+00:51:16,750 --> 00:51:21,300
+Even if they stole it, they wouldn't know to pull the silk thread.
+
+273
+00:51:21,360 --> 00:51:26,269
+Having just a pearl won't be of any use.
+
+274
+00:51:26,309 --> 00:51:31,780
+Pulling the thread will turn it into a fan, right?
+
+275
+00:51:35,119 --> 00:51:38,070
+King, you're drunk.
+
+276
+00:51:38,110 --> 00:51:44,019
+You forgot about your own treasure, and are asking me.
+
+277
+00:51:49,989 --> 00:51:53,690
+Lady, look at who I am.
+
+278
+00:52:00,320 --> 00:52:03,750
+Who are you?
+
+279
+00:52:03,789 --> 00:52:09,889
+I am Tang Seng's second apprentice, Zhu Bajie.
+
+280
+00:52:09,949 --> 00:52:14,780
+Sorry about bothering you, and thanks!
+
+281
+00:52:19,079 --> 00:52:21,710
+Bye!
+
+282
+00:53:06,829 --> 00:53:10,699
+Bull's wife is too flirtatious.
+
+283
+00:53:10,760 --> 00:53:14,710
+All her underlings are handsome.
+
+284
+00:53:14,750 --> 00:53:24,809
+Old Pig almost couldn't take it.
+
+285
+00:53:24,869 --> 00:53:28,860
+Using clever tricks and tactics,
+
+286
+00:53:28,909 --> 00:53:32,820
+I stole their treasure away.
+
+287
+00:53:32,880 --> 00:53:36,789
+This is a great accomplishment.
+
+288
+00:53:36,829 --> 00:53:38,300
+Sandy should be on his knees.
+
+289
+00:53:38,349 --> 00:53:40,730
+Monkey should learn from me.
+
+290
+00:53:40,789 --> 00:53:45,219
+Even Master will be astonished.
+
+291
+00:53:45,280 --> 00:53:49,190
+Old Pig is truly masterful.
+
+292
+00:53:49,230 --> 00:53:54,349
+Old Pig is truly masterful.
+
+293
+00:54:36,719 --> 00:54:40,469
+Fool, how are things going?
+
+294
+00:54:40,510 --> 00:54:42,809
+Not only did I get the fan,
+
+295
+00:54:42,880 --> 00:54:48,789
+Princess Iron Fan was my wife for half a day, too.
+
+296
+00:54:48,829 --> 00:54:51,699
+You got a good deal.
+
+297
+00:54:58,150 --> 00:55:01,579
+Hey, let me see the fan.
+
+298
+00:55:16,030 --> 00:55:20,219
+Why did you shrink it?
+
+299
+00:55:40,550 --> 00:55:45,340
+Old Pig, you do recognize me, right?
+
+300
+00:55:45,389 --> 00:55:49,170
+Stop joking around with me.
+
+301
+00:55:49,230 --> 00:55:52,139
+Who's joking around with you?
+
+302
+00:56:42,869 --> 00:56:45,380
+Fool, how did it go?
+
+303
+00:56:45,429 --> 00:56:47,099
+It was all for nothing.
+
+304
+00:56:47,150 --> 00:56:49,980
+Wuneng, did you borrow the fan?
+
+305
+00:56:50,030 --> 00:56:53,340
+I found Bull Demon King, but he refused.
+
+306
+00:56:53,400 --> 00:56:59,190
+Then, I turned into his look-alike.
+
+307
+00:56:59,230 --> 00:57:03,539
+I tricked Princess Iron Fan into giving me the fan.
+
+308
+00:57:03,590 --> 00:57:10,590
+But then Old Bull turned into your look-alike and tricked me into giving it back.
+
+309
+00:57:10,590 --> 00:57:12,739
+Old Bull's skills are great.
+
+310
+00:57:12,800 --> 00:57:16,150
+I got beaten up by him, too.
+
+311
+00:57:16,190 --> 00:57:21,380
+How could you get the fan and still be such a fool?
+
+312
+00:57:21,429 --> 00:57:25,659
+Not everything revolves around you!
+
+313
+00:57:30,750 --> 00:57:34,369
+Don't fight, we should quickly think of a solution.
+
+314
+00:57:34,429 --> 00:57:40,260
+In which... which direction is there no fire?
+
+315
+00:57:40,320 --> 00:57:47,070
+Of east, south, west, north, there's fire only to the west.
+
+316
+00:57:47,119 --> 00:57:50,739
+So we have no option but to go back.
+
+317
+00:57:50,789 --> 00:57:52,940
+This path is blocked, what other options do we have?
+
+318
+00:57:52,989 --> 00:57:55,219
+Bajie, don't talk like that.
+
+319
+00:57:55,269 --> 00:57:59,139
+There will always be obstacles in our path.
+
+320
+00:57:59,190 --> 00:58:04,539
+To complete our sacred task we must be strong in our faith.
+
+321
+00:58:04,590 --> 00:58:09,219
+We can't change our goal half way just because we encounter some obstacles.
+
+322
+00:58:09,280 --> 00:58:14,590
+The reason that we've been defeated is that we haven't worked together.
+
+323
+00:58:14,630 --> 00:58:17,139
+If the three of you work as one,
+
+324
+00:58:17,190 --> 00:58:20,500
+put your strength together to fight Bull Demon King,
+
+325
+00:58:20,550 --> 00:58:22,849
+then you will certainly be victorious.
+
+326
+00:58:22,909 --> 00:58:26,030
+We have heard the order of Master
+
+327
+00:58:26,030 --> 00:58:30,139
+and will fight Bull Demon King to the end.
+
+328
+00:58:30,190 --> 00:58:34,260
+to... to the end.
+
+329
+00:58:34,320 --> 00:58:37,710
+That's excellent!
+
+330
+00:58:37,750 --> 00:58:40,980
+We have all been through hardships.
+
+331
+00:58:41,039 --> 00:58:43,869
+I hope everyone will make an effort
+
+332
+00:58:43,869 --> 00:58:49,579
+together with my disciples to defeat Bull Demon King and put out the flames of Fiery Mountain.
+
+333
+00:58:49,630 --> 00:58:52,820
+Otherwise this misery will never end.
+
+334
+00:58:53,869 --> 00:58:57,489
+We have heard the order of Master, to seek happiness for all.
+
+335
+00:58:57,550 --> 00:58:58,860
+Everyone work together!
+
+336
+00:58:58,909 --> 00:59:00,519
+All right!
+
+337
+01:08:23,229 --> 01:08:25,609
+Grandma, it's terrible!
+
+338
+01:08:25,670 --> 01:08:30,789
+Grandpa has been trapped, come quickly and look!
+
+339
+01:08:54,470 --> 01:08:56,699
+The fight's not over yet, not over.
+
+340
+01:08:56,760 --> 01:08:58,710
+Careful, careful.
+
+341
+01:08:59,760 --> 01:09:05,789
+Beast, all you have to is give us the fan and we'll spare your life.
+
+342
+01:09:05,840 --> 01:09:12,750
+Old Bull, where is the fan? Hand it over!
+
+343
+01:09:12,789 --> 01:09:19,340
+My... my wife... has it.
+
+344
+01:09:25,239 --> 01:09:27,989
+Darling, darling!
+
+345
+01:09:28,029 --> 01:09:32,260
+Save me, hurry!
+
+346
+01:09:32,319 --> 01:09:35,109
+Give them the fan.
+
+347
+01:09:35,149 --> 01:09:39,619
+King! All right, all right!
+
+348
+01:09:43,399 --> 01:09:47,229
+Wukong, you go one more time!
+
+349
+01:12:30,850 --> 01:12:46,599
+The End
diff --git a/js2/mwEmbed/example_usage/media/sample_smil.xml b/js2/mwEmbed/example_usage/media/sample_smil.xml
new file mode 100644 (file)
index 0000000..25ffecc
--- /dev/null
@@ -0,0 +1,47 @@
+<smil xmlns="http://www.w3.org/2001/SMIL20/Language">
+  <head>
+    <meta name="title" content="Simple Crossfading Example"/>
+    
+    <transition id="fromGreen"
+       type="fade" 
+       subtype="fadeFromColor" 
+       fadeColor="#87CF87" 
+       dur="4s"/>
+       
+    <transition id="toGreen"
+       type="fade"
+       subtype="fadeToColor"
+       fadeColor="#87CF87" 
+       dur="4s"/>
+       
+    <transition id="xFade" 
+       type="fade" 
+       subtype="crossfade" 
+       dur="4s"/>
+       
+  </head>
+  <body>
+    <seq>
+
+       <video src="http://upload.wikimedia.org/wikipedia/commons/d/d3/Okapia_johnstoni5.ogg" 
+               region="video_region" 
+               transIn="fromGreen"     
+               transOut="xFade"        
+               type="video/ogg"        
+               fill="transition"
+               durationHint="15"
+               dur="7s"
+               poster="http://upload.wikimedia.org/wikipedia/commons/thumb/d/d3/Okapia_johnstoni5.ogg/mid-Okapia_johnstoni5.ogg.jpg"/> 
+       
+    <video src="http://upload.wikimedia.org/wikipedia/commons/0/0d/B-36_bomber.ogg" 
+               region="video_region"                           
+               fill="transition" 
+               dur="10s"
+               durationHint="70"
+               type="video/ogg" 
+               poster="http://upload.wikimedia.org/wikipedia/commons/thumb/0/0d/B-36_bomber.ogg/mid-B-36_bomber.ogg.jpg"/>     
+    </seq>
+  </body>
+</smil>
+
+
diff --git a/js2/mwEmbed/jquery/jquery-1.3.2.js b/js2/mwEmbed/jquery/jquery-1.3.2.js
new file mode 100644 (file)
index 0000000..d2548a5
--- /dev/null
@@ -0,0 +1,3657 @@
+/*!
+ * jQuery JavaScript Library v1.3.2
+ * http://jquery.com/
+ *
+ * Copyright (c) 2009 John Resig
+ * Dual licensed under the MIT and GPL licenses.
+ * http://docs.jquery.com/License
+ *
+ * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
+ * Revision: 6246
+ */
+(function(){
+var
+       // Will speed up references to window, and allows munging its name.
+       window = this,
+       // Will speed up references to undefined, and allows munging its name.
+       undefined,
+       // Map over jQuery in case of overwrite
+       _jQuery = window.jQuery,
+       // Map over the $ in case of overwrite
+       _$ = window.$,
+       jQuery = window.jQuery = window.$ = function( selector, context ) {
+               // The jQuery object is actually just the init constructor 'enhanced'
+               return new jQuery.fn.init( selector, context );
+       },
+       // A simple way to check for HTML strings or ID strings
+       // (both of which we optimize for)
+       quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,
+       // Is it a simple selector
+       isSimple = /^.[^:#\[\.,]*$/;
+jQuery.fn = jQuery.prototype = {
+       init: function( selector, context ) {
+               // Make sure that a selection was provided
+               selector = selector || document;
+               // Handle $(DOMElement)
+               if ( selector.nodeType ) {
+                       this[0] = selector;
+                       this.length = 1;
+                       this.context = selector;
+                       return this;
+               }
+               // Handle HTML strings
+               if ( typeof selector === "string" ) {
+                       // Are we dealing with HTML string or an ID?
+                       var match = quickExpr.exec( selector );
+                       // Verify a match, and that no context was specified for #id
+                       if ( match && (match[1] || !context) ) {
+                               // HANDLE: $(html) -> $(array)
+                               if ( match[1] )
+                                       selector = jQuery.clean( [ match[1] ], context );
+                               // HANDLE: $("#id")
+                               else {
+                                       var elem = document.getElementById( match[3] );
+                                       // Handle the case where IE and Opera return items
+                                       // by name instead of ID
+                                       if ( elem && elem.id != match[3] )
+                                               return jQuery().find( selector );
+                                       // Otherwise, we inject the element directly into the jQuery object
+                                       var ret = jQuery( elem || [] );
+                                       ret.context = document;
+                                       ret.selector = selector;
+                                       return ret;
+                               }
+                       // HANDLE: $(expr, [context])
+                       // (which is just equivalent to: $(content).find(expr)
+                       } else
+                               return jQuery( context ).find( selector );
+               // HANDLE: $(function)
+               // Shortcut for document ready
+               } else if ( jQuery.isFunction( selector ) )
+                       return jQuery( document ).ready( selector );
+               // Make sure that old selector state is passed along
+               if ( selector.selector && selector.context ) {
+                       this.selector = selector.selector;
+                       this.context = selector.context;
+               }
+               return this.setArray(jQuery.isArray( selector ) ?
+                       selector :
+                       jQuery.makeArray(selector));
+       },
+       // Start with an empty selector
+       selector: "",
+       // The current version of jQuery being used
+       jquery: "1.3.2",
+       // The number of elements contained in the matched element set
+       size: function() {
+               return this.length;
+       },
+       // 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 === undefined ?
+                       // Return a 'clean' array
+                       Array.prototype.slice.call( this ) :
+                       // Return just the object
+                       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( 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;
+       },
+       // Force the current matched set of elements to become
+       // the specified array of elements (destroying the stack in the process)
+       // You should use pushStack() in order to do this, but maintain the stack
+       setArray: function( elems ) {
+               // Resetting the length to 0, then using the native Array push
+               // is a super-fast way to populate an object with array-like properties
+               this.length = 0;
+               Array.prototype.push.apply( this, elems );
+               return this;
+       },
+       // 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 );
+       },
+       // Determine the position of an element within
+       // the matched set of elements
+       index: function( elem ) {
+               // Locate the position of the desired element
+               return jQuery.inArray(
+                       // If it receives a jQuery object, the first element is used
+                       elem && elem.jquery ? elem[0] : elem
+               , this );
+       },
+       attr: function( name, value, type ) {
+               var options = name;
+               // Look for the case where we're accessing a style value
+               if ( typeof name === "string" )
+                       if ( value === undefined )
+                               return this[0] && jQuery[ type || "attr" ]( this[0], name );
+                       else {
+                               options = {};
+                               options[ name ] = value;
+                       }
+               // Check to see if we're setting style values
+               return this.each(function(i){
+                       // Set all the styles
+                       for ( name in options )
+                               jQuery.attr(
+                                       type ?
+                                               this.style :
+                                               this,
+                                       name, jQuery.prop( this, options[ name ], type, i, name )
+                               );
+               });
+       },
+       css: function( key, value ) {
+               // ignore negative width and height values
+               if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
+                       value = undefined;
+               return this.attr( key, value, "curCSS" );
+       },
+       text: function( text ) {
+               if ( typeof text !== "object" && text != null )
+                       return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
+               var ret = "";
+               jQuery.each( text || this, function(){
+                       jQuery.each( this.childNodes, function(){
+                               if ( this.nodeType != 8 )
+                                       ret += this.nodeType != 1 ?
+                                               this.nodeValue :
+                                               jQuery.fn.text( [ this ] );
+                       });
+               });
+               return ret;
+       },
+       wrapAll: function( html ) {
+               if ( this[0] ) {
+                       // The elements to wrap the target around
+                       var wrap = jQuery( html, this[0].ownerDocument ).clone();
+                       if ( this[0].parentNode )
+                               wrap.insertBefore( this[0] );
+                       wrap.map(function(){
+                               var elem = this;
+                               while ( elem.firstChild )
+                                       elem = elem.firstChild;
+                               return elem;
+                       }).append(this);
+               }
+               return this;
+       },
+       wrapInner: function( html ) {
+               return this.each(function(){
+                       jQuery( this ).contents().wrapAll( html );
+               });
+       },
+       wrap: function( html ) {
+               return this.each(function(){
+                       jQuery( this ).wrapAll( html );
+               });
+       },
+       append: function() {
+               return this.domManip(arguments, true, function(elem){
+                       if (this.nodeType == 1)
+                               this.appendChild( elem );
+               });
+       },
+       prepend: function() {
+               return this.domManip(arguments, true, function(elem){
+                       if (this.nodeType == 1)
+                               this.insertBefore( elem, this.firstChild );
+               });
+       },
+       before: function() {
+               return this.domManip(arguments, false, function(elem){
+                       this.parentNode.insertBefore( elem, this );
+               });
+       },
+       after: function() {
+               return this.domManip(arguments, false, function(elem){
+                       this.parentNode.insertBefore( elem, this.nextSibling );
+               });
+       },
+       end: function() {
+               return this.prevObject || jQuery( [] );
+       },
+       // For internal use only.
+       // Behaves like an Array's method, not like a jQuery method.
+       push: [].push,
+       sort: [].sort,
+       splice: [].splice,
+       find: function( selector ) {
+               if ( this.length === 1 ) {
+                       var ret = this.pushStack( [], "find", selector );
+                       ret.length = 0;
+                       jQuery.find( selector, this[0], ret );
+                       return ret;
+               } else {
+                       return this.pushStack( jQuery.unique(jQuery.map(this, function(elem){
+                               return jQuery.find( selector, elem );
+                       })), "find", selector );
+               }
+       },
+       clone: function( events ) {
+               // Do the clone
+               var ret = this.map(function(){
+                       if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
+                               // IE copies events bound via attachEvent when
+                               // using cloneNode. Calling detachEvent on the
+                               // clone will also remove the events from the orignal
+                               // In order to get around this, we use innerHTML.
+                               // Unfortunately, this means some modifications to
+                               // attributes in IE that are actually only stored
+                               // as properties will not be copied (such as the
+                               // the name attribute on an input).
+                               var html = this.outerHTML;
+                               if ( !html ) {
+                                       var div = this.ownerDocument.createElement("div");
+                                       div.appendChild( this.cloneNode(true) );
+                                       html = div.innerHTML;
+                               }
+                               return jQuery.clean([html.replace(/ jQuery\d+="(?:\d+|null)"/g, "").replace(/^\s*/, "")])[0];
+                       } else
+                               return this.cloneNode(true);
+               });
+               // Copy the events from the original to the clone
+               if ( events === true ) {
+                       var orig = this.find("*").andSelf(), i = 0;
+                       ret.find("*").andSelf().each(function(){
+                               if ( this.nodeName !== orig[i].nodeName )
+                                       return;
+                               var events = jQuery.data( orig[i], "events" );
+                               for ( var type in events ) {
+                                       for ( var handler in events[ type ] ) {
+                                               jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
+                                       }
+                               }
+                               i++;
+                       });
+               }
+               // Return the cloned set
+               return ret;
+       },
+       filter: function( selector ) {
+               return this.pushStack(
+                       jQuery.isFunction( selector ) &&
+                       jQuery.grep(this, function(elem, i){
+                               return selector.call( elem, i );
+                       }) ||
+                       jQuery.multiFilter( selector, jQuery.grep(this, function(elem){
+                               return elem.nodeType === 1;
+                       }) ), "filter", selector );
+       },
+       closest: function( selector ) {
+               var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null,
+                       closer = 0;
+               return this.map(function(){
+                       var cur = this;
+                       while ( cur && cur.ownerDocument ) {
+                               if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) ) {
+                                       jQuery.data(cur, "closest", closer);
+                                       return cur;
+                               }
+                               cur = cur.parentNode;
+                               closer++;
+                       }
+               });
+       },
+       not: function( selector ) {
+               if ( typeof selector === "string" )
+                       // test special case where just one selector is passed in
+                       if ( isSimple.test( selector ) )
+                               return this.pushStack( jQuery.multiFilter( selector, this, true ), "not", selector );
+                       else
+                               selector = jQuery.multiFilter( selector, this );
+               var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
+               return this.filter(function() {
+                       return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
+               });
+       },
+       add: function( selector ) {
+               return this.pushStack( jQuery.unique( jQuery.merge(
+                       this.get(),
+                       typeof selector === "string" ?
+                               jQuery( selector ) :
+                               jQuery.makeArray( selector )
+               )));
+       },
+       is: function( selector ) {
+               return !!selector && jQuery.multiFilter( selector, this ).length > 0;
+       },
+       hasClass: function( selector ) {
+               return !!selector && this.is( "." + selector );
+       },
+       val: function( value ) {
+               if ( value === undefined ) {            
+                       var elem = this[0];
+                       if ( elem ) {
+                               if( jQuery.nodeName( elem, 'option' ) )
+                                       return (elem.attributes.value || {}).specified ? elem.value : elem.text;
+                       
+                               // We need to handle select boxes special
+                               if ( jQuery.nodeName( elem, "select" ) ) {
+                                       var index = elem.selectedIndex,
+                                               values = [],
+                                               options = elem.options,
+                                               one = elem.type == "select-one";
+                                       // Nothing was selected
+                                       if ( index < 0 )
+                                               return null;
+                                       // Loop through all the selected options
+                                       for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
+                                               var option = options[ i ];
+                                               if ( option.selected ) {
+                                                       // Get the specifc 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;                  
+                               }
+                               // Everything else, we just grab the value
+                               return (elem.value || "").replace(/\r/g, "");
+                       }
+                       return undefined;
+               }
+               if ( typeof value === "number" )
+                       value += '';
+               return this.each(function(){
+                       if ( this.nodeType != 1 )
+                               return;
+                       if ( jQuery.isArray(value) && /radio|checkbox/.test( this.type ) )
+                               this.checked = (jQuery.inArray(this.value, value) >= 0 ||
+                                       jQuery.inArray(this.name, value) >= 0);
+                       else if ( jQuery.nodeName( this, "select" ) ) {
+                               var values = jQuery.makeArray(value);
+                               jQuery( "option", this ).each(function(){
+                                       this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
+                                               jQuery.inArray( this.text, values ) >= 0);
+                               });
+                               if ( !values.length )
+                                       this.selectedIndex = -1;
+                       } else
+                               this.value = value;
+               });
+       },
+       html: function( value ) {
+               return value === undefined ?
+                       (this[0] ?
+                               this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g, "") :
+                               null) :
+                       this.empty().append( value );
+       },
+       replaceWith: function( value ) {
+               return this.after( value ).remove();
+       },
+       eq: function( i ) {
+               return this.slice( i, +i + 1 );
+       },
+       slice: function() {
+               return this.pushStack( Array.prototype.slice.apply( this, arguments ),
+                       "slice", Array.prototype.slice.call(arguments).join(",") );
+       },
+       map: function( callback ) {
+               return this.pushStack( jQuery.map(this, function(elem, i){
+                       return callback.call( elem, i, elem );
+               }));
+       },
+       andSelf: function() {
+               return this.add( this.prevObject );
+       },
+       domManip: function( args, table, callback ) {
+               if ( this[0] ) {
+                       var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(),
+                               scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ),
+                               first = fragment.firstChild;
+                       if ( first )
+                               for ( var i = 0, l = this.length; i < l; i++ )
+                                       callback.call( root(this[i], first), this.length > 1 || i > 0 ?
+                                                       fragment.cloneNode(true) : fragment );
+       
+                       if ( scripts )
+                               jQuery.each( scripts, evalScript );
+               }
+               return this;
+       
+               function root( elem, cur ) {
+                       return table && jQuery.nodeName(elem, "table") && jQuery.nodeName(cur, "tr") ?
+                               (elem.getElementsByTagName("tbody")[0] ||
+                               elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
+                               elem;
+               }
+       }
+};
+// Give the init function the jQuery prototype for later instantiation
+jQuery.fn.init.prototype = jQuery.fn;
+function evalScript( i, elem ) {
+       if ( elem.src )
+               jQuery.ajax({
+                       url: elem.src,
+                       async: false,
+                       dataType: "script"
+               });
+       else
+               jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
+       if ( elem.parentNode )
+               elem.parentNode.removeChild( elem );
+}
+function now(){
+       return +new Date;
+}
+jQuery.extend = jQuery.fn.extend = function() {
+       // copy reference to target object
+       var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
+       // 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 ( var name in options ) {
+                               var src = target[ name ], copy = options[ name ];
+                               // Prevent never-ending loop
+                               if ( target === copy )
+                                       continue;
+                               // Recurse if we're merging object values
+                               if ( deep && copy && typeof copy === "object" && !copy.nodeType )
+                                       target[ name ] = jQuery.extend( deep,
+                                               // Never move original objects, clone them
+                                               src || ( copy.length != null ? [ ] : { } )
+                                       , copy );
+                               // Don't bring in undefined values
+                               else if ( copy !== undefined )
+                                       target[ name ] = copy;
+                       }
+       // Return the modified object
+       return target;
+};
+// exclude the following css properties to add px
+var    exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
+       // cache defaultView
+       defaultView = document.defaultView || {},
+       toString = Object.prototype.toString;
+jQuery.extend({
+       noConflict: function( deep ) {
+               window.$ = _$;
+               if ( deep )
+                       window.jQuery = _jQuery;
+               return jQuery;
+       },
+       // 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 toString.call(obj) === "[object Function]";
+       },
+       isArray: function( obj ) {
+               return toString.call(obj) === "[object Array]";
+       },
+       // check if an element is in a (or is an) XML document
+       isXMLDoc: function( elem ) {
+               return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
+                       !!elem.ownerDocument && jQuery.isXMLDoc( elem.ownerDocument );
+       },
+       // Evalulates a script in a global context
+       globalEval: function( data ) {
+               if ( data && /\S/.test(data) ) {
+                       // Inspired by code by Andrea Giammarchi
+                       // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
+                       var head = document.getElementsByTagName("head")[0] || document.documentElement,
+                               script = document.createElement("script");
+                       script.type = "text/javascript";
+                       if ( jQuery.support.scriptEval )
+                               script.appendChild( document.createTextNode( data ) );
+                       else
+                               script.text = data;
+                       // Use insertBefore instead of appendChild  to circumvent an IE6 bug.
+                       // This arises when a base node is used (#2709).
+                       head.insertBefore( script, head.firstChild );
+                       head.removeChild( script );
+               }
+       },
+       nodeName: function( elem, name ) {
+               return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
+       },
+       // args is for internal usage only
+       each: function( object, callback, args ) {
+               var name, i = 0, length = object.length;
+               if ( args ) {
+                       if ( length === undefined ) {
+                               for ( name in object )
+                                       if ( callback.apply( object[ name ], args ) === false )
+                                               break;
+                       } else
+                               for ( ; i < length; )
+                                       if ( callback.apply( object[ i++ ], args ) === false )
+                                               break;
+               // A special, fast, case for the most common use of each
+               } else {
+                       if ( length === undefined ) {
+                               for ( name in object )
+                                       if ( callback.call( object[ name ], name, object[ name ] ) === false )
+                                               break;
+                       } else
+                               for ( var value = object[0];
+                                       i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
+               }
+               return object;
+       },
+       prop: function( elem, value, type, i, name ) {
+               // Handle executable functions
+               if ( jQuery.isFunction( value ) )
+                       value = value.call( elem, i );
+               // Handle passing in a number to a CSS property
+               return typeof value === "number" && type == "curCSS" && !exclude.test( name ) ?
+                       value + "px" :
+                       value;
+       },
+       className: {
+               // internal only, use addClass("class")
+               add: function( elem, classNames ) {
+                       jQuery.each((classNames || "").split(/\s+/), function(i, className){
+                               if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
+                                       elem.className += (elem.className ? " " : "") + className;
+                       });
+               },
+               // internal only, use removeClass("class")
+               remove: function( elem, classNames ) {
+                       if (elem.nodeType == 1)
+                               elem.className = classNames !== undefined ?
+                                       jQuery.grep(elem.className.split(/\s+/), function(className){
+                                               return !jQuery.className.has( classNames, className );
+                                       }).join(" ") :
+                                       "";
+               },
+               // internal only, use hasClass("class")
+               has: function( elem, className ) {
+                       return elem && jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
+               }
+       },
+       // A method for quickly swapping in/out CSS properties to get correct calculations
+       swap: function( elem, options, callback ) {
+               var old = {};
+               // Remember the old values, and insert the new ones
+               for ( var name in options ) {
+                       old[ name ] = elem.style[ name ];
+                       elem.style[ name ] = options[ name ];
+               }
+               callback.call( elem );
+               // Revert the old values
+               for ( var name in options )
+                       elem.style[ name ] = old[ name ];
+       },
+       css: function( elem, name, force, extra ) {
+               if ( name == "width" || name == "height" ) {
+                       var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
+                       function getWH() {
+                               val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
+                               if ( extra === "border" )
+                                       return;
+                               jQuery.each( which, function() {
+                                       if ( !extra )
+                                               val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
+                                       if ( extra === "margin" )
+                                               val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0;
+                                       else
+                                               val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
+                               });
+                       }
+                       if ( elem.offsetWidth !== 0 )
+                               getWH();
+                       else
+                               jQuery.swap( elem, props, getWH );
+                       return Math.max(0, Math.round(val));
+               }
+               return jQuery.curCSS( elem, name, force );
+       },
+       curCSS: function( elem, name, force ) {
+               var ret, style = elem.style;
+               // We need to handle opacity special in IE
+               if ( name == "opacity" && !jQuery.support.opacity ) {
+                       ret = jQuery.attr( style, "opacity" );
+                       return ret == "" ?
+                               "1" :
+                               ret;
+               }
+               // Make sure we're using the right name for getting the float value
+               if ( name.match( /float/i ) )
+                       name = styleFloat;
+               if ( !force && style && style[ name ] )
+                       ret = style[ name ];
+               else if ( defaultView.getComputedStyle ) {
+                       // Only "float" is needed here
+                       if ( name.match( /float/i ) )
+                               name = "float";
+                       name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
+                       var computedStyle = defaultView.getComputedStyle( elem, null );
+                       if ( computedStyle )
+                               ret = computedStyle.getPropertyValue( name );
+                       // We should always get a number back from opacity
+                       if ( name == "opacity" && ret == "" )
+                               ret = "1";
+               } else if ( elem.currentStyle ) {
+                       var camelCase = name.replace(/\-(\w)/g, function(all, letter){
+                               return letter.toUpperCase();
+                       });
+                       ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
+                       // 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
+                       if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
+                               // Remember the original values
+                               var left = style.left, rsLeft = elem.runtimeStyle.left;
+                               // Put in the new values to get a computed value out
+                               elem.runtimeStyle.left = elem.currentStyle.left;
+                               style.left = ret || 0;
+                               ret = style.pixelLeft + "px";
+                               // Revert the changed values
+                               style.left = left;
+                               elem.runtimeStyle.left = rsLeft;
+                       }
+               }
+               return ret;
+       },
+       clean: function( elems, context, fragment ) {
+               context = context || document;
+               // !context.createElement fails in IE with an error but returns typeof 'object'
+               if ( typeof context.createElement === "undefined" )
+                       context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
+               // If a single string is passed in and it's a single tag
+               // just do a createElement and skip the rest
+               if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) {
+                       var match = /^<(\w+)\s*\/?>$/.exec(elems[0]);
+                       if ( match )
+                               return [ context.createElement( match[1] ) ];
+               }
+               var ret = [], scripts = [], div = context.createElement("div");
+               jQuery.each(elems, function(i, elem){
+                       if ( typeof elem === "number" )
+                               elem += '';
+                       if ( !elem )
+                               return;
+                       // Convert html string into DOM nodes
+                       if ( typeof elem === "string" ) {
+                               // Fix "XHTML"-style tags in all browsers
+                               elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
+                                       return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
+                                               all :
+                                               front + "></" + tag + ">";
+                               });
+                               // Trim whitespace, otherwise indexOf won't work as expected
+                               var tags = elem.replace(/^\s+/, "").substring(0, 10).toLowerCase();
+                               var wrap =
+                                       // option or optgroup
+                                       !tags.indexOf("<opt") &&
+                                       [ 1, "<select multiple='multiple'>", "</select>" ] ||
+                                       !tags.indexOf("<leg") &&
+                                       [ 1, "<fieldset>", "</fieldset>" ] ||
+                                       tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
+                                       [ 1, "<table>", "</table>" ] ||
+                                       !tags.indexOf("<tr") &&
+                                       [ 2, "<table><tbody>", "</tbody></table>" ] ||
+                                       // <thead> matched above
+                                       (!tags.indexOf("<td") || !tags.indexOf("<th")) &&
+                                       [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
+                                       !tags.indexOf("<col") &&
+                                       [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
+                                       // IE can't serialize <link> and <script> tags normally
+                                       !jQuery.support.htmlSerialize &&
+                                       [ 1, "div<div>", "</div>" ] ||
+                                       [ 0, "", "" ];
+                               // Go to html and back, then peel off extra wrappers
+                               div.innerHTML = wrap[1] + elem + wrap[2];
+                               // Move to the right depth
+                               while ( wrap[0]-- )
+                                       div = div.lastChild;
+                               // Remove IE's autoinserted <tbody> from table fragments
+                               if ( !jQuery.support.tbody ) {
+                                       // String was a <table>, *may* have spurious <tbody>
+                                       var hasBody = /<tbody/i.test(elem),
+                                               tbody = !tags.indexOf("<table") && !hasBody ?
+                                                       div.firstChild && div.firstChild.childNodes :
+                                               // String was a bare <thead> or <tfoot>
+                                               wrap[1] == "<table>" && !hasBody ?
+                                                       div.childNodes :
+                                                       [];
+                                       for ( var 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 && /^\s/.test( elem ) )
+                                       div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
+                       
+                               elem = jQuery.makeArray( div.childNodes );
+                       }
+                       if ( elem.nodeType )
+                               ret.push( elem );
+                       else
+                               ret = jQuery.merge( ret, elem );
+               });
+               if ( fragment ) {
+                       for ( var i = 0; ret[i]; i++ ) {
+                               if ( jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
+                                       scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
+                               } else {
+                                       if ( ret[i].nodeType === 1 )
+                                               ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
+                                       fragment.appendChild( ret[i] );
+                               }
+                       }
+               
+                       return scripts;
+               }
+               return ret;
+       },
+       attr: function( elem, name, value ) {
+               // don't set attributes on text and comment nodes
+               if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
+                       return undefined;
+               var notxml = !jQuery.isXMLDoc( elem ),
+                       // Whether we are setting (or getting)
+                       set = value !== undefined;
+               // Try to normalize/fix the name
+               name = notxml && jQuery.props[ name ] || name;
+               // Only do all the following if this is a node (faster for style)
+               // IE elem.getAttribute passes even for style
+               if ( elem.tagName ) {
+                       // These attributes require special treatment
+                       var special = /href|src|style/.test( name );
+                       // Safari mis-reports the default selected property of a hidden option
+                       // Accessing the parent's selectedIndex property fixes it
+                       if ( name == "selected" && elem.parentNode )
+                               elem.parentNode.selectedIndex;
+                       // If applicable, access the attribute via the DOM 0 way
+                       if ( name in elem && notxml && !special ) {
+                               if ( set ){
+                                       // We can't allow the type property to be changed (since it causes problems in IE)
+                                       if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
+                                               throw "type property can't be changed";
+                                       elem[ name ] = value;
+                               }
+                               // browsers index elements by id/name on forms, give priority to attributes.
+                               if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) )
+                                       return elem.getAttributeNode( name ).nodeValue;
+                               // 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/
+                               if ( name == "tabIndex" ) {
+                                       var attributeNode = elem.getAttributeNode( "tabIndex" );
+                                       return attributeNode && attributeNode.specified
+                                               ? attributeNode.value
+                                               : elem.nodeName.match(/(button|input|object|select|textarea)/i)
+                                                       ? 0
+                                                       : elem.nodeName.match(/^(a|area)$/i) && elem.href
+                                                               ? 0
+                                                               : undefined;
+                               }
+                               return elem[ name ];
+                       }
+                       if ( !jQuery.support.style && notxml &&  name == "style" )
+                               return jQuery.attr( elem.style, "cssText", value );
+                       if ( set )
+                               // convert the value to a string (all browsers do this but IE) see #1070
+                               elem.setAttribute( name, "" + value );
+                       var attr = !jQuery.support.hrefNormalized && notxml && special
+                                       // Some attributes require a special call on IE
+                                       ? elem.getAttribute( name, 2 )
+                                       : elem.getAttribute( name );
+                       // Non-existent attributes return null, we normalize to undefined
+                       return attr === null ? undefined : attr;
+               }
+               // elem is actually elem.style ... set the style
+               // IE uses filters for opacity
+               if ( !jQuery.support.opacity && name == "opacity" ) {
+                       if ( set ) {
+                               // IE has trouble with opacity if it does not have layout
+                               // Force it by setting the zoom level
+                               elem.zoom = 1;
+                               // Set the alpha filter to set the opacity
+                               elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
+                                       (parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
+                       }
+                       return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
+                               (parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '':
+                               "";
+               }
+               name = name.replace(/-([a-z])/ig, function(all, letter){
+                       return letter.toUpperCase();
+               });
+               if ( set )
+                       elem[ name ] = value;
+               return elem[ name ];
+       },
+       trim: function( text ) {
+               return (text || "").replace( /^\s+|\s+$/g, "" );
+       },
+       makeArray: function( array ) {
+               var ret = [];
+               if( array != null ){
+                       var i = array.length;
+                       // The window, strings (and functions) also have 'length'
+                       if( i == null || typeof array === "string" || jQuery.isFunction(array) || array.setInterval )
+                               ret[0] = array;
+                       else
+                               while( i )
+                                       ret[--i] = array[i];
+               }
+               return ret;
+       },
+       inArray: function( elem, array ) {
+               for ( var i = 0, length = array.length; i < length; i++ )
+               // Use === because on IE, window == document
+                       if ( array[ i ] === elem )
+                               return i;
+               return -1;
+       },
+       merge: function( first, second ) {
+               // We have to loop this way because IE & Opera overwrite the length
+               // expando of getElementsByTagName
+               var i = 0, elem, pos = first.length;
+               // Also, we need to make sure that the correct elements are being returned
+               // (IE returns comment nodes in a '*' query)
+               if ( !jQuery.support.getAll ) {
+                       while ( (elem = second[ i++ ]) != null )
+                               if ( elem.nodeType != 8 )
+                                       first[ pos++ ] = elem;
+               } else
+                       while ( (elem = second[ i++ ]) != null )
+                               first[ pos++ ] = elem;
+               return first;
+       },
+       unique: function( array ) {
+               var ret = [], done = {};
+               try {
+                       for ( var i = 0, length = array.length; i < length; i++ ) {
+                               var id = jQuery.data( array[ i ] );
+                               if ( !done[ id ] ) {
+                                       done[ id ] = true;
+                                       ret.push( array[ i ] );
+                               }
+                       }
+               } catch( e ) {
+                       ret = array;
+               }
+               return ret;
+       },
+       grep: function( elems, callback, inv ) {
+               var ret = [];
+               // Go through the array, only saving the items
+               // that pass the validator function
+               for ( var i = 0, length = elems.length; i < length; i++ )
+                       if ( !inv != !callback( elems[ i ], i ) )
+                               ret.push( elems[ i ] );
+               return ret;
+       },
+       map: function( elems, callback ) {
+               var ret = [];
+               // Go through the array, translating each of the items to their
+               // new value (or values).
+               for ( var i = 0, length = elems.length; i < length; i++ ) {
+                       var value = callback( elems[ i ], i );
+                       if ( value != null )
+                               ret[ ret.length ] = value;
+               }
+               return ret.concat.apply( [], ret );
+       }
+});
+// Use of jQuery.browser is deprecated.
+// It's included for backwards compatibility and plugins,
+// although they should work to migrate away.
+var userAgent = navigator.userAgent.toLowerCase();
+// Figure out what browser is being used
+jQuery.browser = {
+       version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1],
+       safari: /webkit/.test( userAgent ),
+       opera: /opera/.test( userAgent ),
+       msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
+       mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
+};
+jQuery.each({
+       parent: function(elem){return elem.parentNode;},
+       parents: function(elem){return jQuery.dir(elem,"parentNode");},
+       next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
+       prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
+       nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
+       prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
+       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.makeArray(elem.childNodes);}
+}, function(name, fn){
+       jQuery.fn[ name ] = function( selector ) {
+               var ret = jQuery.map( this, fn );
+               if ( selector && typeof selector == "string" )
+                       ret = jQuery.multiFilter( selector, ret );
+               return this.pushStack( jQuery.unique( ret ), name, selector );
+       };
+});
+jQuery.each({
+       appendTo: "append",
+       prependTo: "prepend",
+       insertBefore: "before",
+       insertAfter: "after",
+       replaceAll: "replaceWith"
+}, function(name, original){
+       jQuery.fn[ name ] = function( selector ) {
+               var ret = [], insert = jQuery( selector );
+               for ( var i = 0, l = insert.length; i < l; i++ ) {
+                       var elems = (i > 0 ? this.clone(true) : this).get();
+                       jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
+                       ret = ret.concat( elems );
+               }
+               return this.pushStack( ret, name, selector );
+       };
+});
+jQuery.each({
+       removeAttr: function( name ) {
+               jQuery.attr( this, name, "" );
+               if (this.nodeType == 1)
+                       this.removeAttribute( name );
+       },
+       addClass: function( classNames ) {
+               jQuery.className.add( this, classNames );
+       },
+       removeClass: function( classNames ) {
+               jQuery.className.remove( this, classNames );
+       },
+       toggleClass: function( classNames, state ) {
+               if( typeof state !== "boolean" )
+                       state = !jQuery.className.has( this, classNames );
+               jQuery.className[ state ? "add" : "remove" ]( this, classNames );
+       },
+       remove: function( selector ) {
+               if ( !selector || jQuery.filter( selector, [ this ] ).length ) {
+                       // Prevent memory leaks
+                       jQuery( "*", this ).add([this]).each(function(){
+                               jQuery.event.remove(this);
+                               jQuery.removeData(this);
+                       });
+                       if (this.parentNode)
+                               this.parentNode.removeChild( this );
+               }
+       },
+       empty: function() {
+               // Remove element nodes and prevent memory leaks
+               jQuery(this).children().remove();
+               // Remove any remaining nodes
+               while ( this.firstChild )
+                       this.removeChild( this.firstChild );
+       }
+}, function(name, fn){
+       jQuery.fn[ name ] = function(){
+               return this.each( fn, arguments );
+       };
+});
+// Helper function used by the dimensions and offset modules
+function num(elem, prop) {
+       return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0;
+}
+var expando = "jQuery" + now(), uuid = 0, windowData = {};
+jQuery.extend({
+       cache: {},
+       data: function( elem, name, data ) {
+               elem = elem == window ?
+                       windowData :
+                       elem;
+               var id = elem[ expando ];
+               // Compute a unique ID for the element
+               if ( !id )
+                       id = elem[ expando ] = ++uuid;
+               // Only generate the data cache if we're
+               // trying to access or manipulate it
+               if ( name && !jQuery.cache[ id ] )
+                       jQuery.cache[ id ] = {};
+               // Prevent overriding the named cache with undefined values
+               if ( data !== undefined )
+                       jQuery.cache[ id ][ name ] = data;
+               // Return the named cache data, or the ID for the element
+               return name ?
+                       jQuery.cache[ id ][ name ] :
+                       id;
+       },
+       removeData: function( elem, name ) {
+               elem = elem == window ?
+                       windowData :
+                       elem;
+               var id = elem[ expando ];
+               // If we want to remove a specific section of the element's data
+               if ( name ) {
+                       if ( jQuery.cache[ id ] ) {
+                               // Remove the section of cache data
+                               delete jQuery.cache[ id ][ name ];
+                               // If we've removed all the data, remove the element's cache
+                               name = "";
+                               for ( name in jQuery.cache[ id ] )
+                                       break;
+                               if ( !name )
+                                       jQuery.removeData( elem );
+                       }
+               // Otherwise, we want to remove all of the element's data
+               } else {
+                       // Clean up the element expando
+                       try {
+                               delete elem[ expando ];
+                       } catch(e){
+                               // IE has trouble directly removing the expando
+                               // but it's ok with using removeAttribute
+                               if ( elem.removeAttribute )
+                                       elem.removeAttribute( expando );
+                       }
+                       // Completely remove the data cache
+                       delete jQuery.cache[ id ];
+               }
+       },
+       queue: function( elem, type, data ) {
+               if ( elem ){
+
+                       type = (type || "fx") + "queue";
+
+                       var q = jQuery.data( elem, type );
+
+                       if ( !q || jQuery.isArray(data) )
+                               q = jQuery.data( elem, type, jQuery.makeArray(data) );
+                       else if( data )
+                               q.push( data );
+
+               }
+               return q;
+       },
+       dequeue: function( elem, type ){
+               var queue = jQuery.queue( elem, type ),
+                       fn = queue.shift();
+       
+               if( !type || type === "fx" )
+                       fn = queue[0];
+               
+               if( fn !== undefined )
+                       fn.call(elem);
+       }
+});
+jQuery.fn.extend({
+       data: function( key, value ){
+               var parts = key.split(".");
+               parts[1] = parts[1] ? "." + parts[1] : "";
+               if ( value === undefined ) {
+                       var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
+                       if ( data === undefined && this.length )
+                               data = jQuery.data( this[0], key );
+                       return data === undefined && parts[1] ?
+                               this.data( parts[0] ) :
+                               data;
+               } else
+                       return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
+                               jQuery.data( this, key, value );
+                       });
+       },
+       removeData: function( key ){
+               return this.each(function(){
+                       jQuery.removeData( this, key );
+               });
+       },
+       queue: function(type, data){
+               if ( typeof type !== "string" ) {
+                       data = type;
+                       type = "fx";
+               }
+               if ( data === undefined )
+                       return jQuery.queue( this[0], type );
+               return this.each(function(){
+                       var queue = jQuery.queue( this, type, data );
+               
+                        if( type == "fx" && queue.length == 1 )
+                               queue[0].call(this);
+               });
+       },
+       dequeue: function(type){
+               return this.each(function(){
+                       jQuery.dequeue( this, type );
+               });
+       }
+});/*!
+ * Sizzle CSS Selector Engine - v0.9.3
+ *  Copyright 2009, The Dojo Foundation
+ *  Released under the MIT, BSD, and GPL Licenses.
+ *  More information: http://sizzlejs.com/
+ */
+(function(){
+var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,
+       done = 0,
+       toString = Object.prototype.toString;
+var Sizzle = function(selector, context, results, seed) {
+       results = results || [];
+       context = context || document;
+       if ( context.nodeType !== 1 && context.nodeType !== 9 )
+               return [];
+
+       if ( !selector || typeof selector !== "string" ) {
+               return results;
+       }
+       var parts = [], m, set, checkSet, check, mode, extra, prune = true;
+
+       // Reset the position of the chunker regexp (start from head)
+       chunker.lastIndex = 0;
+
+       while ( (m = chunker.exec(selector)) !== null ) {
+               parts.push( m[1] );
+       
+               if ( m[2] ) {
+                       extra = RegExp.rightContext;
+                       break;
+               }
+       }
+       if ( parts.length > 1 && origPOS.exec( selector ) ) {
+               if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
+                       set = posProcess( parts[0] + parts[1], context );
+               } else {
+                       set = Expr.relative[ parts[0] ] ?
+                               [ context ] :
+                               Sizzle( parts.shift(), context );
+                       while ( parts.length ) {
+                               selector = parts.shift();
+                               if ( Expr.relative[ selector ] )
+                                       selector += parts.shift();
+                               set = posProcess( selector, set );
+                       }
+               }
+       } else {
+               var ret = seed ?
+                       { expr: parts.pop(), set: makeArray(seed) } :
+                       Sizzle.find( parts.pop(), parts.length === 1 && context.parentNode ? context.parentNode : context, isXML(context) );
+               set = Sizzle.filter( ret.expr, ret.set );
+               if ( parts.length > 0 ) {
+                       checkSet = makeArray(set);
+               } else {
+                       prune = false;
+               }
+               while ( parts.length ) {
+                       var cur = parts.pop(), pop = cur;
+                       if ( !Expr.relative[ cur ] ) {
+                               cur = "";
+                       } else {
+                               pop = parts.pop();
+                       }
+                       if ( pop == null ) {
+                               pop = context;
+                       }
+                       Expr.relative[ cur ]( checkSet, pop, isXML(context) );
+               }
+       }
+       if ( !checkSet ) {
+               checkSet = set;
+       }
+       if ( !checkSet ) {
+               throw "Syntax error, unrecognized expression: " + (cur || selector);
+       }
+       if ( toString.call(checkSet) === "[object Array]" ) {
+               if ( !prune ) {
+                       results.push.apply( results, checkSet );
+               } else if ( context.nodeType === 1 ) {
+                       for ( var i = 0; checkSet[i] != null; i++ ) {
+                               if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
+                                       results.push( set[i] );
+                               }
+                       }
+               } else {
+                       for ( var i = 0; checkSet[i] != null; i++ ) {
+                               if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
+                                       results.push( set[i] );
+                               }
+                       }
+               }
+       } else {
+               makeArray( checkSet, results );
+       }
+       if ( extra ) {
+               Sizzle( extra, context, results, seed );
+               if ( sortOrder ) {
+                       hasDuplicate = false;
+                       results.sort(sortOrder);
+                       if ( hasDuplicate ) {
+                               for ( var i = 1; i < results.length; i++ ) {
+                                       if ( results[i] === results[i-1] ) {
+                                               results.splice(i--, 1);
+                                       }
+                               }
+                       }
+               }
+       }
+       return results;
+};
+Sizzle.matches = function(expr, set){
+       return Sizzle(expr, null, null, set);
+};
+Sizzle.find = function(expr, context, isXML){
+       var set, match;
+       if ( !expr ) {
+               return [];
+       }
+       for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
+               var type = Expr.order[i], match;
+       
+               if ( (match = Expr.match[ type ].exec( expr )) ) {
+                       var left = RegExp.leftContext;
+                       if ( left.substr( left.length - 1 ) !== "\\" ) {
+                               match[1] = (match[1] || "").replace(/\\/g, "");
+                               set = Expr.find[ type ]( match, context, isXML );
+                               if ( set != null ) {
+                                       expr = expr.replace( Expr.match[ type ], "" );
+                                       break;
+                               }
+                       }
+               }
+       }
+       if ( !set ) {
+               set = context.getElementsByTagName("*");
+       }
+       return {set: set, expr: expr};
+};
+Sizzle.filter = function(expr, set, inplace, not){
+       var old = expr, result = [], curLoop = set, match, anyFound,
+               isXMLFilter = set && set[0] && isXML(set[0]);
+       while ( expr && set.length ) {
+               for ( var type in Expr.filter ) {
+                       if ( (match = Expr.match[ type ].exec( expr )) != null ) {
+                               var filter = Expr.filter[ type ], found, item;
+                               anyFound = false;
+                               if ( curLoop == result ) {
+                                       result = [];
+                               }
+                               if ( Expr.preFilter[ type ] ) {
+                                       match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
+                                       if ( !match ) {
+                                               anyFound = found = true;
+                                       } else if ( match === true ) {
+                                               continue;
+                                       }
+                               }
+                               if ( match ) {
+                                       for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
+                                               if ( item ) {
+                                                       found = filter( item, match, i, curLoop );
+                                                       var pass = not ^ !!found;
+                                                       if ( inplace && found != null ) {
+                                                               if ( pass ) {
+                                                                       anyFound = true;
+                                                               } else {
+                                                                       curLoop[i] = false;
+                                                               }
+                                                       } else if ( pass ) {
+                                                               result.push( item );
+                                                               anyFound = true;
+                                                       }
+                                               }
+                                       }
+                               }
+                               if ( found !== undefined ) {
+                                       if ( !inplace ) {
+                                               curLoop = result;
+                                       }
+                                       expr = expr.replace( Expr.match[ type ], "" );
+                                       if ( !anyFound ) {
+                                               return [];
+                                       }
+                                       break;
+                               }
+                       }
+               }
+               // Improper expression
+               if ( expr == old ) {
+                       if ( anyFound == null ) {
+                               throw "Syntax error, unrecognized expression: " + expr;
+                       } else {
+                               break;
+                       }
+               }
+               old = expr;
+       }
+       return curLoop;
+};
+var Expr = Sizzle.selectors = {
+       order: [ "ID", "NAME", "TAG" ],
+       match: {
+               ID: /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
+               CLASS: /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
+               NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,
+               ATTR: /\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
+               TAG: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,
+               CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
+               POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
+               PSEUDO: /:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/
+       },
+       attrMap: {
+               "class": "className",
+               "for": "htmlFor"
+       },
+       attrHandle: {
+               href: function(elem){
+                       return elem.getAttribute("href");
+               }
+       },
+       relative: {
+               "+": function(checkSet, part, isXML){
+                       var isPartStr = typeof part === "string",
+                               isTag = isPartStr && !/\W/.test(part),
+                               isPartStrNotTag = isPartStr && !isTag;
+                       if ( isTag && !isXML ) {
+                               part = part.toUpperCase();
+                       }
+                       for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
+                               if ( (elem = checkSet[i]) ) {
+                                       while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
+                                       checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ?
+                                               elem || false :
+                                               elem === part;
+                               }
+                       }
+                       if ( isPartStrNotTag ) {
+                               Sizzle.filter( part, checkSet, true );
+                       }
+               },
+               ">": function(checkSet, part, isXML){
+                       var isPartStr = typeof part === "string";
+                       if ( isPartStr && !/\W/.test(part) ) {
+                               part = isXML ? part : part.toUpperCase();
+                               for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+                                       var elem = checkSet[i];
+                                       if ( elem ) {
+                                               var parent = elem.parentNode;
+                                               checkSet[i] = parent.nodeName === part ? parent : false;
+                                       }
+                               }
+                       } else {
+                               for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+                                       var elem = checkSet[i];
+                                       if ( elem ) {
+                                               checkSet[i] = isPartStr ?
+                                                       elem.parentNode :
+                                                       elem.parentNode === part;
+                                       }
+                               }
+                               if ( isPartStr ) {
+                                       Sizzle.filter( part, checkSet, true );
+                               }
+                       }
+               },
+               "": function(checkSet, part, isXML){
+                       var doneName = done++, checkFn = dirCheck;
+                       if ( !part.match(/\W/) ) {
+                               var nodeCheck = part = isXML ? part : part.toUpperCase();
+                               checkFn = dirNodeCheck;
+                       }
+                       checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
+               },
+               "~": function(checkSet, part, isXML){
+                       var doneName = done++, checkFn = dirCheck;
+                       if ( typeof part === "string" && !part.match(/\W/) ) {
+                               var nodeCheck = part = isXML ? part : part.toUpperCase();
+                               checkFn = dirNodeCheck;
+                       }
+                       checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
+               }
+       },
+       find: {
+               ID: function(match, context, isXML){
+                       if ( typeof context.getElementById !== "undefined" && !isXML ) {
+                               var m = context.getElementById(match[1]);
+                               return m ? [m] : [];
+                       }
+               },
+               NAME: function(match, context, isXML){
+                       if ( typeof context.getElementsByName !== "undefined" ) {
+                               var ret = [], results = context.getElementsByName(match[1]);
+                               for ( var i = 0, l = results.length; i < l; i++ ) {
+                                       if ( results[i].getAttribute("name") === match[1] ) {
+                                               ret.push( results[i] );
+                                       }
+                               }
+                               return ret.length === 0 ? null : ret;
+                       }
+               },
+               TAG: function(match, context){
+                       return context.getElementsByTagName(match[1]);
+               }
+       },
+       preFilter: {
+               CLASS: function(match, curLoop, inplace, result, not, isXML){
+                       match = " " + match[1].replace(/\\/g, "") + " ";
+                       if ( isXML ) {
+                               return match;
+                       }
+                       for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
+                               if ( elem ) {
+                                       if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) {
+                                               if ( !inplace )
+                                                       result.push( elem );
+                                       } else if ( inplace ) {
+                                               curLoop[i] = false;
+                                       }
+                               }
+                       }
+                       return false;
+               },
+               ID: function(match){
+                       return match[1].replace(/\\/g, "");
+               },
+               TAG: function(match, curLoop){
+                       for ( var i = 0; curLoop[i] === false; i++ ){}
+                       return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase();
+               },
+               CHILD: function(match){
+                       if ( match[1] == "nth" ) {
+                               // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
+                               var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
+                                       match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" ||
+                                       !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
+                               // calculate the numbers (first)n+(last) including if they are negative
+                               match[2] = (test[1] + (test[2] || 1)) - 0;
+                               match[3] = test[3] - 0;
+                       }
+                       // TODO: Move to normal caching system
+                       match[0] = done++;
+                       return match;
+               },
+               ATTR: function(match, curLoop, inplace, result, not, isXML){
+                       var name = match[1].replace(/\\/g, "");
+               
+                       if ( !isXML && Expr.attrMap[name] ) {
+                               match[1] = Expr.attrMap[name];
+                       }
+                       if ( match[2] === "~=" ) {
+                               match[4] = " " + match[4] + " ";
+                       }
+                       return match;
+               },
+               PSEUDO: function(match, curLoop, inplace, result, not){
+                       if ( match[1] === "not" ) {
+                               // If we're dealing with a complex expression, or a simple one
+                               if ( match[3].match(chunker).length > 1 || /^\w/.test(match[3]) ) {
+                                       match[3] = Sizzle(match[3], null, null, curLoop);
+                               } else {
+                                       var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
+                                       if ( !inplace ) {
+                                               result.push.apply( result, ret );
+                                       }
+                                       return false;
+                               }
+                       } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
+                               return true;
+                       }
+               
+                       return match;
+               },
+               POS: function(match){
+                       match.unshift( true );
+                       return match;
+               }
+       },
+       filters: {
+               enabled: function(elem){
+                       return elem.disabled === false && elem.type !== "hidden";
+               },
+               disabled: function(elem){
+                       return elem.disabled === true;
+               },
+               checked: function(elem){
+                       return elem.checked === true;
+               },
+               selected: function(elem){
+                       // Accessing this property makes selected-by-default
+                       // options in Safari work properly
+                       elem.parentNode.selectedIndex;
+                       return elem.selected === true;
+               },
+               parent: function(elem){
+                       return !!elem.firstChild;
+               },
+               empty: function(elem){
+                       return !elem.firstChild;
+               },
+               has: function(elem, i, match){
+                       return !!Sizzle( match[3], elem ).length;
+               },
+               header: function(elem){
+                       return /h\d/i.test( elem.nodeName );
+               },
+               text: function(elem){
+                       return "text" === elem.type;
+               },
+               radio: function(elem){
+                       return "radio" === elem.type;
+               },
+               checkbox: function(elem){
+                       return "checkbox" === elem.type;
+               },
+               file: function(elem){
+                       return "file" === elem.type;
+               },
+               password: function(elem){
+                       return "password" === elem.type;
+               },
+               submit: function(elem){
+                       return "submit" === elem.type;
+               },
+               image: function(elem){
+                       return "image" === elem.type;
+               },
+               reset: function(elem){
+                       return "reset" === elem.type;
+               },
+               button: function(elem){
+                       return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON";
+               },
+               input: function(elem){
+                       return /input|select|textarea|button/i.test(elem.nodeName);
+               }
+       },
+       setFilters: {
+               first: function(elem, i){
+                       return i === 0;
+               },
+               last: function(elem, i, match, array){
+                       return i === array.length - 1;
+               },
+               even: function(elem, i){
+                       return i % 2 === 0;
+               },
+               odd: function(elem, i){
+                       return i % 2 === 1;
+               },
+               lt: function(elem, i, match){
+                       return i < match[3] - 0;
+               },
+               gt: function(elem, i, match){
+                       return i > match[3] - 0;
+               },
+               nth: function(elem, i, match){
+                       return match[3] - 0 == i;
+               },
+               eq: function(elem, i, match){
+                       return match[3] - 0 == i;
+               }
+       },
+       filter: {
+               PSEUDO: function(elem, match, i, array){
+                       var name = match[1], filter = Expr.filters[ name ];
+                       if ( filter ) {
+                               return filter( elem, i, match, array );
+                       } else if ( name === "contains" ) {
+                               return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0;
+                       } else if ( name === "not" ) {
+                               var not = match[3];
+                               for ( var i = 0, l = not.length; i < l; i++ ) {
+                                       if ( not[i] === elem ) {
+                                               return false;
+                                       }
+                               }
+                               return true;
+                       }
+               },
+               CHILD: function(elem, match){
+                       var type = match[1], node = elem;
+                       switch (type) {
+                               case 'only':
+                               case 'first':
+                                       while (node = node.previousSibling)  {
+                                               if ( node.nodeType === 1 ) return false;
+                                       }
+                                       if ( type == 'first') return true;
+                                       node = elem;
+                               case 'last':
+                                       while (node = node.nextSibling)  {
+                                               if ( node.nodeType === 1 ) return false;
+                                       }
+                                       return true;
+                               case 'nth':
+                                       var first = match[2], last = match[3];
+                                       if ( first == 1 && last == 0 ) {
+                                               return true;
+                                       }
+                               
+                                       var doneName = match[0],
+                                               parent = elem.parentNode;
+
+                                       if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
+                                               var count = 0;
+                                               for ( node = parent.firstChild; node; node = node.nextSibling ) {
+                                                       if ( node.nodeType === 1 ) {
+                                                               node.nodeIndex = ++count;
+                                                       }
+                                               }
+                                               parent.sizcache = doneName;
+                                       }
+                               
+                                       var diff = elem.nodeIndex - last;
+                                       if ( first == 0 ) {
+                                               return diff == 0;
+                                       } else {
+                                               return ( diff % first == 0 && diff / first >= 0 );
+                                       }
+                       }
+               },
+               ID: function(elem, match){
+                       return elem.nodeType === 1 && elem.getAttribute("id") === match;
+               },
+               TAG: function(elem, match){
+                       return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;
+               },
+               CLASS: function(elem, match){
+                       return (" " + (elem.className || elem.getAttribute("class")) + " ")
+                               .indexOf( match ) > -1;
+               },
+               ATTR: function(elem, match){
+                       var name = match[1],
+                               result = Expr.attrHandle[ name ] ?
+                                       Expr.attrHandle[ name ]( elem ) :
+                                       elem[ name ] != null ?
+                                               elem[ name ] :
+                                               elem.getAttribute( name ),
+                               value = result + "",
+                               type = match[2],
+                               check = match[4];
+                       return result == null ?
+                               type === "!=" :
+                               type === "=" ?
+                               value === check :
+                               type === "*=" ?
+                               value.indexOf(check) >= 0 :
+                               type === "~=" ?
+                               (" " + value + " ").indexOf(check) >= 0 :
+                               !check ?
+                               value && result !== false :
+                               type === "!=" ?
+                               value != check :
+                               type === "^=" ?
+                               value.indexOf(check) === 0 :
+                               type === "$=" ?
+                               value.substr(value.length - check.length) === check :
+                               type === "|=" ?
+                               value === check || value.substr(0, check.length + 1) === check + "-" :
+                               false;
+               },
+               POS: function(elem, match, i, array){
+                       var name = match[2], filter = Expr.setFilters[ name ];
+                       if ( filter ) {
+                               return filter( elem, i, match, array );
+                       }
+               }
+       }
+};
+var origPOS = Expr.match.POS;
+for ( var type in Expr.match ) {
+       Expr.match[ type ] = RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
+}
+var makeArray = function(array, results) {
+       array = Array.prototype.slice.call( array );
+       if ( results ) {
+               results.push.apply( results, array );
+               return results;
+       }
+
+       return array;
+};
+// Perform a simple check to determine if the browser is capable of
+// converting a NodeList to an array using builtin methods.
+try {
+       Array.prototype.slice.call( document.documentElement.childNodes );
+// Provide a fallback method if it does not work
+} catch(e){
+       makeArray = function(array, results) {
+               var ret = results || [];
+               if ( toString.call(array) === "[object Array]" ) {
+                       Array.prototype.push.apply( ret, array );
+               } else {
+                       if ( typeof array.length === "number" ) {
+                               for ( var i = 0, l = array.length; i < l; i++ ) {
+                                       ret.push( array[i] );
+                               }
+                       } else {
+                               for ( var i = 0; array[i]; i++ ) {
+                                       ret.push( array[i] );
+                               }
+                       }
+               }
+               return ret;
+       };
+}
+var sortOrder;
+if ( document.documentElement.compareDocumentPosition ) {
+       sortOrder = function( a, b ) {
+               var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
+               if ( ret === 0 ) {
+                       hasDuplicate = true;
+               }
+               return ret;
+       };
+} else if ( "sourceIndex" in document.documentElement ) {
+       sortOrder = function( a, b ) {
+               var ret = a.sourceIndex - b.sourceIndex;
+               if ( ret === 0 ) {
+                       hasDuplicate = true;
+               }
+               return ret;
+       };
+} else if ( document.createRange ) {
+       sortOrder = function( a, b ) {
+               var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
+               aRange.selectNode(a);
+               aRange.collapse(true);
+               bRange.selectNode(b);
+               bRange.collapse(true);
+               var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
+               if ( ret === 0 ) {
+                       hasDuplicate = true;
+               }
+               return ret;
+       };
+}
+// Check to see if the browser returns elements by name when
+// querying by getElementById (and provide a workaround)
+(function(){
+       // We're going to inject a fake input element with a specified name
+       var form = document.createElement("form"),
+               id = "script" + (new Date).getTime();
+       form.innerHTML = "<input name='" + id + "'/>";
+       // Inject it into the root element, check its status, and remove it quickly
+       var root = document.documentElement;
+       root.insertBefore( form, root.firstChild );
+       // The workaround has to do additional checks after a getElementById
+       // Which slows things down for other browsers (hence the branching)
+       if ( !!document.getElementById( id ) ) {
+               Expr.find.ID = function(match, context, isXML){
+                       if ( typeof context.getElementById !== "undefined" && !isXML ) {
+                               var m = context.getElementById(match[1]);
+                               return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
+                       }
+               };
+               Expr.filter.ID = function(elem, match){
+                       var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
+                       return elem.nodeType === 1 && node && node.nodeValue === match;
+               };
+       }
+       root.removeChild( form );
+})();
+(function(){
+       // Check to see if the browser returns only elements
+       // when doing getElementsByTagName("*")
+       // Create a fake element
+       var div = document.createElement("div");
+       div.appendChild( document.createComment("") );
+       // Make sure no comments are found
+       if ( div.getElementsByTagName("*").length > 0 ) {
+               Expr.find.TAG = function(match, context){
+                       var results = context.getElementsByTagName(match[1]);
+                       // Filter out possible comments
+                       if ( match[1] === "*" ) {
+                               var tmp = [];
+                               for ( var i = 0; results[i]; i++ ) {
+                                       if ( results[i].nodeType === 1 ) {
+                                               tmp.push( results[i] );
+                                       }
+                               }
+                               results = tmp;
+                       }
+                       return results;
+               };
+       }
+       // Check to see if an attribute returns normalized href attributes
+       div.innerHTML = "<a href='#'></a>";
+       if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
+                       div.firstChild.getAttribute("href") !== "#" ) {
+               Expr.attrHandle.href = function(elem){
+                       return elem.getAttribute("href", 2);
+               };
+       }
+})();
+if ( document.querySelectorAll ) (function(){
+       var oldSizzle = Sizzle, div = document.createElement("div");
+       div.innerHTML = "<p class='TEST'></p>";
+       // Safari can't handle uppercase or unicode characters when
+       // in quirks mode.
+       if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
+               return;
+       }
+
+       Sizzle = function(query, context, extra, seed){
+               context = context || document;
+               // Only use querySelectorAll on non-XML documents
+               // (ID selectors don't work in non-HTML documents)
+               if ( !seed && context.nodeType === 9 && !isXML(context) ) {
+                       try {
+                               return makeArray( context.querySelectorAll(query), extra );
+                       } catch(e){}
+               }
+       
+               return oldSizzle(query, context, extra, seed);
+       };
+       Sizzle.find = oldSizzle.find;
+       Sizzle.filter = oldSizzle.filter;
+       Sizzle.selectors = oldSizzle.selectors;
+       Sizzle.matches = oldSizzle.matches;
+})();
+if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){
+       var div = document.createElement("div");
+       div.innerHTML = "<div class='test e'></div><div class='test'></div>";
+       // Opera can't find a second classname (in 9.6)
+       if ( div.getElementsByClassName("e").length === 0 )
+               return;
+       // Safari caches class attributes, doesn't catch changes (in 3.2)
+       div.lastChild.className = "e";
+       if ( div.getElementsByClassName("e").length === 1 )
+               return;
+       Expr.order.splice(1, 0, "CLASS");
+       Expr.find.CLASS = function(match, context, isXML) {
+               if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
+                       return context.getElementsByClassName(match[1]);
+               }
+       };
+})();
+function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+       var sibDir = dir == "previousSibling" && !isXML;
+       for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+               var elem = checkSet[i];
+               if ( elem ) {
+                       if ( sibDir && elem.nodeType === 1 ){
+                               elem.sizcache = doneName;
+                               elem.sizset = i;
+                       }
+                       elem = elem[dir];
+                       var match = false;
+                       while ( elem ) {
+                               if ( elem.sizcache === doneName ) {
+                                       match = checkSet[elem.sizset];
+                                       break;
+                               }
+                               if ( elem.nodeType === 1 && !isXML ){
+                                       elem.sizcache = doneName;
+                                       elem.sizset = i;
+                               }
+                               if ( elem.nodeName === cur ) {
+                                       match = elem;
+                                       break;
+                               }
+                               elem = elem[dir];
+                       }
+                       checkSet[i] = match;
+               }
+       }
+}
+function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+       var sibDir = dir == "previousSibling" && !isXML;
+       for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+               var elem = checkSet[i];
+               if ( elem ) {
+                       if ( sibDir && elem.nodeType === 1 ) {
+                               elem.sizcache = doneName;
+                               elem.sizset = i;
+                       }
+                       elem = elem[dir];
+                       var match = false;
+                       while ( elem ) {
+                               if ( elem.sizcache === doneName ) {
+                                       match = checkSet[elem.sizset];
+                                       break;
+                               }
+                               if ( elem.nodeType === 1 ) {
+                                       if ( !isXML ) {
+                                               elem.sizcache = doneName;
+                                               elem.sizset = i;
+                                       }
+                                       if ( typeof cur !== "string" ) {
+                                               if ( elem === cur ) {
+                                                       match = true;
+                                                       break;
+                                               }
+                                       } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
+                                               match = elem;
+                                               break;
+                                       }
+                               }
+                               elem = elem[dir];
+                       }
+                       checkSet[i] = match;
+               }
+       }
+}
+var contains = document.compareDocumentPosition ?  function(a, b){
+       return a.compareDocumentPosition(b) & 16;
+} : function(a, b){
+       return a !== b && (a.contains ? a.contains(b) : true);
+};
+var isXML = function(elem){
+       return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
+               !!elem.ownerDocument && isXML( elem.ownerDocument );
+};
+var posProcess = function(selector, context){
+       var tmpSet = [], later = "", match,
+               root = context.nodeType ? [context] : context;
+       // Position selectors must be done after the filter
+       // And so must :not(positional) so we move all PSEUDOs to the end
+       while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
+               later += match[0];
+               selector = selector.replace( Expr.match.PSEUDO, "" );
+       }
+       selector = Expr.relative[selector] ? selector + "*" : selector;
+       for ( var i = 0, l = root.length; i < l; i++ ) {
+               Sizzle( selector, root[i], tmpSet );
+       }
+       return Sizzle.filter( later, tmpSet );
+};
+// EXPOSE
+jQuery.find = Sizzle;
+jQuery.filter = Sizzle.filter;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.filters;
+Sizzle.selectors.filters.hidden = function(elem){
+       return elem.offsetWidth === 0 || elem.offsetHeight === 0;
+};
+Sizzle.selectors.filters.visible = function(elem){
+       return elem.offsetWidth > 0 || elem.offsetHeight > 0;
+};
+Sizzle.selectors.filters.animated = function(elem){
+       return jQuery.grep(jQuery.timers, function(fn){
+               return elem === fn.elem;
+       }).length;
+};
+jQuery.multiFilter = function( expr, elems, not ) {
+       if ( not ) {
+               expr = ":not(" + expr + ")";
+       }
+       return Sizzle.matches(expr, elems);
+};
+jQuery.dir = function( elem, dir ){
+       var matched = [], cur = elem[dir];
+       while ( cur && cur != document ) {
+               if ( cur.nodeType == 1 )
+                       matched.push( cur );
+               cur = cur[dir];
+       }
+       return matched;
+};
+jQuery.nth = function(cur, result, dir, elem){
+       result = result || 1;
+       var num = 0;
+       for ( ; cur; cur = cur[dir] )
+               if ( cur.nodeType == 1 && ++num == result )
+                       break;
+       return cur;
+};
+jQuery.sibling = function(n, elem){
+       var r = [];
+       for ( ; n; n = n.nextSibling ) {
+               if ( n.nodeType == 1 && n != elem )
+                       r.push( n );
+       }
+       return r;
+};
+return;
+window.Sizzle = Sizzle;
+})();
+/*
+ * A number of helper functions used for managing events.
+ * Many of the ideas behind this code originated from
+ * Dean Edwards' addEvent library.
+ */
+jQuery.event = {
+       // Bind an event to an element
+       // Original by Dean Edwards
+       add: function(elem, types, handler, data) {
+               if ( elem.nodeType == 3 || elem.nodeType == 8 )
+                       return;
+               // For whatever reason, IE has trouble passing the window object
+               // around, causing it to be cloned in the process
+               if ( elem.setInterval && elem != window )
+                       elem = window;
+               // Make sure that the function being executed has a unique ID
+               if ( !handler.guid )
+                       handler.guid = this.guid++;
+               // if data is passed, bind to handler
+               if ( data !== undefined ) {
+                       // Create temporary function pointer to original handler
+                       var fn = handler;
+                       // Create unique handler function, wrapped around original handler
+                       handler = this.proxy( fn );
+                       // Store data in unique handler
+                       handler.data = data;
+               }
+               // Init the element's event structure
+               var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
+                       handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
+                               // Handle the second event of a trigger and when
+                               // an event is called after a page has unloaded
+                               return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
+                                       jQuery.event.handle.apply(arguments.callee.elem, arguments) :
+                                       undefined;
+                       });
+               // Add elem as a property of the handle function
+               // This is to prevent a memory leak with non-native
+               // event in IE.
+               handle.elem = elem;
+               // Handle multiple events separated by a space
+               // jQuery(...).bind("mouseover mouseout", fn);
+               jQuery.each(types.split(/\s+/), function(index, type) {
+                       // Namespaced event handlers
+                       var namespaces = type.split(".");
+                       type = namespaces.shift();
+                       handler.type = namespaces.slice().sort().join(".");
+                       // Get the current list of functions bound to this event
+                       var handlers = events[type];
+               
+                       if ( jQuery.event.specialAll[type] )
+                               jQuery.event.specialAll[type].setup.call(elem, data, namespaces);
+                       // Init the event handler queue
+                       if (!handlers) {
+                               handlers = events[type] = {};
+                               // Check for a special event handler
+                               // Only use addEventListener/attachEvent if the special
+                               // events handler returns false
+                               if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem, data, namespaces) === false ) {
+                                       // Bind the global event handler to the element
+                                       if (elem.addEventListener)
+                                               elem.addEventListener(type, handle, false);
+                                       else if (elem.attachEvent)
+                                               elem.attachEvent("on" + type, handle);
+                               }
+                       }
+                       // Add the function to the element's handler list
+                       handlers[handler.guid] = handler;
+                       // Keep track of which events have been used, for global triggering
+                       jQuery.event.global[type] = true;
+               });
+               // Nullify elem to prevent memory leaks in IE
+               elem = null;
+       },
+       guid: 1,
+       global: {},
+       // Detach an event or set of events from an element
+       remove: function(elem, types, handler) {
+               // don't do events on text and comment nodes
+               if ( elem.nodeType == 3 || elem.nodeType == 8 )
+                       return;
+               var events = jQuery.data(elem, "events"), ret, index;
+               if ( events ) {
+                       // Unbind all events for the element
+                       if ( types === undefined || (typeof types === "string" && types.charAt(0) == ".") )
+                               for ( var type in events )
+                                       this.remove( elem, type + (types || "") );
+                       else {
+                               // types is actually an event object here
+                               if ( types.type ) {
+                                       handler = types.handler;
+                                       types = types.type;
+                               }
+                               // Handle multiple events seperated by a space
+                               // jQuery(...).unbind("mouseover mouseout", fn);
+                               jQuery.each(types.split(/\s+/), function(index, type){
+                                       // Namespaced event handlers
+                                       var namespaces = type.split(".");
+                                       type = namespaces.shift();
+                                       var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
+                                       if ( events[type] ) {
+                                               // remove the given handler for the given type
+                                               if ( handler )
+                                                       delete events[type][handler.guid];
+                                               // remove all handlers for the given type
+                                               else
+                                                       for ( var handle in events[type] )
+                                                               // Handle the removal of namespaced events
+                                                               if ( namespace.test(events[type][handle].type) )
+                                                                       delete events[type][handle];
+                                                               
+                                               if ( jQuery.event.specialAll[type] )
+                                                       jQuery.event.specialAll[type].teardown.call(elem, namespaces);
+                                               // remove generic event handler if no more handlers exist
+                                               for ( ret in events[type] ) break;
+                                               if ( !ret ) {
+                                                       if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem, namespaces) === false ) {
+                                                               if (elem.removeEventListener)
+                                                                       elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
+                                                               else if (elem.detachEvent)
+                                                                       elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
+                                                       }
+                                                       ret = null;
+                                                       delete events[type];
+                                               }
+                                       }
+                               });
+                       }
+                       // Remove the expando if it's no longer used
+                       for ( ret in events ) break;
+                       if ( !ret ) {
+                               var handle = jQuery.data( elem, "handle" );
+                               if ( handle ) handle.elem = null;
+                               jQuery.removeData( elem, "events" );
+                               jQuery.removeData( elem, "handle" );
+                       }
+               }
+       },
+       // bubbling is internal
+       trigger: function( event, data, elem, bubbling ) {
+               // Event object or event type
+               var type = event.type || event;
+               if( !bubbling ){
+                       event = typeof event === "object" ?
+                               // jQuery.Event object
+                               event[expando] ? event :
+                               // Object literal
+                               jQuery.extend( jQuery.Event(type), event ) :
+                               // Just the event type (string)
+                               jQuery.Event(type);
+                       if ( type.indexOf("!") >= 0 ) {
+                               event.type = type = type.slice(0, -1);
+                               event.exclusive = true;
+                       }
+                       // Handle a global trigger
+                       if ( !elem ) {
+                               // Don't bubble custom events when global (to avoid too much overhead)
+                               event.stopPropagation();
+                               // Only trigger if we've ever bound an event for it
+                               if ( this.global[type] )
+                                       jQuery.each( jQuery.cache, function(){
+                                               if ( this.events && this.events[type] )
+                                                       jQuery.event.trigger( event, data, this.handle.elem );
+                                       });
+                       }
+                       // Handle triggering a single element
+                       // don't do events on text and comment nodes
+                       if ( !elem || elem.nodeType == 3 || elem.nodeType == 8 )
+                               return undefined;
+               
+                       // Clean up in case it is reused
+                       event.result = undefined;
+                       event.target = elem;
+               
+                       // Clone the incoming data, if any
+                       data = jQuery.makeArray(data);
+                       data.unshift( event );
+               }
+               event.currentTarget = elem;
+               // Trigger the event, it is assumed that "handle" is a function
+               var handle = jQuery.data(elem, "handle");
+               if ( handle )
+                       handle.apply( elem, data );
+               // Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
+               if ( (!elem[type] || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
+                       event.result = false;
+               // Trigger the native events (except for clicks on links)
+               if ( !bubbling && elem[type] && !event.isDefaultPrevented() && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
+                       this.triggered = true;
+                       try {
+                               elem[ type ]();
+                       // prevent IE from throwing an error for some hidden elements
+                       } catch (e) {}
+               }
+               this.triggered = false;
+               if ( !event.isPropagationStopped() ) {
+                       var parent = elem.parentNode || elem.ownerDocument;
+                       if ( parent )
+                               jQuery.event.trigger(event, data, parent, true);
+               }
+       },
+       handle: function(event) {
+               // returned undefined or false
+               var all, handlers;
+               event = arguments[0] = jQuery.event.fix( event || window.event );
+               event.currentTarget = this;
+       
+               // Namespaced event handlers
+               var namespaces = event.type.split(".");
+               event.type = namespaces.shift();
+               // Cache this now, all = true means, any handler
+               all = !namespaces.length && !event.exclusive;
+       
+               var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
+               handlers = ( jQuery.data(this, "events") || {} )[event.type];
+               for ( var j in handlers ) {
+                       var handler = handlers[j];
+                       // Filter the functions by class
+                       if ( all || namespace.test(handler.type) ) {
+                               // Pass in a reference to the handler function itself
+                               // So that we can later remove it
+                               event.handler = handler;
+                               event.data = handler.data;
+                               var ret = handler.apply(this, arguments);
+                               if( ret !== undefined ){
+                                       event.result = ret;
+                                       if ( ret === false ) {
+                                               event.preventDefault();
+                                               event.stopPropagation();
+                                       }
+                               }
+                               if( event.isImmediatePropagationStopped() )
+                                       break;
+                       }
+               }
+       },
+       props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
+       fix: function(event) {
+               if ( event[expando] )
+                       return event;
+               // store a copy of the original event object
+               // and "clone" to set read-only properties
+               var originalEvent = event;
+               event = jQuery.Event( originalEvent );
+               for ( var i = this.props.length, prop; i; ){
+                       prop = this.props[ --i ];
+                       event[ prop ] = originalEvent[ prop ];
+               }
+               // Fix target property, if necessary
+               if ( !event.target )
+                       event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
+               // check if target is a textnode (safari)
+               if ( event.target.nodeType == 3 )
+                       event.target = event.target.parentNode;
+               // Add relatedTarget, if necessary
+               if ( !event.relatedTarget && event.fromElement )
+                       event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
+               // Calculate pageX/Y if missing and clientX/Y available
+               if ( event.pageX == null && event.clientX != null ) {
+                       var doc = document.documentElement, body = document.body;
+                       event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
+                       event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
+               }
+               // Add which for key events
+               if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
+                       event.which = event.charCode || event.keyCode;
+               // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
+               if ( !event.metaKey && event.ctrlKey )
+                       event.metaKey = event.ctrlKey;
+               // Add which for click: 1 == left; 2 == middle; 3 == right
+               // Note: button is not normalized, so don't use it
+               if ( !event.which && event.button )
+                       event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
+               return event;
+       },
+       proxy: function( fn, proxy ){
+               proxy = proxy || function(){ return fn.apply(this, arguments); };
+               // Set the guid of unique handler to the same of original handler, so it can be removed
+               proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
+               // So proxy can be declared as an argument
+               return proxy;
+       },
+       special: {
+               ready: {
+                       // Make sure the ready event is setup
+                       setup: bindReady,
+                       teardown: function() {}
+               }
+       },
+
+       specialAll: {
+               live: {
+                       setup: function( selector, namespaces ){
+                               jQuery.event.add( this, namespaces[0], liveHandler );
+                       },
+                       teardown:  function( namespaces ){
+                               if ( namespaces.length ) {
+                                       var remove = 0, name = RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");
+                               
+                                       jQuery.each( (jQuery.data(this, "events").live || {}), function(){
+                                               if ( name.test(this.type) )
+                                                       remove++;
+                                       });
+                               
+                                       if ( remove < 1 )
+                                               jQuery.event.remove( this, namespaces[0], liveHandler );
+                               }
+                       }
+               }
+       }
+};
+jQuery.Event = function( src ){
+       // Allow instantiation without the 'new' keyword
+       if( !this.preventDefault )
+               return new jQuery.Event(src);
+
+       // Event object
+       if( src && src.type ){
+               this.originalEvent = src;
+               this.type = src.type;
+       // Event type
+       }else
+               this.type = src;
+       // timeStamp is buggy for some events on Firefox(#3843)
+       // So we won't rely on the native value
+       this.timeStamp = now();
+
+       // Mark it as fixed
+       this[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)
+               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
+};
+// Checks if an event happened on an element within another element
+// Used in jQuery.event.special.mouseenter and mouseleave handlers
+var withinElement = function(event) {
+       // Check if mouse(over|out) are still within the same parent element
+       var parent = event.relatedTarget;
+       // Traverse up the tree
+       while ( parent && parent != this )
+               try { parent = parent.parentNode; }
+               catch(e) { parent = this; }
+
+       if( parent != this ){
+               // set the correct event type
+               event.type = event.data;
+               // handle event if we actually just moused on to a non sub-element
+               jQuery.event.handle.apply( this, arguments );
+       }
+};
+
+jQuery.each({
+       mouseover: 'mouseenter',
+       mouseout: 'mouseleave'
+}, function( orig, fix ){
+       jQuery.event.special[ fix ] = {
+               setup: function(){
+                       jQuery.event.add( this, orig, withinElement, fix );
+               },
+               teardown: function(){
+                       jQuery.event.remove( this, orig, withinElement );
+               }
+       };                        
+});
+jQuery.fn.extend({
+       bind: function( type, data, fn ) {
+               return type == "unload" ? this.one(type, data, fn) : this.each(function(){
+                       jQuery.event.add( this, type, fn || data, fn && data );
+               });
+       },
+       one: function( type, data, fn ) {
+               var one = jQuery.event.proxy( fn || data, function(event) {
+                       jQuery(this).unbind(event, one);
+                       return (fn || data).apply( this, arguments );
+               });
+               return this.each(function(){
+                       jQuery.event.add( this, type, one, fn && data);
+               });
+       },
+       unbind: function( type, fn ) {
+               return this.each(function(){
+                       jQuery.event.remove( this, type, fn );
+               });
+       },
+       trigger: function( type, data ) {
+               return this.each(function(){
+                       jQuery.event.trigger( type, data, this );
+               });
+       },
+       triggerHandler: function( type, data ) {
+               if( this[0] ){
+                       var event = jQuery.Event(type);
+                       event.preventDefault();
+                       event.stopPropagation();
+                       jQuery.event.trigger( event, data, this[0] );
+                       return event.result;
+               }       
+       },
+       toggle: function( fn ) {
+               // Save reference to arguments for access in closure
+               var args = arguments, i = 1;
+               // link all the functions, so any of them can unbind this click handler
+               while( i < args.length )
+                       jQuery.event.proxy( fn, args[i++] );
+               return this.click( jQuery.event.proxy( fn, function(event) {
+                       // Figure out which function to execute
+                       this.lastToggle = ( this.lastToggle || 0 ) % i;
+                       // Make sure that clicks stop
+                       event.preventDefault();
+                       // and execute the function
+                       return args[ this.lastToggle++ ].apply( this, arguments ) || false;
+               }));
+       },
+       hover: function(fnOver, fnOut) {
+               return this.mouseenter(fnOver).mouseleave(fnOut);
+       },
+       ready: function(fn) {
+               // Attach the listeners
+               bindReady();
+               // If the DOM is already ready
+               if ( jQuery.isReady )
+                       // Execute the function immediately
+                       fn.call( document, jQuery );
+               // Otherwise, remember the function for later
+               else
+                       // Add the function to the wait list
+                       jQuery.readyList.push( fn );
+               return this;
+       },
+
+       live: function( type, fn ){
+               var proxy = jQuery.event.proxy( fn );
+               proxy.guid += this.selector + type;
+               jQuery(document).bind( liveConvert(type, this.selector), this.selector, proxy );
+               return this;
+       },
+
+       die: function( type, fn ){
+               jQuery(document).unbind( liveConvert(type, this.selector), fn ? { guid: fn.guid + this.selector + type } : null );
+               return this;
+       }
+});
+function liveHandler( event ){
+       var check = RegExp("(^|\\.)" + event.type + "(\\.|$)"),
+               stop = true,
+               elems = [];
+       jQuery.each(jQuery.data(this, "events").live || [], function(i, fn){
+               if ( check.test(fn.type) ) {
+                       var elem = jQuery(event.target).closest(fn.data)[0];
+                       if ( elem )
+                               elems.push({ elem: elem, fn: fn });
+               }
+       });
+       elems.sort(function(a,b) {
+               return jQuery.data(a.elem, "closest") - jQuery.data(b.elem, "closest");
+       });
+
+       jQuery.each(elems, function(){
+               if ( this.fn.call(this.elem, event, this.fn.data) === false )
+                       return (stop = false);
+       });
+       return stop;
+}
+function liveConvert(type, selector){
+       return ["live", type, selector.replace(/\./g, "`").replace(/ /g, "|")].join(".");
+}
+jQuery.extend({
+       isReady: false,
+       readyList: [],
+       // Handle when the DOM is ready
+       ready: function() {
+               // Make sure that the DOM is not already loaded
+               if ( !jQuery.isReady ) {
+                       // Remember that the DOM is ready
+                       jQuery.isReady = true;
+                       // If there are functions bound, to execute
+                       if ( jQuery.readyList ) {
+                               // Execute all of them
+                               jQuery.each( jQuery.readyList, function(){
+                                       this.call( document, jQuery );
+                               });
+                               // Reset the list of functions
+                               jQuery.readyList = null;
+                       }
+                       // Trigger any bound ready events
+                       jQuery(document).triggerHandler("ready");
+               }
+       }
+});
+var readyBound = false;
+function bindReady(){
+       if ( readyBound ) return;
+       readyBound = true;
+       // Mozilla, Opera and webkit nightlies currently support this event
+       if ( document.addEventListener ) {
+               // Use the handy event callback
+               document.addEventListener( "DOMContentLoaded", function(){
+                       document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
+                       jQuery.ready();
+               }, false );
+       // If IE event model is used
+       } else if ( document.attachEvent ) {
+               // ensure firing before onload,
+               // maybe late but safe also for iframes
+               document.attachEvent("onreadystatechange", function(){
+                       if ( document.readyState === "complete" ) {
+                               document.detachEvent( "onreadystatechange", arguments.callee );
+                               jQuery.ready();
+                       }
+               });
+               // If IE and not an iframe
+               // continually check to see if the document is ready
+               if ( document.documentElement.doScroll && window == window.top ) (function(){
+                       if ( jQuery.isReady ) return;
+                       try {
+                               // If IE is used, use the trick by Diego Perini
+                               // http://javascript.nwbox.com/IEContentLoaded/
+                               document.documentElement.doScroll("left");
+                       } catch( error ) {
+                               setTimeout( arguments.callee, 0 );
+                               return;
+                       }
+                       // and execute any waiting functions
+                       jQuery.ready();
+               })();
+       }
+       // A fallback to window.onload, that will always work
+       jQuery.event.add( window, "load", jQuery.ready );
+}
+jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
+       "mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave," +
+       "change,select,submit,keydown,keypress,keyup,error").split(","), function(i, name){
+       // Handle event binding
+       jQuery.fn[name] = function(fn){
+               return fn ? this.bind(name, fn) : this.trigger(name);
+       };
+});
+// Prevent memory leaks in IE
+// And prevent errors on refresh with events like mouseover in other browsers
+// Window isn't included so as not to unbind existing unload events
+jQuery( window ).bind( 'unload', function(){
+       for ( var id in jQuery.cache )
+               // Skip the window
+               if ( id != 1 && jQuery.cache[ id ].handle )
+                       jQuery.event.remove( jQuery.cache[ id ].handle.elem );
+});
+(function(){
+       jQuery.support = {};
+       var root = document.documentElement,
+               script = document.createElement("script"),
+               div = document.createElement("div"),
+               id = "script" + (new Date).getTime();
+       div.style.display = "none";
+       div.innerHTML = '   <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>';
+       var all = div.getElementsByTagName("*"),
+               a = div.getElementsByTagName("a")[0];
+       // Can't get basic test support
+       if ( !all || !all.length || !a ) {
+               return;
+       }
+       jQuery.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 you can get all elements in an <object> element
+               // IE 7 always returns no results
+               objectAll: !!div.getElementsByTagName("object")[0]
+                       .getElementsByTagName("*").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 insted)
+               style: /red/.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)
+               opacity: a.style.opacity === "0.5",
+       
+               // Verify style float existence
+               // (IE uses styleFloat instead of cssFloat)
+               cssFloat: !!a.style.cssFloat,
+               // Will be defined later
+               scriptEval: false,
+               noCloneEvent: true,
+               boxModel: null
+       };
+
+       script.type = "text/javascript";
+       try {
+               script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
+       } catch(e){}
+       root.insertBefore( script, root.firstChild );
+
+       // Make sure that the execution of code works by injecting a script
+       // tag with appendChild/createTextNode
+       // (IE doesn't support this, fails, and uses .text instead)
+       if ( window[ id ] ) {
+               jQuery.support.scriptEval = true;
+               delete window[ id ];
+       }
+       root.removeChild( script );
+       if ( div.attachEvent && div.fireEvent ) {
+               div.attachEvent("onclick", function(){
+                       // Cloning a node shouldn't copy over any
+                       // bound event handlers (IE does this)
+                       jQuery.support.noCloneEvent = false;
+                       div.detachEvent("onclick", arguments.callee);
+               });
+               div.cloneNode(true).fireEvent("onclick");
+       }
+       // Figure out if the W3C box model works as expected
+       // document.body must exist before we can do this
+       jQuery(function(){
+               var div = document.createElement("div");
+               div.style.width = div.style.paddingLeft = "1px";
+               document.body.appendChild( div );
+               jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
+               document.body.removeChild( div ).style.display = 'none';
+       });
+})();
+var styleFloat = jQuery.support.cssFloat ? "cssFloat" : "styleFloat";
+jQuery.props = {
+       "for": "htmlFor",
+       "class": "className",
+       "float": styleFloat,
+       cssFloat: styleFloat,
+       styleFloat: styleFloat,
+       readonly: "readOnly",
+       maxlength: "maxLength",
+       cellspacing: "cellSpacing",
+       rowspan: "rowSpan",
+       tabindex: "tabIndex"
+};
+jQuery.fn.extend({
+       // Keep a copy of the old load
+       _load: jQuery.fn.load,
+       load: function( url, params, callback ) {
+               if ( typeof url !== "string" )
+                       return this._load( url );
+               var off = url.indexOf(" ");
+               if ( off >= 0 ) {
+                       var selector = url.slice(off, url.length);
+                       url = url.slice(0, off);
+               }
+               // Default to a GET request
+               var type = "GET";
+               // If the second parameter was provided
+               if ( params )
+                       // If it's a function
+                       if ( jQuery.isFunction( params ) ) {
+                               // We assume that it's the callback
+                               callback = params;
+                               params = null;
+                       // Otherwise, build a param string
+                       } else if( typeof params === "object" ) {
+                               params = jQuery.param( params );
+                               type = "POST";
+                       }
+               var self = this;
+               // Request the remote document
+               jQuery.ajax({
+                       url: url,
+                       type: type,
+                       dataType: "html",
+                       data: params,
+                       complete: function(res, status){
+                               // If successful, inject the HTML into all the matched elements
+                               if ( status == "success" || status == "notmodified" )
+                                       // 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(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
+                                                       // Locate the specified elements
+                                                       .find(selector) :
+                                               // If not, just inject the full result
+                                               res.responseText );
+                               if( callback )
+                                       self.each( callback, [res.responseText, status, res] );
+                       }
+               });
+               return this;
+       },
+       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 || /select|textarea/i.test(this.nodeName) ||
+                                       /text|hidden|password|search/i.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};
+                                       }) :
+                                       {name: elem.name, value: val};
+               }).get();
+       }
+});
+// 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.bind(o, f);
+       };
+});
+var jsc = now();
+jQuery.extend({
+       get: function( url, data, callback, type ) {
+               // shift arguments if data argument was ommited
+               if ( jQuery.isFunction( data ) ) {
+                       callback = data;
+                       data = null;
+               }
+               return jQuery.ajax({
+                       type: "GET",
+                       url: url,
+                       data: data,
+                       success: callback,
+                       dataType: type
+               });
+       },
+       getScript: function( url, callback ) {
+               return jQuery.get(url, null, callback, "script");
+       },
+       getJSON: function( url, data, callback ) {
+               return jQuery.get(url, data, callback, "json");
+       },
+       post: function( url, data, callback, type ) {
+               if ( jQuery.isFunction( data ) ) {
+                       callback = data;
+                       data = {};
+               }
+               return jQuery.ajax({
+                       type: "POST",
+                       url: url,
+                       data: data,
+                       success: callback,
+                       dataType: type
+               });
+       },
+       ajaxSetup: function( settings ) {
+               jQuery.extend( jQuery.ajaxSettings, settings );
+       },
+       ajaxSettings: {
+               url: location.href,
+               global: true,
+               type: "GET",
+               contentType: "application/x-www-form-urlencoded",
+               processData: true,
+               async: true,
+               /*
+               timeout: 0,
+               data: null,
+               username: null,
+               password: null,
+               */
+               // Create the request object; Microsoft failed to properly
+               // implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
+               // This function can be overriden by calling jQuery.ajaxSetup
+               xhr:function(){
+                       return window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
+               },
+               accepts: {
+                       xml: "application/xml, text/xml",
+                       html: "text/html",
+                       script: "text/javascript, application/javascript",
+                       json: "application/json, text/javascript",
+                       text: "text/plain",
+                       _default: "*/*"
+               }
+       },
+       // Last-Modified header cache for next request
+       lastModified: {},
+       ajax: function( s ) {
+               // Extend the settings, but re-extend 's' so that it can be
+               // checked again later (in the test suite, specifically)
+               s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
+               var jsonp, jsre = /=\?(&|$)/g, status, data,
+                       type = s.type.toUpperCase();
+               // convert data if not already a string
+               if ( s.data && s.processData && typeof s.data !== "string" )
+                       s.data = jQuery.param(s.data);
+               // Handle JSONP Parameter Callbacks
+               if ( s.dataType == "jsonp" ) {
+                       if ( type == "GET" ) {
+                               if ( !s.url.match(jsre) )
+                                       s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
+                       } else if ( !s.data || !s.data.match(jsre) )
+                               s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
+                       s.dataType = "json";
+               }
+               // Build temporary JSONP function
+               if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
+                       jsonp = "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 ] = function(tmp){
+                               data = tmp;
+                               success();
+                               complete();
+                               // Garbage collect
+                               window[ jsonp ] = undefined;
+                               try{ delete window[ jsonp ]; } catch(e){}
+                               if ( head )
+                                       head.removeChild( script );
+                       };
+               }
+               if ( s.dataType == "script" && s.cache == null )
+                       s.cache = false;
+               if ( s.cache === false && type == "GET" ) {
+                       var ts = now();
+                       // try replacing _= if it is there
+                       var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
+                       // if nothing was replaced, add timestamp to the end
+                       s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
+               }
+               // If data is available, append data to url for get requests
+               if ( s.data && type == "GET" ) {
+                       s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
+                       // IE likes to send both get and post data, prevent this
+                       s.data = null;
+               }
+               // Watch for a new set of requests
+               if ( s.global && ! jQuery.active++ )
+                       jQuery.event.trigger( "ajaxStart" );
+               // Matches an absolute URL, and saves the domain
+               var parts = /^(\w+:)?\/\/([^\/?#]+)/.exec( s.url );
+               // If we're requesting a remote document
+               // and trying to load JSON or Script with a GET
+               if ( s.dataType == "script" && type == "GET" && parts
+                       && ( parts[1] && parts[1] != location.protocol || parts[2] != location.host )){
+                       var head = document.getElementsByTagName("head")[0];
+                       var script = document.createElement("script");
+                       script.src = s.url;
+                       if (s.scriptCharset)
+                               script.charset = s.scriptCharset;
+                       // Handle Script loading
+                       if ( !jsonp ) {
+                               var done = false;
+                               // Attach handlers for all browsers
+                               script.onload = script.onreadystatechange = function(){
+                                       if ( !done && (!this.readyState ||
+                                                       this.readyState == "loaded" || this.readyState == "complete") ) {
+                                               done = true;
+                                               success();
+                                               complete();
+                                               // Handle memory leak in IE
+                                               script.onload = script.onreadystatechange = null;
+                                               head.removeChild( script );
+                                       }
+                               };
+                       }
+                       head.appendChild(script);
+                       // We handle everything using the script element injection
+                       return undefined;
+               }
+               var requestDone = false;
+               // Create the request object
+               var xhr = s.xhr();
+               // Open the socket
+               // Passing null username, generates a login popup on Opera (#2865)
+               if( s.username )
+                       xhr.open(type, s.url, s.async, s.username, s.password);
+               else
+                       xhr.open(type, s.url, s.async);
+               // Need an extra try/catch for cross domain requests in Firefox 3
+               try {
+                       // Set the correct header, if data is being sent
+                       if ( s.data )
+                               xhr.setRequestHeader("Content-Type", s.contentType);
+                       // Set the If-Modified-Since header, if ifModified mode.
+                       if ( s.ifModified )
+                               xhr.setRequestHeader("If-Modified-Since",
+                                       jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
+                       // Set header so the called script knows that it's an XMLHttpRequest
+                       xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
+                       // Set the Accepts header for the server, depending on the dataType
+                       xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
+                               s.accepts[ s.dataType ] + ", */*" :
+                               s.accepts._default );
+               } catch(e){}
+               // Allow custom headers/mimetypes and early abort
+               if ( s.beforeSend && s.beforeSend(xhr, s) === false ) {
+                       // Handle the global AJAX counter
+                       if ( s.global && ! --jQuery.active )
+                               jQuery.event.trigger( "ajaxStop" );
+                       // close opended socket
+                       xhr.abort();
+                       return false;
+               }
+               if ( s.global )
+                       jQuery.event.trigger("ajaxSend", [xhr, s]);
+               // Wait for a response to come back
+               var onreadystatechange = function(isTimeout){
+                       // The request was aborted, clear the interval and decrement jQuery.active
+                       if (xhr.readyState == 0) {
+                               if (ival) {
+                                       // clear poll interval
+                                       clearInterval(ival);
+                                       ival = null;
+                                       // Handle the global AJAX counter
+                                       if ( s.global && ! --jQuery.active )
+                                               jQuery.event.trigger( "ajaxStop" );
+                               }
+                       // The transfer is complete and the data is available, or the request timed out
+                       } else if ( !requestDone && xhr && (xhr.readyState == 4 || isTimeout == "timeout") ) {
+                               requestDone = true;
+                               // clear poll interval
+                               if (ival) {
+                                       clearInterval(ival);
+                                       ival = null;
+                               }
+                               status = isTimeout == "timeout" ? "timeout" :
+                                       !jQuery.httpSuccess( xhr ) ? "error" :
+                                       s.ifModified && jQuery.httpNotModified( xhr, s.url ) ? "notmodified" :
+                                       "success";
+                               if ( status == "success" ) {
+                                       // Watch for, and catch, XML document parse errors
+                                       try {
+                                               // process the data (runs the xml through httpData regardless of callback)
+                                               data = jQuery.httpData( xhr, s.dataType, s );
+                                       } catch(e) {
+                                               status = "parsererror";
+                                       }
+                               }
+                               // Make sure that the request was successful or notmodified
+                               if ( status == "success" ) {
+                                       // Cache Last-Modified header, if ifModified mode.
+                                       var modRes;
+                                       try {
+                                               modRes = xhr.getResponseHeader("Last-Modified");
+                                       } catch(e) {} // swallow exception thrown by FF if header is not available
+                                       if ( s.ifModified && modRes )
+                                               jQuery.lastModified[s.url] = modRes;
+                                       // JSONP handles its own success callback
+                                       if ( !jsonp )
+                                               success();
+                               } else
+                                       jQuery.handleError(s, xhr, status);
+                               // Fire the complete handlers
+                               complete();
+                               if ( isTimeout )
+                                       xhr.abort();
+                               // Stop memory leaks
+                               if ( s.async )
+                                       xhr = null;
+                       }
+               };
+               if ( s.async ) {
+                       // don't attach the handler to the request, just poll it instead
+                       var ival = setInterval(onreadystatechange, 13);
+                       // Timeout checker
+                       if ( s.timeout > 0 )
+                               setTimeout(function(){
+                                       // Check to see if the request is still happening
+                                       if ( xhr && !requestDone )
+                                               onreadystatechange( "timeout" );
+                               }, s.timeout);
+               }
+               // Send the data
+               try {
+                       xhr.send(s.data);
+               } catch(e) {
+                       jQuery.handleError(s, xhr, null, e);
+               }
+               // firefox 1.5 doesn't fire statechange for sync requests
+               if ( !s.async )
+                       onreadystatechange();
+               function success(){
+                       // If a local callback was specified, fire it and pass it the data
+                       if ( s.success )
+                               s.success( data, status );
+                       // Fire the global callback
+                       if ( s.global )
+                               jQuery.event.trigger( "ajaxSuccess", [xhr, s] );
+               }
+               function complete(){
+                       // Process result
+                       if ( s.complete )
+                               s.complete(xhr, status);
+                       // The request was completed
+                       if ( s.global )
+                               jQuery.event.trigger( "ajaxComplete", [xhr, s] );
+                       // Handle the global AJAX counter
+                       if ( s.global && ! --jQuery.active )
+                               jQuery.event.trigger( "ajaxStop" );
+               }
+               // return XMLHttpRequest to allow aborting the request etc.
+               return xhr;
+       },
+       handleError: function( s, xhr, status, e ) {
+               // If a local callback was specified, fire it
+               if ( s.error ) s.error( xhr, status, e );
+               // Fire the global callback
+               if ( s.global )
+                       jQuery.event.trigger( "ajaxError", [xhr, s, e] );
+       },
+       // Counter for holding the number of active queries
+       active: 0,
+       // Determines if an XMLHttpRequest was successful or not
+       httpSuccess: function( xhr ) {
+               try {
+                       // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
+                       return !xhr.status && location.protocol == "file:" ||
+                               ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status == 304 || xhr.status == 1223;
+               } catch(e){}
+               return false;
+       },
+       // Determines if an XMLHttpRequest returns NotModified
+       httpNotModified: function( xhr, url ) {
+               try {
+                       var xhrRes = xhr.getResponseHeader("Last-Modified");
+                       // Firefox always returns 200. check Last-Modified date
+                       return xhr.status == 304 || xhrRes == jQuery.lastModified[url];
+               } catch(e){}
+               return false;
+       },
+       httpData: function( xhr, type, s ) {
+               var ct = xhr.getResponseHeader("content-type"),
+                       xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0,
+                       data = xml ? xhr.responseXML : xhr.responseText;
+               if ( xml && data.documentElement.tagName == "parsererror" )
+                       throw "parsererror";
+               
+               // Allow a pre-filtering function to sanitize the response
+               // s != null is checked to keep backwards compatibility
+               if( s && s.dataFilter )
+                       data = s.dataFilter( data, type );
+               // The filter can actually parse the response
+               if( typeof data === "string" ){
+                       // If the type is "script", eval it in global context
+                       if ( type == "script" )
+                               jQuery.globalEval( data );
+                       // Get the JavaScript object, if JSON is used.
+                       if ( type == "json" )
+                               data = window["eval"]("(" + data + ")");
+               }
+       
+               return data;
+       },
+       // Serialize an array of form elements or a set of
+       // key/values into a query string
+       param: function( a ) {
+               var s = [ ];
+               function add( key, value ){
+                       s[ s.length ] = encodeURIComponent(key) + '=' + encodeURIComponent(value);
+               };
+               // If an array was passed in, assume that it is an array
+               // of form elements
+               if ( jQuery.isArray(a) || a.jquery )
+                       // Serialize the form elements
+                       jQuery.each( a, function(){
+                               add( this.name, this.value );
+                       });
+               // Otherwise, assume that it's an object of key/value pairs
+               else
+                       // Serialize the key/values
+                       for ( var j in a )
+                               // If the value is an array then the key names need to be repeated
+                               if ( jQuery.isArray(a[j]) )
+                                       jQuery.each( a[j], function(){
+                                               add( j, this );
+                                       });
+                               else
+                                       add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] );
+               // Return the resulting serialization
+               return s.join("&").replace(/%20/g, "+");
+       }
+});
+var elemdisplay = {},
+       timerId,
+       fxAttrs = [
+               // height animations
+               [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
+               // width animations
+               [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
+               // opacity animations
+               [ "opacity" ]
+       ];
+function genFx( type, num ){
+       var obj = {};
+       jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function(){
+               obj[ this ] = type;
+       });
+       return obj;
+}
+jQuery.fn.extend({
+       show: function(speed,callback){
+               if ( speed ) {
+                       return this.animate( genFx("show", 3), speed, callback);
+               } else {
+                       for ( var i = 0, l = this.length; i < l; i++ ){
+                               var old = jQuery.data(this[i], "olddisplay");
+                       
+                               this[i].style.display = old || "";
+                       
+                               if ( jQuery.css(this[i], "display") === "none" ) {
+                                       var tagName = this[i].tagName, display;
+                               
+                                       if ( elemdisplay[ tagName ] ) {
+                                               display = elemdisplay[ tagName ];
+                                       } else {
+                                               var elem = jQuery("<" + tagName + " />").appendTo("body");
+                                       
+                                               display = elem.css("display");
+                                               if ( display === "none" )
+                                                       display = "block";
+                                       
+                                               elem.remove();
+                                       
+                                               elemdisplay[ tagName ] = display;
+                                       }
+                               
+                                       jQuery.data(this[i], "olddisplay", display);
+                               }
+                       }
+                       // Set the display of the elements in a second loop
+                       // to avoid the constant reflow
+                       for ( var i = 0, l = this.length; i < l; i++ ){
+                               this[i].style.display = jQuery.data(this[i], "olddisplay") || "";
+                       }
+               
+                       return this;
+               }
+       },
+       hide: function(speed,callback){
+               if ( speed ) {
+                       return this.animate( genFx("hide", 3), speed, callback);
+               } else {
+                       for ( var i = 0, l = this.length; i < l; i++ ){
+                               var old = jQuery.data(this[i], "olddisplay");
+                               if ( !old && old !== "none" )
+                                       jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display"));
+                       }
+                       // Set the display of the elements in a second loop
+                       // to avoid the constant reflow
+                       for ( var i = 0, l = this.length; i < l; i++ ){
+                               this[i].style.display = "none";
+                       }
+                       return this;
+               }
+       },
+       // Save the old toggle function
+       _toggle: jQuery.fn.toggle,
+       toggle: function( fn, fn2 ){
+               var bool = typeof fn === "boolean";
+               return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
+                       this._toggle.apply( this, arguments ) :
+                       fn == null || bool ?
+                               this.each(function(){
+                                       var state = bool ? fn : jQuery(this).is(":hidden");
+                                       jQuery(this)[ state ? "show" : "hide" ]();
+                               }) :
+                               this.animate(genFx("toggle", 3), fn, fn2);
+       },
+       fadeTo: function(speed,to,callback){
+               return this.animate({opacity: to}, speed, callback);
+       },
+       animate: function( prop, speed, easing, callback ) {
+               var optall = jQuery.speed(speed, easing, callback);
+               return this[ optall.queue === false ? "each" : "queue" ](function(){
+       
+                       var opt = jQuery.extend({}, optall), p,
+                               hidden = this.nodeType == 1 && jQuery(this).is(":hidden"),
+                               self = this;
+
+                       for ( p in prop ) {
+                               if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
+                                       return opt.complete.call(this);
+                               if ( ( p == "height" || p == "width" ) && this.style ) {
+                                       // Store display property
+                                       opt.display = jQuery.css(this, "display");
+                                       // Make sure that nothing sneaks out
+                                       opt.overflow = this.style.overflow;
+                               }
+                       }
+                       if ( opt.overflow != null )
+                               this.style.overflow = "hidden";
+                       opt.curAnim = jQuery.extend({}, prop);
+                       jQuery.each( prop, function(name, val){
+                               var e = new jQuery.fx( self, opt, name );
+                               if ( /toggle|show|hide/.test(val) )
+                                       e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
+                               else {
+                                       var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
+                                               start = e.cur(true) || 0;
+                                       if ( parts ) {
+                                               var end = parseFloat(parts[2]),
+                                                       unit = parts[3] || "px";
+                                               // We need to compute starting value
+                                               if ( unit != "px" ) {
+                                                       self.style[ name ] = (end || 1) + unit;
+                                                       start = ((end || 1) / e.cur(true)) * start;
+                                                       self.style[ name ] = start + unit;
+                                               }
+                                               // If a +=/-= token was provided, we're doing a relative animation
+                                               if ( parts[1] )
+                                                       end = ((parts[1] == "-=" ? -1 : 1) * end) + start;
+                                               e.custom( start, end, unit );
+                                       } else
+                                               e.custom( start, val, "" );
+                               }
+                       });
+                       // For JS strict compliance
+                       return true;
+               });
+       },
+       stop: function(clearQueue, gotoEnd){
+               var timers = jQuery.timers;
+               if (clearQueue)
+                       this.queue([]);
+               this.each(function(){
+                       // go in reverse order so anything added to the queue during the loop is ignored
+                       for ( var i = timers.length - 1; i >= 0; i-- )
+                               if ( timers[i].elem == this ) {
+                                       if (gotoEnd)
+                                               // force the next step to be the last
+                                               timers[i](true);
+                                       timers.splice(i, 1);
+                               }
+               });
+               // start the next in the queue if the last step wasn't forced
+               if (!gotoEnd)
+                       this.dequeue();
+               return this;
+       }
+});
+// Generate shortcuts for custom animations
+jQuery.each({
+       slideDown: genFx("show", 1),
+       slideUp: genFx("hide", 1),
+       slideToggle: genFx("toggle", 1),
+       fadeIn: { opacity: "show" },
+       fadeOut: { opacity: "hide" }
+}, function( name, props ){
+       jQuery.fn[ name ] = function( speed, callback ){
+               return this.animate( props, speed, callback );
+       };
+});
+jQuery.extend({
+       speed: function(speed, easing, fn) {
+               var opt = typeof speed === "object" ? 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 :
+                       jQuery.fx.speeds[opt.duration] || jQuery.fx.speeds._default;
+               // Queueing
+               opt.old = opt.complete;
+               opt.complete = function(){
+                       if ( opt.queue !== false )
+                               jQuery(this).dequeue();
+                       if ( jQuery.isFunction( opt.old ) )
+                               opt.old.call( this );
+               };
+               return opt;
+       },
+       easing: {
+               linear: function( p, n, firstNum, diff ) {
+                       return firstNum + diff * p;
+               },
+               swing: function( p, n, firstNum, diff ) {
+                       return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
+               }
+       },
+       timers: [],
+       fx: function( elem, options, prop ){
+               this.options = options;
+               this.elem = elem;
+               this.prop = prop;
+               if ( !options.orig )
+                       options.orig = {};
+       }
+});
+jQuery.fx.prototype = {
+       // Simple function for setting a style value
+       update: function(){
+               if ( this.options.step )
+                       this.options.step.call( this.elem, this.now, this );
+               (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
+               // Set display property to block for height/width animations
+               if ( ( this.prop == "height" || this.prop == "width" ) && this.elem.style )
+                       this.elem.style.display = "block";
+       },
+       // Get the current size
+       cur: function(force){
+               if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) )
+                       return this.elem[ this.prop ];
+               var r = parseFloat(jQuery.css(this.elem, this.prop, force));
+               return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
+       },
+       // Start an animation from one number to another
+       custom: function(from, to, unit){
+               this.startTime = now();
+               this.start = from;
+               this.end = to;
+               this.unit = unit || this.unit || "px";
+               this.now = this.start;
+               this.pos = this.state = 0;
+               var self = this;
+               function t(gotoEnd){
+                       return self.step(gotoEnd);
+               }
+               t.elem = this.elem;
+               if ( t() && jQuery.timers.push(t) && !timerId ) {
+                       timerId = setInterval(function(){
+                               var timers = jQuery.timers;
+                               for ( var i = 0; i < timers.length; i++ )
+                                       if ( !timers[i]() )
+                                               timers.splice(i--, 1);
+                               if ( !timers.length ) {
+                                       clearInterval( timerId );
+                                       timerId = undefined;
+                               }
+                       }, 13);
+               }
+       },
+       // Simple 'show' function
+       show: function(){
+               // Remember where we started, so that we can go back to it later
+               this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
+               this.options.show = true;
+               // Begin the animation
+               // Make sure that we start at a small width/height to avoid any
+               // flash of content
+               this.custom(this.prop == "width" || this.prop == "height" ? 1 : 0, this.cur());
+               // Start by showing the element
+               jQuery(this.elem).show();
+       },
+       // Simple 'hide' function
+       hide: function(){
+               // Remember where we started, so that we can go back to it later
+               this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
+               this.options.hide = true;
+               // Begin the animation
+               this.custom(this.cur(), 0);
+       },
+       // Each step of an animation
+       step: function(gotoEnd){
+               var t = now();
+               if ( gotoEnd || t >= this.options.duration + this.startTime ) {
+                       this.now = this.end;
+                       this.pos = this.state = 1;
+                       this.update();
+                       this.options.curAnim[ this.prop ] = true;
+                       var done = true;
+                       for ( var i in this.options.curAnim )
+                               if ( this.options.curAnim[i] !== true )
+                                       done = false;
+                       if ( done ) {
+                               if ( this.options.display != null ) {
+                                       // Reset the overflow
+                                       this.elem.style.overflow = this.options.overflow;
+                                       // Reset the display
+                                       this.elem.style.display = this.options.display;
+                                       if ( jQuery.css(this.elem, "display") == "none" )
+                                               this.elem.style.display = "block";
+                               }
+                               // Hide the element if the "hide" operation was done
+                               if ( this.options.hide )
+                                       jQuery(this.elem).hide();
+                               // Reset the properties, if the item has been hidden or shown
+                               if ( this.options.hide || this.options.show )
+                                       for ( var p in this.options.curAnim )
+                                               jQuery.attr(this.elem.style, p, this.options.orig[p]);
+                               
+                               // Execute the complete function
+                               this.options.complete.call( this.elem );
+                       }
+                       return false;
+               } else {
+                       var n = t - this.startTime;
+                       this.state = n / this.options.duration;
+                       // Perform the easing function, defaults to swing
+                       this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
+                       this.now = this.start + ((this.end - this.start) * this.pos);
+                       // Perform the next step of the animation
+                       this.update();
+               }
+               return true;
+       }
+};
+jQuery.extend( jQuery.fx, {
+       speeds:{
+               slow: 600,
+               fast: 200,
+               // Default speed
+               _default: 400
+       },
+       step: {
+               opacity: function(fx){
+                       jQuery.attr(fx.elem.style, "opacity", fx.now);
+               },
+               _default: function(fx){
+                       if ( fx.elem.style && fx.elem.style[ fx.prop ] != null )
+                               fx.elem.style[ fx.prop ] = fx.now + fx.unit;
+                       else
+                               fx.elem[ fx.prop ] = fx.now;
+               }
+       }
+});
+if ( document.documentElement["getBoundingClientRect"] )
+       jQuery.fn.offset = function() {
+               if ( !this[0] ) return { top: 0, left: 0 };
+               if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
+               var box  = this[0].getBoundingClientRect(), doc = this[0].ownerDocument, body = doc.body, docElem = doc.documentElement,
+                       clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,
+                       top  = box.top  + (self.pageYOffset || jQuery.boxModel && docElem.scrollTop  || body.scrollTop ) - clientTop,
+                       left = box.left + (self.pageXOffset || jQuery.boxModel && docElem.scrollLeft || body.scrollLeft) - clientLeft;
+               return { top: top, left: left };
+       };
+else
+       jQuery.fn.offset = function() {
+               if ( !this[0] ) return { top: 0, left: 0 };
+               if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
+               jQuery.offset.initialized || jQuery.offset.initialize();
+               var elem = this[0], offsetParent = elem.offsetParent, prevOffsetParent = elem,
+                       doc = elem.ownerDocument, computedStyle, docElem = doc.documentElement,
+                       body = doc.body, defaultView = doc.defaultView,
+                       prevComputedStyle = defaultView.getComputedStyle(elem, null),
+                       top = elem.offsetTop, left = elem.offsetLeft;
+               while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
+                       computedStyle = defaultView.getComputedStyle(elem, null);
+                       top -= elem.scrollTop, left -= elem.scrollLeft;
+                       if ( elem === offsetParent ) {
+                               top += elem.offsetTop, left += elem.offsetLeft;
+                               if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.tagName)) )
+                                       top  += parseInt( computedStyle.borderTopWidth,  10) || 0,
+                                       left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
+                               prevOffsetParent = offsetParent, offsetParent = elem.offsetParent;
+                       }
+                       if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" )
+                               top  += parseInt( computedStyle.borderTopWidth,  10) || 0,
+                               left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
+                       prevComputedStyle = computedStyle;
+               }
+               if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" )
+                       top  += body.offsetTop,
+                       left += body.offsetLeft;
+               if ( prevComputedStyle.position === "fixed" )
+                       top  += Math.max(docElem.scrollTop, body.scrollTop),
+                       left += Math.max(docElem.scrollLeft, body.scrollLeft);
+               return { top: top, left: left };
+       };
+jQuery.offset = {
+       initialize: function() {
+               if ( this.initialized ) return;
+               var body = document.body, container = document.createElement('div'), innerDiv, checkDiv, table, td, rules, prop, bodyMarginTop = body.style.marginTop,
+                       html = '<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>';
+               rules = { position: 'absolute', top: 0, left: 0, margin: 0, border: 0, width: '1px', height: '1px', visibility: 'hidden' };
+               for ( prop in rules ) container.style[prop] = rules[prop];
+               container.innerHTML = html;
+               body.insertBefore(container, body.firstChild);
+               innerDiv = container.firstChild, checkDiv = innerDiv.firstChild, td = innerDiv.nextSibling.firstChild.firstChild;
+               this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
+               this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
+               innerDiv.style.overflow = 'hidden', innerDiv.style.position = 'relative';
+               this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
+               body.style.marginTop = '1px';
+               this.doesNotIncludeMarginInBodyOffset = (body.offsetTop === 0);
+               body.style.marginTop = bodyMarginTop;
+               body.removeChild(container);
+               this.initialized = true;
+       },
+       bodyOffset: function(body) {
+               jQuery.offset.initialized || jQuery.offset.initialize();
+               var top = body.offsetTop, left = body.offsetLeft;
+               if ( jQuery.offset.doesNotIncludeMarginInBodyOffset )
+                       top  += parseInt( jQuery.curCSS(body, 'marginTop',  true), 10 ) || 0,
+                       left += parseInt( jQuery.curCSS(body, 'marginLeft', true), 10 ) || 0;
+               return { top: top, left: left };
+       }
+};
+
+jQuery.fn.extend({
+       position: function() {
+               var left = 0, top = 0, results;
+               if ( this[0] ) {
+                       // Get *real* offsetParent
+                       var offsetParent = this.offsetParent(),
+                       // Get correct offsets
+                       offset     = this.offset(),
+                       parentOffset = /^body|html$/i.test(offsetParent[0].tagName) ? { 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  -= num( this, 'marginTop'  );
+                       offset.left -= num( this, 'marginLeft' );
+                       // Add offsetParent borders
+                       parentOffset.top  += num( offsetParent, 'borderTopWidth'  );
+                       parentOffset.left += num( offsetParent, 'borderLeftWidth' );
+                       // Subtract the two offsets
+                       results = {
+                               top:  offset.top  - parentOffset.top,
+                               left: offset.left - parentOffset.left
+                       };
+               }
+               return results;
+       },
+       offsetParent: function() {
+               var offsetParent = this[0].offsetParent || document.body;
+               while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && jQuery.css(offsetParent, 'position') == 'static') )
+                       offsetParent = offsetParent.offsetParent;
+               return jQuery(offsetParent);
+       }
+});
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( ['Left', 'Top'], function(i, name) {
+       var method = 'scroll' + name;
+
+       jQuery.fn[ method ] = function(val) {
+               if (!this[0]) return null;
+               return val !== undefined ?
+                       // Set the scroll offset
+                       this.each(function() {
+                               this == window || this == document ?
+                                       window.scrollTo(
+                                               !i ? val : jQuery(window).scrollLeft(),
+                                                i ? val : jQuery(window).scrollTop()
+                                       ) :
+                                       this[ method ] = val;
+                       }) :
+                       // Return the scroll offset
+                       this[0] == window || this[0] == document ?
+                               self[ i ? 'pageYOffset' : 'pageXOffset' ] ||
+                                       jQuery.boxModel && document.documentElement[ method ] ||
+                                       document.body[ method ] :
+                               this[0][ method ];
+       };
+});
+// Create innerHeight, innerWidth, outerHeight and outerWidth methods
+jQuery.each([ "Height", "Width" ], function(i, name){
+       var tl = i ? "Left"  : "Top",  // top or left
+               br = i ? "Right" : "Bottom", // bottom or right
+               lower = name.toLowerCase();
+       // innerHeight and innerWidth
+       jQuery.fn["inner" + name] = function(){
+               return this[0] ?
+                       jQuery.css( this[0], lower, false, "padding" ) :
+                       null;
+       };
+       // outerHeight and outerWidth
+       jQuery.fn["outer" + name] = function(margin) {
+               return this[0] ?
+                       jQuery.css( this[0], lower, false, margin ? "margin" : "border" ) :
+                       null;
+       };
+
+       var type = name.toLowerCase();
+       jQuery.fn[ type ] = function( size ) {
+               // Get window width or height
+               return this[0] == window ?
+                       // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
+                       document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] ||
+                       document.body[ "client" + name ] :
+                       // Get document width or height
+                       this[0] == document ?
+                               // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
+                               Math.max(
+                                       document.documentElement["client" + name],
+                                       document.body["scroll" + name], document.documentElement["scroll" + name],
+                                       document.body["offset" + name], document.documentElement["offset" + name]
+                               ) :
+                               // Get or set width or height on the element
+                               size === undefined ?
+                                       // Get width or height on the element
+                                       (this.length ? jQuery.css( this[0], type ) : null) :
+                                       // Set the width or height on the element (default to pixels if value is unitless)
+                                       this.css( type, typeof size === "string" ? size : size + "px" );
+       };
+});
+})();
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery-1.3.2.min.js b/js2/mwEmbed/jquery/jquery-1.3.2.min.js
new file mode 100644 (file)
index 0000000..b1ae21d
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * jQuery JavaScript Library v1.3.2
+ * http://jquery.com/
+ *
+ * Copyright (c) 2009 John Resig
+ * Dual licensed under the MIT and GPL licenses.
+ * http://docs.jquery.com/License
+ *
+ * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
+ * Revision: 6246
+ */
+(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F<J;F++){var G=M[F];if(G.selected){K=o(G).val();if(H){return K}L.push(K)}}return L}return(E.value||"").replace(/\r/g,"")}return g}if(typeof K==="number"){K+=""}return this.each(function(){if(this.nodeType!=1){return}if(o.isArray(K)&&/radio|checkbox/.test(this.type)){this.checked=(o.inArray(this.value,K)>=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G<E;G++){L.call(K(this[G],H),this.length>1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H<I;H++){if((G=arguments[H])!=null){for(var F in G){var K=J[F],L=G[F];if(J===L){continue}if(E&&L&&typeof L==="object"&&!L.nodeType){J[F]=o.extend(E,K||(L.length!=null?[]:{}),L)}else{if(L!==g){J[F]=L}}}}}return J};var b=/z-?index|font-?weight|opacity|zoom|line-?height/i,q=document.defaultView||{},s=Object.prototype.toString;o.extend({noConflict:function(E){l.$=p;if(E){l.jQuery=y}return o},isFunction:function(E){return s.call(E)==="[object Function]"},isArray:function(E){return s.call(E)==="[object Array]"},isXMLDoc:function(E){return E.nodeType===9&&E.documentElement.nodeName!=="HTML"||!!E.ownerDocument&&o.isXMLDoc(E.ownerDocument)},globalEval:function(G){if(G&&/\S/.test(G)){var F=document.getElementsByTagName("head")[0]||document.documentElement,E=document.createElement("script");E.type="text/javascript";if(o.support.scriptEval){E.appendChild(document.createTextNode(G))}else{E.text=G}F.insertBefore(E,F.firstChild);F.removeChild(E)}},nodeName:function(F,E){return F.nodeName&&F.nodeName.toUpperCase()==E.toUpperCase()},each:function(G,K,F){var E,H=0,I=G.length;if(F){if(I===g){for(E in G){if(K.apply(G[E],F)===false){break}}}else{for(;H<I;){if(K.apply(G[H++],F)===false){break}}}}else{if(I===g){for(E in G){if(K.call(G[E],E,G[E])===false){break}}}else{for(var J=G[0];H<I&&K.call(J,H,J)!==false;J=G[++H]){}}}return G},prop:function(H,I,G,F,E){if(o.isFunction(I)){I=I.call(H,F)}return typeof I==="number"&&G=="curCSS"&&!b.test(E)?I+"px":I},className:{add:function(E,F){o.each((F||"").split(/\s+/),function(G,H){if(E.nodeType==1&&!o.className.has(E.className,H)){E.className+=(E.className?" ":"")+H}})},remove:function(E,F){if(E.nodeType==1){E.className=F!==g?o.grep(E.className.split(/\s+/),function(G){return !o.className.has(F,G)}).join(" "):""}},has:function(F,E){return F&&o.inArray(E,(F.className||F).toString().split(/\s+/))>-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+"></"+T+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("<opt")&&[1,"<select multiple='multiple'>","</select>"]||!O.indexOf("<leg")&&[1,"<fieldset>","</fieldset>"]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"<table>","</table>"]||!O.indexOf("<tr")&&[2,"<table><tbody>","</tbody></table>"]||(!O.indexOf("<td")||!O.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||!O.indexOf("<col")&&[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"]||!o.support.htmlSerialize&&[1,"div<div>","</div>"]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/<tbody/i.test(S),N=!O.indexOf("<table")&&!R?L.firstChild&&L.firstChild.childNodes:Q[1]=="<table>"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E<F;E++){if(H[E]===G){return E}}return -1},merge:function(H,E){var F=0,G,I=H.length;if(!o.support.getAll){while((G=E[F++])!=null){if(G.nodeType!=8){H[I++]=G}}}else{while((G=E[F++])!=null){H[I++]=G}}return H},unique:function(K){var F=[],E={};try{for(var G=0,H=K.length;G<H;G++){var J=o.data(K[G]);if(!E[J]){E[J]=true;F.push(K[G])}}}catch(I){F=K}return F},grep:function(F,J,E){var G=[];for(var H=0,I=F.length;H<I;H++){if(!E!=!J(F[H],H)){G.push(F[H])}}return G},map:function(E,J){var F=[];for(var G=0,H=E.length;G<H;G++){var I=J(E[G],G);if(I!=null){F[F.length]=I}}return F.concat.apply([],F)}});var C=navigator.userAgent.toLowerCase();o.browser={version:(C.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)||[0,"0"])[1],safari:/webkit/.test(C),opera:/opera/.test(C),msie:/msie/.test(C)&&!/opera/.test(C),mozilla:/mozilla/.test(C)&&!/(compatible|webkit)/.test(C)};o.each({parent:function(E){return E.parentNode},parents:function(E){return o.dir(E,"parentNode")},next:function(E){return o.nth(E,2,"nextSibling")},prev:function(E){return o.nth(E,2,"previousSibling")},nextAll:function(E){return o.dir(E,"nextSibling")},prevAll:function(E){return o.dir(E,"previousSibling")},siblings:function(E){return o.sibling(E.parentNode.firstChild,E)},children:function(E){return o.sibling(E.firstChild)},contents:function(E){return o.nodeName(E,"iframe")?E.contentDocument||E.contentWindow.document:o.makeArray(E.childNodes)}},function(E,F){o.fn[E]=function(G){var H=o.map(this,F);if(G&&typeof G=="string"){H=o.multiFilter(G,H)}return this.pushStack(o.unique(H),E,G)}});o.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(E,F){o.fn[E]=function(G){var J=[],L=o(G);for(var K=0,H=L.length;K<H;K++){var I=(K>0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}});
+/*
+ * Sizzle CSS Selector Engine - v0.9.3
+ *  Copyright 2009, The Dojo Foundation
+ *  Released under the MIT, BSD, and GPL Licenses.
+ *  More information: http://sizzlejs.com/
+ */
+(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa<ab.length;aa++){if(ab[aa]===ab[aa-1]){ab.splice(aa--,1)}}}}}return ab};F.matches=function(T,U){return F(T,null,null,U)};F.find=function(aa,T,ab){var Z,X;if(!aa){return[]}for(var W=0,V=I.order.length;W<V;W++){var Y=I.order[W],X;if((X=I.match[Y].exec(aa))){var U=RegExp.leftContext;if(U.substr(U.length-1)!=="\\"){X[1]=(X[1]||"").replace(/\\/g,"");Z=I.find[Y](X,T,ab);if(Z!=null){aa=aa.replace(I.match[Y],"");break}}}}if(!Z){Z=T.getElementsByTagName("*")}return{set:Z,expr:aa}};F.filter=function(ad,ac,ag,W){var V=ad,ai=[],aa=ac,Y,T,Z=ac&&ac[0]&&Q(ac[0]);while(ad&&ac.length){for(var ab in I.filter){if((Y=I.match[ab].exec(ad))!=null){var U=I.filter[ab],ah,af;T=false;if(aa==ai){ai=[]}if(I.preFilter[ab]){Y=I.preFilter[ab](Y,aa,ag,ai,W,Z);if(!Y){T=ah=true}else{if(Y===true){continue}}}if(Y){for(var X=0;(af=aa[X])!=null;X++){if(af){ah=U(af,Y,X,aa);var ae=W^!!ah;if(ag&&ah!=null){if(ae){T=true}else{aa[X]=false}}else{if(ae){ai.push(af);T=true}}}}}if(ah!==g){if(!ag){aa=ai}ad=ad.replace(I.match[ab],"");if(!T){return[]}break}}}if(ad==V){if(T==null){throw"Syntax error, unrecognized expression: "+ad}else{break}}V=ad}return aa};var I=F.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(T){return T.getAttribute("href")}},relative:{"+":function(aa,T,Z){var X=typeof T==="string",ab=X&&!/\W/.test(T),Y=X&&!ab;if(ab&&!Z){T=T.toUpperCase()}for(var W=0,V=aa.length,U;W<V;W++){if((U=aa[W])){while((U=U.previousSibling)&&U.nodeType!==1){}aa[W]=Y||U&&U.nodeName===T?U||false:U===T}}if(Y){F.filter(T,aa,true)}},">":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V<T;V++){var Y=Z[V];if(Y){var W=Y.parentNode;Z[V]=W.nodeName===U?W:false}}}else{for(var V=0,T=Z.length;V<T;V++){var Y=Z[V];if(Y){Z[V]=X?Y.parentNode:Y.parentNode===U}}if(X){F.filter(U,Z,true)}}},"":function(W,U,Y){var V=L++,T=S;if(!U.match(/\W/)){var X=U=Y?U:U.toUpperCase();T=P}T("parentNode",U,V,W,X,Y)},"~":function(W,U,Y){var V=L++,T=S;if(typeof U==="string"&&!U.match(/\W/)){var X=U=Y?U:U.toUpperCase();T=P}T("previousSibling",U,V,W,X,Y)}},find:{ID:function(U,V,W){if(typeof V.getElementById!=="undefined"&&!W){var T=V.getElementById(U[1]);return T?[T]:[]}},NAME:function(V,Y,Z){if(typeof Y.getElementsByName!=="undefined"){var U=[],X=Y.getElementsByName(V[1]);for(var W=0,T=X.length;W<T;W++){if(X[W].getAttribute("name")===V[1]){U.push(X[W])}}return U.length===0?null:U}},TAG:function(T,U){return U.getElementsByTagName(T[1])}},preFilter:{CLASS:function(W,U,V,T,Z,aa){W=" "+W[1].replace(/\\/g,"")+" ";if(aa){return W}for(var X=0,Y;(Y=U[X])!=null;X++){if(Y){if(Z^(Y.className&&(" "+Y.className+" ").indexOf(W)>=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return U<T[3]-0},gt:function(V,U,T){return U>T[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W<T;W++){if(Y[W]===Z){return false}}return true}}}},CHILD:function(T,W){var Z=W[1],U=T;switch(Z){case"only":case"first":while(U=U.previousSibling){if(U.nodeType===1){return false}}if(Z=="first"){return true}U=T;case"last":while(U=U.nextSibling){if(U.nodeType===1){return false}}return true;case"nth":var V=W[2],ac=W[3];if(V==1&&ac==0){return true}var Y=W[0],ab=T.parentNode;if(ab&&(ab.sizcache!==Y||!T.nodeIndex)){var X=0;for(U=ab.firstChild;U;U=U.nextSibling){if(U.nodeType===1){U.nodeIndex=++X}}ab.sizcache=Y}var aa=T.nodeIndex-ac;if(V==0){return aa==0}else{return(aa%V==0&&aa/V>=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V<T;V++){U.push(X[V])}}else{for(var V=0;X[V];V++){U.push(X[V])}}}return U}}var G;if(document.documentElement.compareDocumentPosition){G=function(U,T){var V=U.compareDocumentPosition(T)&4?-1:U===T?0:1;if(V===0){hasDuplicate=true}return V}}else{if("sourceIndex" in document.documentElement){G=function(U,T){var V=U.sourceIndex-T.sourceIndex;if(V===0){hasDuplicate=true}return V}}else{if(document.createRange){G=function(W,U){var V=W.ownerDocument.createRange(),T=U.ownerDocument.createRange();V.selectNode(W);V.collapse(true);T.selectNode(U);T.collapse(true);var X=V.compareBoundaryPoints(Range.START_TO_END,T);if(X===0){hasDuplicate=true}return X}}}}(function(){var U=document.createElement("form"),V="script"+(new Date).getTime();U.innerHTML="<input name='"+V+"'/>";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="<a href='#'></a>";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="<p class='TEST'></p>";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="<div class='test e'></div><div class='test'></div>";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W<V;W++){var T=ad[W];if(T){if(ab&&T.nodeType===1){T.sizcache=Y;T.sizset=W}T=T[U];var X=false;while(T){if(T.sizcache===Y){X=ad[T.sizset];break}if(T.nodeType===1&&!ac){T.sizcache=Y;T.sizset=W}if(T.nodeName===Z){X=T;break}T=T[U]}ad[W]=X}}}function S(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W<V;W++){var T=ad[W];if(T){if(ab&&T.nodeType===1){T.sizcache=Y;T.sizset=W}T=T[U];var X=false;while(T){if(T.sizcache===Y){X=ad[T.sizset];break}if(T.nodeType===1){if(!ac){T.sizcache=Y;T.sizset=W}if(typeof Z!=="string"){if(T===Z){X=true;break}}else{if(F.filter(Z,[T]).length>0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z<U;Z++){F(T,V[Z],W)}return F.filter(X,W)};o.find=F;o.filter=F.filter;o.expr=F.selectors;o.expr[":"]=o.expr.filters;F.selectors.filters.hidden=function(T){return T.offsetWidth===0||T.offsetHeight===0};F.selectors.filters.visible=function(T){return T.offsetWidth>0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F<E.length){o.event.proxy(G,E[F++])}return this.click(o.event.proxy(G,function(H){this.lastToggle=(this.lastToggle||0)%F;H.preventDefault();return E[this.lastToggle++].apply(this,arguments)||false}))},hover:function(E,F){return this.mouseenter(E).mouseleave(F)},ready:function(E){B();if(o.isReady){E.call(document,o)}else{o.readyList.push(E)}return this},live:function(G,F){var E=o.event.proxy(F);E.guid+=this.selector+G;o(document).bind(i(G,this.selector),this.selector,E);return this},die:function(F,E){o(document).unbind(i(F,this.selector),E?{guid:E.guid+this.selector+F}:null);return this}});function c(H){var E=RegExp("(^|\\.)"+H.type+"(\\.|$)"),G=true,F=[];o.each(o.data(this,"events").live||[],function(I,J){if(E.test(J.type)){var K=o(H.target).closest(J.data)[0];if(K){F.push({elem:K,fn:J})}}});F.sort(function(J,I){return o.data(J.elem,"closest")-o.data(I.elem,"closest")});o.each(F,function(){if(this.fn.call(this.elem,H,this.fn.data)===false){return(G=false)}});return G}function i(F,E){return["live",F,E.replace(/\./g,"`").replace(/ /g,"|")].join(".")}o.extend({isReady:false,readyList:[],ready:function(){if(!o.isReady){o.isReady=true;if(o.readyList){o.each(o.readyList,function(){this.call(document,o)});o.readyList=null}o(document).triggerHandler("ready")}}});var x=false;function B(){if(x){return}x=true;if(document.addEventListener){document.addEventListener("DOMContentLoaded",function(){document.removeEventListener("DOMContentLoaded",arguments.callee,false);o.ready()},false)}else{if(document.attachEvent){document.attachEvent("onreadystatechange",function(){if(document.readyState==="complete"){document.detachEvent("onreadystatechange",arguments.callee);o.ready()}});if(document.documentElement.doScroll&&l==l.top){(function(){if(o.isReady){return}try{document.documentElement.doScroll("left")}catch(E){setTimeout(arguments.callee,0);return}o.ready()})()}}}o.event.add(l,"load",o.ready)}o.each(("blur,focus,load,resize,scroll,unload,click,dblclick,mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave,change,select,submit,keydown,keypress,keyup,error").split(","),function(F,E){o.fn[E]=function(G){return G?this.bind(E,G):this.trigger(E)}});o(l).bind("unload",function(){for(var E in o.cache){if(E!=1&&o.cache[E].handle){o.event.remove(o.cache[E].handle.elem)}}});(function(){o.support={};var F=document.documentElement,G=document.createElement("script"),K=document.createElement("div"),J="script"+(new Date).getTime();K.style.display="none";K.innerHTML='   <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>';var H=K.getElementsByTagName("*"),E=K.getElementsByTagName("a")[0];if(!H||!H.length||!E){return}o.support={leadingWhitespace:K.firstChild.nodeType==3,tbody:!K.getElementsByTagName("tbody").length,objectAll:!!K.getElementsByTagName("object")[0].getElementsByTagName("*").length,htmlSerialize:!!K.getElementsByTagName("link").length,style:/red/.test(E.getAttribute("style")),hrefNormalized:E.getAttribute("href")==="/a",opacity:E.style.opacity==="0.5",cssFloat:!!E.style.cssFloat,scriptEval:false,noCloneEvent:true,boxModel:null};G.type="text/javascript";try{G.appendChild(document.createTextNode("window."+J+"=1;"))}catch(I){}F.insertBefore(G,F.firstChild);if(l[J]){o.support.scriptEval=true;delete l[J]}F.removeChild(G);if(K.attachEvent&&K.fireEvent){K.attachEvent("onclick",function(){o.support.noCloneEvent=false;K.detachEvent("onclick",arguments.callee)});K.cloneNode(true).fireEvent("onclick")}o(function(){var L=document.createElement("div");L.style.width=L.style.paddingLeft="1px";document.body.appendChild(L);o.boxModel=o.support.boxModel=L.offsetWidth===2;document.body.removeChild(L).style.display="none"})})();var w=o.support.cssFloat?"cssFloat":"styleFloat";o.props={"for":"htmlFor","class":"className","float":w,cssFloat:w,styleFloat:w,readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",tabindex:"tabIndex"};o.fn.extend({_load:o.fn.load,load:function(G,J,K){if(typeof G!=="string"){return this._load(G)}var I=G.indexOf(" ");if(I>=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("<div/>").append(M.responseText.replace(/<script(.|\s)*?\/script>/g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H<F;H++){var E=o.data(this[H],"olddisplay");this[H].style.display=E||"";if(o.css(this[H],"display")==="none"){var G=this[H].tagName,K;if(m[G]){K=m[G]}else{var I=o("<"+G+" />").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H<F;H++){this[H].style.display=o.data(this[H],"olddisplay")||""}return this}},hide:function(H,I){if(H){return this.animate(t("hide",3),H,I)}else{for(var G=0,F=this.length;G<F;G++){var E=o.data(this[G],"olddisplay");if(!E&&E!=="none"){o.data(this[G],"olddisplay",o.css(this[G],"display"))}}for(var G=0,F=this.length;G<F;G++){this[G].style.display="none"}return this}},_toggle:o.fn.toggle,toggle:function(G,F){var E=typeof G==="boolean";return o.isFunction(G)&&o.isFunction(F)?this._toggle.apply(this,arguments):G==null||E?this.each(function(){var H=E?G:o(this).is(":hidden");o(this)[H?"show":"hide"]()}):this.animate(t("toggle",3),G,F)},fadeTo:function(E,G,F){return this.animate({opacity:G},E,F)},animate:function(I,F,H,G){var E=o.speed(F,H,G);return this[E.queue===false?"each":"queue"](function(){var K=o.extend({},E),M,L=this.nodeType==1&&o(this).is(":hidden"),J=this;for(M in I){if(I[M]=="hide"&&L||I[M]=="show"&&!L){return K.complete.call(this)}if((M=="height"||M=="width")&&this.style){K.display=o.css(this,"display");K.overflow=this.style.overflow}}if(K.overflow!=null){this.style.overflow="hidden"}K.curAnim=o.extend({},I);o.each(I,function(O,S){var R=new o.fx(J,K,O);if(/toggle|show|hide/.test(S)){R[S=="toggle"?L?"show":"hide":S](I)}else{var Q=S.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),T=R.cur(true)||0;if(Q){var N=parseFloat(Q[2]),P=Q[3]||"px";if(P!="px"){J.style[O]=(N||1)+P;T=((N||1)/R.cur(true))*T;J.style[O]=T+P}if(Q[1]){N=((Q[1]=="-="?-1:1)*N)+T}R.custom(T,N,P)}else{R.custom(T,S,"")}}});return true})},stop:function(F,E){var G=o.timers;if(F){this.queue([])}this.each(function(){for(var H=G.length-1;H>=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J<K.length;J++){if(!K[J]()){K.splice(J--,1)}}if(!K.length){clearInterval(n);n=g}},13)}},show:function(){this.options.orig[this.prop]=o.attr(this.elem.style,this.prop);this.options.show=true;this.custom(this.prop=="width"||this.prop=="height"?1:0,this.cur());o(this.elem).show()},hide:function(){this.options.orig[this.prop]=o.attr(this.elem.style,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(H){var G=e();if(H||G>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})();
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/AUTHORS.txt b/js2/mwEmbed/jquery/jquery.ui/AUTHORS.txt
new file mode 100644 (file)
index 0000000..637175b
--- /dev/null
@@ -0,0 +1,30 @@
+jQuery UI Authors (http://ui.jquery.com/about)
+
+This software consists of voluntary contributions made by many
+individuals. For exact contribution history, see the revision history
+and logs, available at http://jquery-ui.googlecode.com/svn/
+
+Brandon Aaron
+Paul Bakaus (paulbakaus.com)
+David Bolter
+Rich Caloggero
+Chi Cheng (cloudream@gmail.com)
+Colin Clark (http://colin.atrc.utoronto.ca/)
+Michelle D'Souza
+Aaron Eisenberger (aaronchi@gmail.com)
+Ariel Flesler
+Bohdan Ganicky
+Scott González
+Marc Grabanski (m@marcgrabanski.com)
+Klaus Hartl (stilbuero.de)
+Scott Jehl
+Cody Lindley
+Eduardo Lundgren (eduardolundgren@gmail.com)
+Todd Parker
+John Resig
+Patty Toland
+Ca-Phun Ung (yelotofu.com)
+Keith Wood (kbwood@virginbroadband.com.au)
+Maggie Costello Wachs
+Richard D. Worth (rdworth.org)
+Jörn Zaefferer (bassistance.de)
diff --git a/js2/mwEmbed/jquery/jquery.ui/GPL-LICENSE.txt b/js2/mwEmbed/jquery/jquery.ui/GPL-LICENSE.txt
new file mode 100644 (file)
index 0000000..11dddd0
--- /dev/null
@@ -0,0 +1,278 @@
+        GNU GENERAL PUBLIC LICENSE
+           Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+          Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+        GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+          NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
diff --git a/js2/mwEmbed/jquery/jquery.ui/MIT-LICENSE.txt b/js2/mwEmbed/jquery/jquery.ui/MIT-LICENSE.txt
new file mode 100644 (file)
index 0000000..f0f2ba9
--- /dev/null
@@ -0,0 +1,25 @@
+Copyright (c) 2009 Paul Bakaus, http://jqueryui.com/
+
+This software consists of voluntary contributions made by many
+individuals (AUTHORS.txt, http://jqueryui.com/about) For exact
+contribution history, see the revision history and logs, available
+at http://jquery-ui.googlecode.com/svn/
+
+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/js2/mwEmbed/jquery/jquery.ui/external/bgiframe/ChangeLog.txt b/js2/mwEmbed/jquery/jquery.ui/external/bgiframe/ChangeLog.txt
new file mode 100644 (file)
index 0000000..995b351
--- /dev/null
@@ -0,0 +1,20 @@
+== New and Noteworthy ==
+
+== 2.1.1 ==
+
+* Removed $.browser.version for jQuery < 1.1.3
+
+== 2.1 ==
+
+* Updated to work with jQuery 1.1.3
+* Added $.browser.version for jQuery < 1.1.3
+* Optimized duplication check by using child selector and using .length test
+
+== 2.0 ==
+
+* Added ability change settings like width, height, src and more.
+
+== 1.0 ==
+
+* Only adds iframe once per an element
+* Works with SSL enabled pages
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/external/bgiframe/META.json b/js2/mwEmbed/jquery/jquery.ui/external/bgiframe/META.json
new file mode 100644 (file)
index 0000000..766190b
--- /dev/null
@@ -0,0 +1,32 @@
+{
+       "name": "jQuery-bgiframe",
+       "version": 2.1,
+       "author": [
+               "Brandon Aaron <brandon.aaron@gmail.com>"
+       ],
+       "abstract": "jQuery plugin for fixing z-index issues in IE6",
+       "license": "mit, gpl",
+       "distribution_type": "plugin",
+       "requires": {
+               "jQuery": ">=1.0.3"
+       },
+       "provides": {
+               "jQuery.bgiframe": {
+                       "version": 2.1,
+                       "file": "jquery.bgiframe.js"
+               }
+       },
+       "keywords": [
+               "iframe",
+               "hack",
+               "zIndex",
+               "z-index",
+               "ie6"
+       ],
+       "stability": "Official",
+       "meta-spec": {
+               "version": 1.3,
+               "url": "http://module-build.sourceforge.net/META-spec-v1.3.html"
+       },
+       "generated_by": "Brandon Aaron"
+}
diff --git a/js2/mwEmbed/jquery/jquery.ui/external/bgiframe/docs/fonts-min.css b/js2/mwEmbed/jquery/jquery.ui/external/bgiframe/docs/fonts-min.css
new file mode 100644 (file)
index 0000000..3b7c21a
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+Copyright (c) 2007, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+version: 2.2.2
+*/
+body {font:13px arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}table {font-size:inherit;font:100%;}select, input, textarea {font:99% arial,helvetica,clean,sans-serif;}pre, code {font:115% monospace;*font-size:100%;}body * {line-height:1.22em;}
diff --git a/js2/mwEmbed/jquery/jquery.ui/external/bgiframe/docs/index.html b/js2/mwEmbed/jquery/jquery.ui/external/bgiframe/docs/index.html
new file mode 100644 (file)
index 0000000..2635a57
--- /dev/null
@@ -0,0 +1,113 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+       "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+       <head>
+               <meta http-equiv="Content-type" content="text/html; charset=utf-8">
+               <title>bgiframe 2.1.1 docs</title>
+               <link rel="stylesheet" type="text/css" href="reset-min.css">
+               <link rel="stylesheet" type="text/css" href="fonts-min.css">
+               <style type="text/css" media="screen">
+                       body { margin: 25px; }
+                       h1 { margin: 1.0em 0; font-size: 167%; font-weight: bold; }
+                       #toc { margin: 0 0 3.0em; }
+                               #toc li { margin: 0.4em 0; font-size: 100%; }
+                       #qa { margin: 0 0 3.0em; }
+                               #qa dt.question { margin: 2.0em 0 1.0em; font-size: 122%; font-weight: bold; }
+                               #qa dd.answer { margin: 0 2.0em; }
+                                       #qa dd.answer p { margin: 0 0 1.5em; }
+                                       #qa dd.answer code { font-size: 92%; }
+                                       
+                                       #qa dd.answer #options dt { margin: 2.0em 0 1.0em;  }
+                                       #qa dd.answer #options dd { margin: 0 2.0em; }
+                                       
+               </style>
+       </head>
+       <body>
+               <div id="wrapper">
+                       <div id="container">
+                               <h1>bgiframe 2.1.1</h1>
+                               <ul id="toc">
+                                       <li><a href="#what_does_it_do">What does it do</a></li>
+                                       <li><a href="#when_should_i_use_it">When should I use it</a></li>
+                                       <li><a href="#how_do_i_use_it">How do I use it</a></li>
+                                       <li><a href="#how_does_it_work">How does it work</a></li>
+                                       <li><a href="#where_can_i_get_it">Where can I get it</a></li>
+                                       <li><a href="#what_has_changed">What has changed</a></li>
+                                       <li><a href="#suggestions_bugs_patches">Suggestions? Bugs? Patches?</a></li>
+                               </ul>
+                               <dl id="qa">
+                                       <dt id="what_does_it_do" class="question">What does it do?</dt>
+                                       <dd class="answer">
+                                               <p>Have you ever experienced the select form element z-index issue in Internet Explorer 6? Most likely you have if you've implemented some sort of drop down menu navigation that shows up over a select form element.</p>
+                                               <p>The background iframe (bgiframe) plugin provides a very small, quick and easy way to fix that problem so you don't have to worry about it. No matter the size, borders or position the bgiframe plugin can fix it.</p>
+                                       </dd>
+                                       
+                                       <dt id="when_should_i_use_it" class="question">When should I use it?</dt>
+                                       <dd class="answer">
+                                               <p>The bgiframe plugin should be used when you are trying to show elements above a select form control in Internet Explorer 6.</p>
+                                       </dd>
+                                       
+                                       <dt id="how_do_i_use_it" class="question">How do I use it?</dt>
+                                       <dd class="answer">
+                                               <p>The usage is simple. Just call <code>bgiframe</code> on a jQuery collection of elements.</p>
+                                               <p><code>$('.fix-z-index').bgiframe();</code></p>
+                                               <p>The plugin tries its best to handle most situations but sometimes some configuration is necessary. For example if your borders are defined in a unit other than pixels, you will need to manually set the <code>top</code> and <code>left</code> properties to the negative width of the border. Here are the options/settings available to configure the output.</p>
+                                               <dl id="options">
+                                                       <dt><code>top</code></dt>
+                                                       <dd>
+                                                               <p>The iframe must be offset to the top by the width of the top border. This should be a negative number representing the border-top-width. If a number is is used here, pixels will be assumed. Otherwise, be sure to specify a unit. An expression could also be used. By default the value is "auto" which will use an expression to get the border-top-width if it is in pixels.</p>
+                                                               <p><code>$('.fix-z-index').bgiframe({ top: '-1em' });</code></p>
+                                                       </dd>
+                                                       <dt><code>left</code></dt>
+                                                       <dd>
+                                                               <p>The iframe must be offset to the left by the width of the left border. This should be a negative number representing the border-left-width. If a number is used here, pixels will be assumed. Otherwise, be sure to specify a unit. An expression could also be used. By default the value is "auto" which will use an expression to get the border-left-width if it is in pixels.</p>
+                                                               <p><code>$('.fix-z-index').bgiframe({ left: '-1em' });</code></p>
+                                                       </dd>
+                                                       <dt><code>width</code></dt>
+                                                       <dd>
+                                                               <p>This is the width of the iframe. If a number is used here, pixels will be assume. Otherwise, be sure to specify a unit. An expression could also be used. By default the value is "auto" which will use an expression to get the offsetWidth.</p>
+                                                               <p><code>$('.fix-z-index').bgiframe({ width: 100 });</code></p>
+                                                       </dd>
+                                                       <dt><code>height</code></dt>
+                                                       <dd>
+                                                               <p>This is the height of the iframe. If a number is used here, pixels will be assume. Otherwise, be sure to specify a unit. An expression could also be used. By default the value is "auto" which will use an expression to get the offsetHeight.</p>
+                                                               <p><code>$('.fix-z-index').bgiframe({ height: 100 });</code></p>
+                                                       </dd>
+                                                       <dt><code>opacity</code></dt>
+                                                       <dd>
+                                                               <p>This is a boolean representing whether or not to use opacity. If set to true, the opacity of 0 is applied. If set to false, the opacity filter is not applied. Default: true.</p>
+                                                               <p><code>$('.fix-z-index').bgiframe({ opacity: false });</code></p>
+                                                       </dd>
+                                                       <dt><code>src</code></dt>
+                                                       <dd>
+                                                               <p>This setting is provided so that one could change the src of the iframe to whatever they need. Default: "javascript:false;"</p>
+                                                               <p><code>$('.fix-z-index').bgiframe({ src: '#' });</code></p>
+                                                       </dd>
+                                               </dl>
+                                       </dd>
+
+                                       <dt id="how_does_it_work" class="question">How does it work?</dt>
+                                       <dd class="answer">
+                                               <p>The bgiframe plugin works by prepending an iframe to the element. The iframe is given a class of bgiframe and positioned below all the other children of the element. In the default configuration it automatically adjusts to the width and height of the element (including the borders) and the opacity is set to 0. The element needs to have position (relative or absolute) and should have a background (color or image).</p>
+                                               <p>Check out the <a href="http://brandonaaron.net/jquery/plugins/bgiframe/test/">test page</a> to see the plugin in action.</p>
+                                       </dd>
+
+                                       <dt id="where_can_i_get_it" class="question">Where can I get it?</dt>
+                                       <dd class="answer">
+                                               <ul>
+                                                       <li><a href="http://jquery.com/plugins/files/bgiframe-2.1.zip">2.1 zip</a> from the bgiframe <a href="http://jquery.com/plugins/project/bgiframe">project page</a>.</li>
+                                                       <li>Latest SVN: http://jqueryjs.googlecode.com/svn/trunk/plugins/bgiframe/</li>
+                                                       <li>Tagged Versions in SVN: Latest SVN: http://jqueryjs.googlecode.com/svn/tags/plugins/bgiframe/</li>
+                                               </ul>
+                                       </dd>
+                                       
+                                       <dt id="suggestions_bugs_patches" class="question">Suggestions? Bugs? Patches?</dt>
+                                       <dd class="answer">
+                                               <p>Feel free to make any suggestions, bug reports or add any patches via the <a href="http://jquery.com/plugins/project/bgiframe">project page</a>.</p>
+                                       </dd>
+                               </dl>
+                               <p>The bgiframe plugin is authored by <a href="http://blog.brandonaaron.net/">Brandon Aaron (http://brandonaaron.net/)</a></p>
+                       </div>
+               </div>
+       </body>
+</html>
diff --git a/js2/mwEmbed/jquery/jquery.ui/external/bgiframe/docs/reset-min.css b/js2/mwEmbed/jquery/jquery.ui/external/bgiframe/docs/reset-min.css
new file mode 100644 (file)
index 0000000..bab9886
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+Copyright (c) 2007, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+version: 2.2.2
+*/
+body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}ol,ul {list-style:none;}caption,th {text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym {border:0;}
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/external/bgiframe/jquery.bgiframe.js b/js2/mwEmbed/jquery/jquery.ui/external/bgiframe/jquery.bgiframe.js
new file mode 100644 (file)
index 0000000..df52f50
--- /dev/null
@@ -0,0 +1,100 @@
+/* Copyright (c) 2006 Brandon Aaron (http://brandonaaron.net)
+ * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 
+ * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
+ *
+ * $LastChangedDate: 2007-07-21 18:44:59 -0500 (Sat, 21 Jul 2007) $
+ * $Rev: 2446 $
+ *
+ * Version 2.1.1
+ */
+
+(function($){
+
+/**
+ * The bgiframe is chainable and applies the iframe hack to get 
+ * around zIndex issues in IE6. It will only apply itself in IE6 
+ * and adds a class to the iframe called 'bgiframe'. The iframe
+ * is appeneded as the first child of the matched element(s) 
+ * with a tabIndex and zIndex of -1.
+ * 
+ * By default the plugin will take borders, sized with pixel units,
+ * into account. If a different unit is used for the border's width,
+ * then you will need to use the top and left settings as explained below.
+ *
+ * NOTICE: This plugin has been reported to cause perfromance problems
+ * when used on elements that change properties (like width, height and
+ * opacity) a lot in IE6. Most of these problems have been caused by 
+ * the expressions used to calculate the elements width, height and 
+ * borders. Some have reported it is due to the opacity filter. All 
+ * these settings can be changed if needed as explained below.
+ *
+ * @example $('div').bgiframe();
+ * @before <div><p>Paragraph</p></div>
+ * @result <div><iframe class="bgiframe".../><p>Paragraph</p></div>
+ *
+ * @param Map settings Optional settings to configure the iframe.
+ * @option String|Number top The iframe must be offset to the top
+ *             by the width of the top border. This should be a negative 
+ *       number representing the border-top-width. If a number is 
+ *             is used here, pixels will be assumed. Otherwise, be sure
+ *             to specify a unit. An expression could also be used. 
+ *             By default the value is "auto" which will use an expression 
+ *             to get the border-top-width if it is in pixels.
+ * @option String|Number left The iframe must be offset to the left
+ *             by the width of the left border. This should be a negative 
+ *       number representing the border-left-width. If a number is 
+ *             is used here, pixels will be assumed. Otherwise, be sure
+ *             to specify a unit. An expression could also be used. 
+ *             By default the value is "auto" which will use an expression 
+ *             to get the border-left-width if it is in pixels.
+ * @option String|Number width This is the width of the iframe. If
+ *             a number is used here, pixels will be assume. Otherwise, be sure
+ *             to specify a unit. An experssion could also be used.
+ *             By default the value is "auto" which will use an experssion
+ *             to get the offsetWidth.
+ * @option String|Number height This is the height of the iframe. If
+ *             a number is used here, pixels will be assume. Otherwise, be sure
+ *             to specify a unit. An experssion could also be used.
+ *             By default the value is "auto" which will use an experssion
+ *             to get the offsetHeight.
+ * @option Boolean opacity This is a boolean representing whether or not
+ *             to use opacity. If set to true, the opacity of 0 is applied. If
+ *             set to false, the opacity filter is not applied. Default: true.
+ * @option String src This setting is provided so that one could change 
+ *             the src of the iframe to whatever they need.
+ *             Default: "javascript:false;"
+ *
+ * @name bgiframe
+ * @type jQuery
+ * @cat Plugins/bgiframe
+ * @author Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
+ */
+$.fn.bgIframe = $.fn.bgiframe = function(s) {
+       // This is only for IE6
+       if ( $.browser.msie && /6.0/.test(navigator.userAgent) ) {
+               s = $.extend({
+                       top      : 'auto', // auto == .currentStyle.borderTopWidth
+                       left    : 'auto', // auto == .currentStyle.borderLeftWidth
+                       width   : 'auto', // auto == offsetWidth
+                       height  : 'auto', // auto == offsetHeight
+                       opacity : true,
+                       src     : 'javascript:false;'
+               }, s || {});
+               var prop = function(n){return n&&n.constructor==Number?n+'px':n;},
+                   html = '<iframe class="bgiframe"frameborder="0"tabindex="-1"src="'+s.src+'"'+
+                              'style="display:block;position:absolute;z-index:-1;'+
+                                      (s.opacity !== false?'filter:Alpha(Opacity=\'0\');':'')+
+                                              'top:'+(s.top=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderTopWidth)||0)*-1)+\'px\')':prop(s.top))+';'+
+                                              'left:'+(s.left=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderLeftWidth)||0)*-1)+\'px\')':prop(s.left))+';'+
+                                              'width:'+(s.width=='auto'?'expression(this.parentNode.offsetWidth+\'px\')':prop(s.width))+';'+
+                                              'height:'+(s.height=='auto'?'expression(this.parentNode.offsetHeight+\'px\')':prop(s.height))+';'+
+                                       '"/>';
+               return this.each(function() {
+                       if ( $('> iframe.bgiframe', this).length == 0 )
+                               this.insertBefore( document.createElement(html), this.firstChild );
+               });
+       }
+       return this;
+};
+
+})(jQuery);
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/external/bgiframe/jquery.bgiframe.min.js b/js2/mwEmbed/jquery/jquery.ui/external/bgiframe/jquery.bgiframe.min.js
new file mode 100644 (file)
index 0000000..ef8679d
--- /dev/null
@@ -0,0 +1,10 @@
+/* Copyright (c) 2006 Brandon Aaron (http://brandonaaron.net)
+ * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 
+ * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
+ *
+ * $LastChangedDate: 2007-07-21 18:45:56 -0500 (Sat, 21 Jul 2007) $
+ * $Rev: 2447 $
+ *
+ * Version 2.1.1
+ */
+(function($){$.fn.bgIframe=$.fn.bgiframe=function(s){if($.browser.msie&&/6.0/.test(navigator.userAgent)){s=$.extend({top:'auto',left:'auto',width:'auto',height:'auto',opacity:true,src:'javascript:false;'},s||{});var prop=function(n){return n&&n.constructor==Number?n+'px':n;},html='<iframe class="bgiframe"frameborder="0"tabindex="-1"src="'+s.src+'"'+'style="display:block;position:absolute;z-index:-1;'+(s.opacity!==false?'filter:Alpha(Opacity=\'0\');':'')+'top:'+(s.top=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderTopWidth)||0)*-1)+\'px\')':prop(s.top))+';'+'left:'+(s.left=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderLeftWidth)||0)*-1)+\'px\')':prop(s.left))+';'+'width:'+(s.width=='auto'?'expression(this.parentNode.offsetWidth+\'px\')':prop(s.width))+';'+'height:'+(s.height=='auto'?'expression(this.parentNode.offsetHeight+\'px\')':prop(s.height))+';'+'"/>';return this.each(function(){if($('> iframe.bgiframe',this).length==0)this.insertBefore(document.createElement(html),this.firstChild);});}return this;};})(jQuery);
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/external/bgiframe/jquery.bgiframe.pack.js b/js2/mwEmbed/jquery/jquery.ui/external/bgiframe/jquery.bgiframe.pack.js
new file mode 100644 (file)
index 0000000..90dee9a
--- /dev/null
@@ -0,0 +1,10 @@
+/* Copyright (c) 2006 Brandon Aaron (http://brandonaaron.net)
+ * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 
+ * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
+ *
+ * $LastChangedDate: 2007-07-21 18:44:59 -0500 (Sat, 21 Jul 2007) $
+ * $Rev: 2446 $
+ *
+ * Version 2.1.1
+ */
+eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(b($){$.m.E=$.m.g=b(s){h($.x.10&&/6.0/.I(D.B)){s=$.w({c:\'3\',5:\'3\',8:\'3\',d:\'3\',k:M,e:\'F:i;\'},s||{});C a=b(n){f n&&n.t==r?n+\'4\':n},p=\'<o Y="g"W="0"R="-1"e="\'+s.e+\'"\'+\'Q="P:O;N:L;z-H:-1;\'+(s.k!==i?\'G:J(K=\\\'0\\\');\':\'\')+\'c:\'+(s.c==\'3\'?\'7(((l(2.9.j.A)||0)*-1)+\\\'4\\\')\':a(s.c))+\';\'+\'5:\'+(s.5==\'3\'?\'7(((l(2.9.j.y)||0)*-1)+\\\'4\\\')\':a(s.5))+\';\'+\'8:\'+(s.8==\'3\'?\'7(2.9.S+\\\'4\\\')\':a(s.8))+\';\'+\'d:\'+(s.d==\'3\'?\'7(2.9.v+\\\'4\\\')\':a(s.d))+\';\'+\'"/>\';f 2.T(b(){h($(\'> o.g\',2).U==0)2.V(q.X(p),2.u)})}f 2}})(Z);',62,63,'||this|auto|px|left||expression|width|parentNode||function|top|height|src|return|bgiframe|if|false|currentStyle|opacity|parseInt|fn||iframe|html|document|Number||constructor|firstChild|offsetHeight|extend|browser|borderLeftWidth||borderTopWidth|userAgent|var|navigator|bgIframe|javascript|filter|index|test|Alpha|Opacity|absolute|true|position|block|display|style|tabindex|offsetWidth|each|length|insertBefore|frameborder|createElement|class|jQuery|msie'.split('|'),0,{}))
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/external/bgiframe/test/index.html b/js2/mwEmbed/jquery/jquery.ui/external/bgiframe/test/index.html
new file mode 100644 (file)
index 0000000..82be8e8
--- /dev/null
@@ -0,0 +1,197 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+       "http://www.w3.org/TR/html4/strict.dtd">
+<html debug="true">
+       <head>
+               <meta http-equiv="Content-type" content="text/html; charset=utf-8">
+               <title>jQuery bgiframe Visual Test</title>
+               
+               <!-- load latest build of jquery.js -->
+               <script type="text/javascript" src="../../../jquery/dist/jquery.js"></script>
+
+               <!-- load dimensions.js (this is what we're testing! -->
+               <script type="text/javascript" src="../jquery.bgiframe.js"></script>
+               
+               <!-- load firebug lite 
+               <script type="text/javascript" src="http://brandon.jquery.com/firebuglite/firebug.js"></script>-->
+               
+               <link rel="Stylesheet" media="screen" href="../../../jquery/test/data/testsuite.css" />
+               
+               <script type="text/javascript" charset="utf-8">
+                       $(function() {
+                               $('#userAgent').html(navigator.userAgent);
+                               $('#box2').bgiframe();
+                               $('#box3').bgiframe({top: -5, left: -5});
+                               $('#box4').bgiframe({top: -5, left: -5, width: 270, height: 120});
+                               $('#box5').bgiframe({top: 0, left: 0, width: 260, height: 110});
+                               $('#box6').bgiframe({top: '-5px', left: '-5px', width: '270px', height: '120px'});
+                               $('#box7').bgiframe({top: '-.5em', left: '-.5em', width: '17em', height: '12em'});
+                               $('#box8').bgiframe({top: '-.5em', left: '-.5em'});
+                               $('#box9').bgiframe({opacity:false});
+                       });
+               </script>
+               
+               <style type="text/css" media="screen">
+                       #wrapper { position: relative; width: 100%; font: 12px Arial; }
+                               form { position: absolute; top: 0; left: 0; width: 100%; }
+                                       select { position: relative; width: 100%; margin: 0 0 2px; z-index: 1; }
+                               
+                               .box { position: relative; z-index: 2; float: left; margin: 5px; border: 5px solid #666; padding: 5px; width: 250px; height: 100px; color: #000; background-color: #999; }
+                                       dl { margin: 0; padding: 0; }
+                                               dt { float: left; margin: 0; padding: 0; width: 50px; }
+                                               dd { margin: 0; padding: 0; }
+                               #box7, #box8 { border-width: .5em; padding: .5em; width: 15em; height: 10em; }
+               </style>
+       </head>
+       <body>
+               <h1 id="banner">jQuery bgiframe - Visual Test</h1>
+               <h2 id="userAgent"></h2>
+               <div id="wrapper">
+                       <form action="#" method="get" accept-charset="utf-8">
+                               <select name="test"><option>Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing</option></select>
+                               <select name="test"><option>Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing</option></select>
+                               <select name="test"><option>Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing</option></select>
+                               <select name="test"><option>Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing</option></select>
+                               <select name="test"><option>Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing</option></select>
+                               <select name="test"><option>Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing</option></select>
+                               <select name="test"><option>Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing</option></select>
+                               <select name="test"><option>Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing</option></select>
+                               <select name="test"><option>Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing</option></select>
+                               <select name="test"><option>Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing</option></select>
+                               <select name="test"><option>Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing</option></select>
+                               <select name="test"><option>Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing</option></select>
+                               <select name="test"><option>Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing</option></select>
+                               <select name="test"><option>Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing</option></select>
+                               <select name="test"><option>Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing</option></select>
+                               <select name="test"><option>Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing</option></select>
+                               <select name="test"><option>Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing</option></select>
+                               <select name="test"><option>Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing</option></select>
+                               <select name="test"><option>Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing</option></select>
+                       </form>
+                       
+                       <div id="box1" class="box">nothing</div>
+                       <div id="box2" class="box">
+                               <dl>
+                                       <dt>top:</dt>
+                                       <dd>'auto'</dd>
+                                       
+                                       <dt>left:</dt>
+                                       <dd>'auto'</dd>
+                                       
+                                       <dt>width:</dt>
+                                       <dd>'auto'</dd>
+                                       
+                                       <dt>height:</dt>
+                                       <dd>'auto'</dd>
+                               </dl>
+                       </div>
+                       <div id="box3" class="box">
+                               <dl>
+                                       <dt>top:</dt>
+                                       <dd>0</dd>
+                                       
+                                       <dt>left:</dt>
+                                       <dd>0</dd>
+                                       
+                                       <dt>width:</dt>
+                                       <dd>'auto'</dd>
+                                       
+                                       <dt>height:</dt>
+                                       <dd>'auto'</dd>
+                               </dl>
+                       </div>
+                       <div id="box4" class="box">
+                               <dl>
+                                       <dt>top:</dt>
+                                       <dd>-5</dd>
+                                       
+                                       <dt>left:</dt>
+                                       <dd>-5</dd>
+                                       
+                                       <dt>width:</dt>
+                                       <dd>270</dd>
+                                       
+                                       <dt>height:</dt>
+                                       <dd>120</dd>
+                               </dl>
+                       </div>
+                       <div id="box5" class="box">
+                               <dl>
+                                       <dt>top:</dt>
+                                       <dd>0</dd>
+                                       
+                                       <dt>left:</dt>
+                                       <dd>0</dd>
+                                       
+                                       <dt>width:</dt>
+                                       <dd>260</dd>
+                                       
+                                       <dt>height:</dt>
+                                       <dd>110</dd>
+                               </dl>
+                       </div>
+                       <div id="box6" class="box">
+                               <dl>
+                                       <dt>top:</dt>
+                                       <dd>'-5px'</dd>
+                                       
+                                       <dt>left:</dt>
+                                       <dd>'-5px'</dd>
+                                       
+                                       <dt>width:</dt>
+                                       <dd>'270px'</dd>
+                                       
+                                       <dt>height:</dt>
+                                       <dd>'120px'</dd>
+                               </dl>
+                       </div>
+                       <div id="box7" class="box">
+                               <dl>
+                                       <dt>top:</dt>
+                                       <dd>'-.5em'</dd>
+                                       
+                                       <dt>left:</dt>
+                                       <dd>'-.5em'</dd>
+                                       
+                                       <dt>width:</dt>
+                                       <dd>'17em'</dd>
+                                       
+                                       <dt>height:</dt>
+                                       <dd>'12em'</dd>
+                               </dl>
+                       </div>
+                       <div id="box8" class="box">
+                               <dl>
+                                       <dt>top:</dt>
+                                       <dd>'-.5em'</dd>
+
+                                       <dt>left:</dt>
+                                       <dd>'-.5em'</dd>
+
+                                       <dt>width:</dt>
+                                       <dd>'auto'</dd>
+
+                                       <dt>height:</dt>
+                                       <dd>'auto'</dd>
+                               </dl>
+                       </div>
+                       <div id="box9" class="box">
+                               <dl>
+                                       <dt>top:</dt>
+                                       <dd>'auto'</dd>
+                                       
+                                       <dt>left:</dt>
+                                       <dd>'auto'</dd>
+                                       
+                                       <dt>width:</dt>
+                                       <dd>'auto'</dd>
+                                       
+                                       <dt>height:</dt>
+                                       <dd>'auto'</dd>
+                                       
+                                       <dt>opacity:</dt>
+                                       <dd>false</dd>
+                               </dl>
+                       </div>
+               </div>
+       </body>
+</html>
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/external/cookie/jquery.cookie.min.js b/js2/mwEmbed/jquery/jquery.ui/external/cookie/jquery.cookie.min.js
new file mode 100644 (file)
index 0000000..cb09af9
--- /dev/null
@@ -0,0 +1,10 @@
+/**
+ * Cookie plugin
+ *
+ * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ */
+jQuery.cookie=function(name,value,options){if(typeof value!='undefined'){options=options||{};if(value===null){value='';options=$.extend({},options);options.expires=-1;}var expires='';if(options.expires&&(typeof options.expires=='number'||options.expires.toUTCString)){var date;if(typeof options.expires=='number'){date=new Date();date.setTime(date.getTime()+(options.expires*24*60*60*1000));}else{date=options.expires;}expires='; expires='+date.toUTCString();}var path=options.path?'; path='+(options.path):'';var domain=options.domain?'; domain='+(options.domain):'';var secure=options.secure?'; secure':'';document.cookie=[name,'=',encodeURIComponent(value),expires,path,domain,secure].join('');}else{var cookieValue=null;if(document.cookie&&document.cookie!=''){var cookies=document.cookie.split(';');for(var i=0;i<cookies.length;i++){var cookie=jQuery.trim(cookies[i]);if(cookie.substring(0,name.length+1)==(name+'=')){cookieValue=decodeURIComponent(cookie.substring(name.length+1));break;}}}return cookieValue;}};
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/external/cookie/jquery.cookie.pack.js b/js2/mwEmbed/jquery/jquery.ui/external/cookie/jquery.cookie.pack.js
new file mode 100644 (file)
index 0000000..adf66b7
--- /dev/null
@@ -0,0 +1,10 @@
+/**
+ * Cookie plugin
+ *
+ * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ */
+eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('q.5=x(k,d,a){4(m d!=\'H\'){a=a||{};4(d===p){d=\'\';a=$.A({},a);a.3=-1}2 g=\'\';4(a.3&&(m a.3==\'u\'||a.3.s)){2 f;4(m a.3==\'u\'){f=F C();f.B(f.z()+(a.3*y*o*o*v))}n{f=a.3}g=\'; 3=\'+f.s()}2 b=a.7?\'; 7=\'+(a.7):\'\';2 e=a.9?\'; 9=\'+(a.9):\'\';2 l=a.t?\'; t\':\'\';6.5=[k,\'=\',L(d),g,b,e,l].K(\'\')}n{2 h=p;4(6.5&&6.5!=\'\'){2 c=6.5.E(\';\');D(2 i=0;i<c.8;i++){2 j=q.G(c[i]);4(j.r(0,k.8+1)==(k+\'=\')){h=I(j.r(k.8+1));J}}}w h}};',48,48,'||var|expires|if|cookie|document|path|length|domain|||||||||||||typeof|else|60|null|jQuery|substring|toUTCString|secure|number|1000|return|function|24|getTime|extend|setTime|Date|for|split|new|trim|undefined|decodeURIComponent|break|join|encodeURIComponent'.split('|'),0,{}))
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/external/cookie/jquery.cookie.zip b/js2/mwEmbed/jquery/jquery.ui/external/cookie/jquery.cookie.zip
new file mode 100644 (file)
index 0000000..90f540b
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/external/cookie/jquery.cookie.zip differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/external/jsdiff/jsdiff.js b/js2/mwEmbed/jquery/jquery.ui/external/jsdiff/jsdiff.js
new file mode 100644 (file)
index 0000000..cc3a998
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * Javascript Diff Algorithm
+ *  By John Resig (http://ejohn.org/)
+ *  Modified by Chu Alan "sprite"
+ *
+ * More Info:
+ *  http://ejohn.org/projects/javascript-diff-algorithm/
+ */
+
+function escape(s) {
+       var n = s;
+       n = n.replace(/&/g, "&amp;");
+       n = n.replace(/</g, "&lt;");
+       n = n.replace(/>/g, "&gt;");
+       n = n.replace(/"/g, "&quot;");
+
+       return n;
+}
+
+function diffString( o, n ) {
+  o = o.replace(/\s+$/, '');
+  n = n.replace(/\s+$/, '');
+
+  var out = diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/) );
+  var str = "";
+
+  var oSpace = o.match(/\s+/g);
+  if (oSpace == null) {
+       oSpace = ["\n"];
+  } else {
+       oSpace.push("\n");
+  }
+  var nSpace = n.match(/\s+/g);
+  if (nSpace == null) {
+       nSpace = ["\n"];
+  } else {
+       nSpace.push("\n");
+  }
+
+  if (out.n.length == 0) {
+         for (var i = 0; i < out.o.length; i++) {
+               str += '<del>' + escape(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>' + escape(out.o[n]) + oSpace[n] + "</del>";
+         }
+       }
+
+       for ( var i = 0; i < out.n.length; i++ ) {
+         if (out.n[i].text == null) {
+               str += '<ins>' + escape(out.n[i]) + nSpace[i] + "</ins>";
+         } else {
+               var pre = "";
+
+               for (n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++ ) {
+                 pre += '<del>' + escape(out.o[n]) + oSpace[n] + "</del>";
+               }
+               str += " " + out.n[i].text + nSpace[i] + pre;
+         }
+       }
+  }
+  
+  return str;
+}
+
+function randomColor() {
+       return "rgb(" + (Math.random() * 100) + "%, " + 
+                                       (Math.random() * 100) + "%, " + 
+                                       (Math.random() * 100) + "%)";
+}
+function diffString2( o, n ) {
+  o = o.replace(/\s+$/, '');
+  n = n.replace(/\s+$/, '');
+
+  var out = diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/) );
+
+  var oSpace = o.match(/\s+/g);
+  if (oSpace == null) {
+       oSpace = ["\n"];
+  } else {
+       oSpace.push("\n");
+  }
+  var nSpace = n.match(/\s+/g);
+  if (nSpace == null) {
+       nSpace = ["\n"];
+  } else {
+       nSpace.push("\n");
+  }
+
+  var os = "";
+  var colors = new Array();
+  for (var i = 0; i < out.o.length; i++) {
+         colors[i] = randomColor();
+
+         if (out.o[i].text != null) {
+                 os += '<span style="background-color: ' +colors[i]+ '">' + 
+                               escape(out.o[i].text) + oSpace[i] + "</span>";
+         } else {
+                 os += "<del>" + escape(out.o[i]) + oSpace[i] + "</del>";
+         }
+  }
+
+  var ns = "";
+  for (var i = 0; i < out.n.length; i++) {
+         if (out.n[i].text != null) {
+                 ns += '<span style="background-color: ' +colors[out.n[i].row]+ '">' + 
+                               escape(out.n[i].text) + nSpace[i] + "</span>";
+         } else {
+                 ns += "<ins>" + escape(out.n[i]) + nSpace[i] + "</ins>";
+         }
+  }
+
+  return { o : os , n : ns };
+}
+
+function diff( o, n ) {
+  var ns = new Object();
+  var os = new Object();
+  
+  for ( var i = 0; i < n.length; i++ ) {
+       if ( ns[ n[i] ] == null )
+         ns[ n[i] ] = { rows: new Array(), o: null };
+       ns[ n[i] ].rows.push( i );
+  }
+  
+  for ( var i = 0; i < o.length; i++ ) {
+       if ( os[ o[i] ] == null )
+         os[ o[i] ] = { rows: new Array(), n: null };
+       os[ o[i] ].rows.push( i );
+  }
+  
+  for ( var i in ns ) {
+       if ( ns[i].rows.length == 1 && typeof(os[i]) != "undefined" && 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 ( var 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 ( var 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 };
+}
+
diff --git a/js2/mwEmbed/jquery/jquery.ui/external/qunit/testrunner.js b/js2/mwEmbed/jquery/jquery.ui/external/qunit/testrunner.js
new file mode 100644 (file)
index 0000000..4a408d3
--- /dev/null
@@ -0,0 +1,780 @@
+/*
+ * QUnit - jQuery unit testrunner
+ * 
+ * http://docs.jquery.com/QUnit
+ *
+ * Copyright (c) 2008 John Resig, Jörn Zaefferer
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * $Id: testrunner.js 6173 2009-02-02 20:09:32Z jeresig $
+ */
+
+(function($) {
+
+// Tests for equality any JavaScript type and structure without unexpected results.
+// Discussions and reference: http://philrathe.com/articles/equiv
+// Test suites: http://philrathe.com/tests/equiv
+// Author: Philippe Rathé <prathe@gmail.com>
+var equiv = function () {
+
+       var innerEquiv; // the real equiv function
+       var callers = []; // stack to decide between skip/abort functions
+
+       // Determine what is o.
+       function hoozit(o) {
+               if (typeof o === "string") {
+                       return "string";
+
+               } else if (typeof o === "boolean") {
+                       return "boolean";
+
+               } else if (typeof o === "number") {
+
+                       if (isNaN(o)) {
+                               return "nan";
+                       } else {
+                               return "number";
+                       }
+
+               } else if (typeof o === "undefined") {
+                       return "undefined";
+
+               // consider: typeof null === object
+               } else if (o === null) {
+                       return "null";
+
+               // consider: typeof [] === object
+               } else if (o instanceof Array) {
+                       return "array";
+               
+               // consider: typeof new Date() === object
+               } else if (o instanceof Date) {
+                       return "date";
+
+               // consider: /./ instanceof Object;
+               //                 /./ instanceof RegExp;
+               //                typeof /./ === "function"; // => false in IE and Opera,
+               //                                                                                true in FF and Safari
+               } else if (o instanceof RegExp) {
+                       return "regexp";
+
+               } else if (typeof o === "object") {
+                       return "object";
+
+               } else if (o instanceof Function) {
+                       return "function";
+               }
+       }
+
+       // Call the o related callback with the given arguments.
+       function bindCallbacks(o, callbacks, args) {
+               var prop = hoozit(o);
+               if (prop) {
+                       if (hoozit(callbacks[prop]) === "function") {
+                               return callbacks[prop].apply(callbacks, args);
+                       } else {
+                               return callbacks[prop]; // or undefined
+                       }
+               }
+       }
+
+       var callbacks = function () {
+
+               // for string, boolean, number and null
+               function useStrictEquality(b, a) {
+                       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 hoozit(b) === "date" && a.valueOf() === b.valueOf();
+                       },
+
+                       "regexp": function (b, a) {
+                               return hoozit(b) === "regexp" &&
+                                       a.source === b.source && // the regex itself
+                                       a.global === b.global && // and its modifers (gmi) ...
+                                       a.ignoreCase === b.ignoreCase &&
+                                       a.multiline === b.multiline;
+                       },
+
+                       // - 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;
+                               var len;
+
+                               // b could be an object literal here
+                               if ( ! (hoozit(b) === "array")) {
+                                       return false;
+                               }
+
+                               len = a.length;
+                               if (len !== b.length) { // safe and faster
+                                       return false;
+                               }
+                               for (i = 0; i < len; i++) {
+                                       if( ! innerEquiv(a[i], b[i])) {
+                                               return false;
+                                       }
+                               }
+                               return true;
+                       },
+
+                       "object": function (b, a) {
+                               var i;
+                               var eq = true; // unless we can proove it
+                               var aProperties = [], bProperties = []; // collection of strings
+
+                               // comparing constructors is more strict than using instanceof
+                               if ( a.constructor !== b.constructor) {
+                                       return false;
+                               }
+
+                               // stack constructor before traversing properties
+                               callers.push(a.constructor);
+
+                               for (i in a) { // be strict: don't ensures hasOwnProperty and go deep
+
+                                       aProperties.push(i); // collect a's properties
+
+                                       if ( ! innerEquiv(a[i], b[i])) {
+                                               eq = false;
+                                       }
+                               }
+
+                               callers.pop(); // unstack, we are done
+
+                               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 = Array.prototype.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 (typeof a !== typeof b || a === null || b === null || typeof a === "undefined" || typeof b === "undefined") {
+                               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;
+}(); // equiv
+
+var GETParams = $.map( location.search.slice(1).split('&'), decodeURIComponent ),
+       ngindex = $.inArray("noglobals", GETParams),
+       noglobals = ngindex !== -1;
+
+if( noglobals )
+       GETParams.splice( ngindex, 1 );
+       
+var config = {
+       stats: {
+               all: 0,
+               bad: 0
+       },
+       queue: [],
+       // block until document ready
+       blocking: true,
+       //restrict modules/tests by get parameters
+       filters: GETParams,
+       isLocal: !!(window.location.protocol == 'file:')
+};
+
+// public API as global methods
+$.extend(window, {
+       test: test,
+       module: module,
+       expect: expect,
+       ok: ok,
+       equals: equals,
+       start: start,
+       stop: stop,
+       reset: reset,
+       isLocal: config.isLocal,
+       same: function(a, b, message) {
+               push(equiv(a, b), a, b, message);
+       },
+       QUnit: {
+               equiv: equiv,
+               ok: ok,
+               done: function(failures, total){},
+               log: function(result, message){}
+       },
+       // legacy methods below
+       isSet: isSet,
+       isObj: isObj,
+       compare: function() {
+               throw "compare is deprecated - use same() instead";
+       },
+       compare2: function() {
+               throw "compare2 is deprecated - use same() instead";
+       },
+       serialArray: function() {
+               throw "serialArray is deprecated - use jsDump.parse() instead";
+       },
+       q: q,
+       t: t,
+       url: url,
+       triggerEvent: triggerEvent
+});
+
+$(window).load(function() {
+       $('#userAgent').html(navigator.userAgent);
+       var head = $('<div class="testrunner-toolbar"><label for="filter-pass">Hide passed tests</label></div>').insertAfter("#userAgent");
+       $('<input type="checkbox" id="filter-pass" />').attr("disabled", true).prependTo(head).click(function() {
+               $('li.pass')[this.checked ? 'hide' : 'show']();
+       });
+       $('<input type="checkbox" id="filter-missing">').attr("disabled", true).appendTo(head).click(function() {
+               $("li.fail:contains('missing test - untested code is broken code')").parent('ol').parent('li.fail')[this.checked ? 'hide' : 'show']();
+       });
+       $("#filter-missing").after('<label for="filter-missing">Hide missing tests (untested code is broken code)</label>');
+       runTest();      
+});
+
+function synchronize(callback) {
+       config.queue.push(callback);
+       if(!config.blocking) {
+               process();
+       }
+}
+
+function process() {
+       while(config.queue.length && !config.blocking) {
+               config.queue.shift()();
+       }
+}
+
+function stop(timeout) {
+       config.blocking = true;
+       if (timeout)
+               config.timeout = setTimeout(function() {
+                       QUnit.ok( false, "Test timed out" );
+                       start();
+               }, timeout);
+}
+function start() {
+       // A slight delay, to avoid any current callbacks
+       setTimeout(function() {
+               if(config.timeout)
+                       clearTimeout(config.timeout);
+               config.blocking = false;
+               process();
+       }, 13);
+}
+
+function validTest( name ) {
+       var i = config.filters.length,
+               run = false;
+
+       if( !i )
+               return true;
+       
+       while( i-- ){
+               var filter = config.filters[i],
+                       not = filter.charAt(0) == '!';
+               if( not ) 
+                       filter = filter.slice(1);
+               if( name.indexOf(filter) != -1 )
+                       return !not;
+               if( not )
+                       run = true;
+       }
+       return run;
+}
+
+function runTest() {
+       config.blocking = false;
+       var started = +new Date;
+       config.fixture = document.getElementById('main').innerHTML;
+       config.ajaxSettings = $.ajaxSettings;
+       synchronize(function() {
+               $('<p id="testresult" class="result"/>').html(['Tests completed in ',
+                       +new Date - started, ' milliseconds.<br/>',
+                       '<span class="bad">', config.stats.bad, '</span> tests of <span class="all">', config.stats.all, '</span> failed.']
+                       .join(''))
+                       .appendTo("body");
+               $("#banner").addClass(config.stats.bad ? "fail" : "pass");
+               QUnit.done( config.stats.bad, config.stats.all );
+       });
+}
+
+var pollution;
+
+function saveGlobal(){
+       pollution = [ ];
+       
+       if( noglobals )
+               for( var key in window )
+                       pollution.push(key);
+}
+function checkPollution( name ){
+       var old = pollution;
+       saveGlobal();
+       
+       if( pollution.length > old.length ){
+               ok( false, "Introduced global variable(s): " + diff(old, pollution).join(", ") );
+               config.expected++;
+       }
+}
+
+function diff( clean, dirty ){
+       return $.grep( dirty, function(name){
+               return $.inArray( name, clean ) == -1;
+       });
+}
+
+function test(name, callback) {
+       if(config.currentModule)
+               name = config.currentModule + " module: " + name;
+       var lifecycle = $.extend({
+               setup: function() {},
+               teardown: function() {}
+       }, config.moduleLifecycle);
+       
+       if ( !validTest(name) )
+               return;
+       
+       synchronize(function() {
+               config.assertions = [];
+               config.expected = null;
+               try {
+                       if( !pollution )
+                               saveGlobal();
+                       lifecycle.setup();
+               } catch(e) {
+                       QUnit.ok( false, "Setup failed on " + name + ": " + e.message );
+               }
+       })
+       synchronize(function() {
+               try {
+                       callback();
+               } catch(e) {
+                       if( typeof console != "undefined" && console.error && console.warn ) {
+                               console.error("Test " + name + " died, exception and test follows");
+                               console.error(e);
+                               console.warn(callback.toString());
+                       }
+                       QUnit.ok( false, "Died on test #" + (config.assertions.length + 1) + ": " + e.message );
+                       // else next test will carry the responsibility
+                       saveGlobal();
+               }
+       });
+       synchronize(function() {
+               try {
+                       checkPollution();
+                       lifecycle.teardown();
+               } catch(e) {
+                       QUnit.ok( false, "Teardown failed on " + name + ": " + e.message );
+               }
+       })
+       synchronize(function() {
+               try {
+                       reset();
+               } catch(e) {
+                       if( typeof console != "undefined" && console.error && console.warn ) {
+                               console.error("reset() failed, following Test " + name + ", exception and reset fn follows");
+                               console.error(e);
+                               console.warn(reset.toString());
+                       }
+               }
+               
+               if(config.expected && config.expected != config.assertions.length) {
+                       QUnit.ok( false, "Expected " + config.expected + " assertions, but " + config.assertions.length + " were run" );
+               }
+               
+               var good = 0, bad = 0;
+               var ol  = $("<ol/>").hide();
+               config.stats.all += config.assertions.length;
+               for ( var i = 0; i < config.assertions.length; i++ ) {
+                       var assertion = config.assertions[i];
+                       $("<li/>").addClass(assertion.result ? "pass" : "fail").text(assertion.message || "(no message)").appendTo(ol);
+                       assertion.result ? good++ : bad++;
+               }
+               config.stats.bad += bad;
+       
+               var b = $("<strong/>").html(name + " <b style='color:black;'>(<b class='fail'>" + bad + "</b>, <b class='pass'>" + good + "</b>, " + config.assertions.length + ")</b>")
+               .click(function(){
+                       $(this).next().toggle();
+               })
+               .dblclick(function(event) {
+                       var target = $(event.target).filter("strong").clone();
+                       if ( target.length ) {
+                               target.children().remove();
+                               location.href = location.href.match(/^(.+?)(\?.*)?$/)[1] + "?" + encodeURIComponent($.trim(target.text()));
+                       }
+               });
+               
+               $("<li/>").addClass(bad ? "fail" : "pass").append(b).append(ol).appendTo("#tests");
+       
+               if(bad) {
+                       $("#filter-pass").attr("disabled", null);
+                       $("#filter-missing").attr("disabled", null);
+               }
+       });
+}
+
+// call on start of module test to prepend name to all tests
+function module(name, lifecycle) {
+       config.currentModule = name;
+       config.moduleLifecycle = lifecycle;
+}
+
+/**
+ * Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through.
+ */
+function expect(asserts) {
+       config.expected = asserts;
+}
+
+/**
+ * Resets the test setup. Useful for tests that modify the DOM.
+ */
+function reset() {
+       $("#main").html( config.fixture );
+       $.event.global = {};
+       $.ajaxSettings = $.extend({}, config.ajaxSettings);
+}
+
+/**
+ * Asserts true.
+ * @example ok( $("a").size() > 5, "There must be at least 5 anchors" );
+ */
+function ok(a, msg) {
+       QUnit.log(a, msg);
+
+       config.assertions.push({
+               result: !!a,
+               message: msg
+       });
+}
+
+/**
+ * Asserts that two arrays are the same
+ */
+function isSet(a, b, msg) {
+       function serialArray( a ) {
+               var r = [];
+               
+               if ( a && a.length )
+                       for ( var i = 0; i < a.length; i++ ) {
+                               var str = a[i].nodeName;
+                               if ( str ) {
+                                       str = str.toLowerCase();
+                                       if ( a[i].id )
+                                               str += "#" + a[i].id;
+                               } else
+                                       str = a[i];
+                               r.push( str );
+                       }
+       
+               return "[ " + r.join(", ") + " ]";
+       }
+       var ret = true;
+       if ( a && b && a.length != undefined && a.length == b.length ) {
+               for ( var i = 0; i < a.length; i++ )
+                       if ( a[i] != b[i] )
+                               ret = false;
+       } else
+               ret = false;
+       QUnit.ok( ret, !ret ? (msg + " expected: " + serialArray(b) + " result: " + serialArray(a)) : msg );
+}
+
+/**
+ * Asserts that two objects are equivalent
+ */
+function isObj(a, b, msg) {
+       var ret = true;
+       
+       if ( a && b ) {
+               for ( var i in a )
+                       if ( a[i] != b[i] )
+                               ret = false;
+
+               for ( i in b )
+                       if ( a[i] != b[i] )
+                               ret = false;
+       } else
+               ret = false;
+
+       QUnit.ok( ret, msg );
+}
+
+/**
+ * Returns an array of elements with the given IDs, eg.
+ * @example q("main", "foo", "bar")
+ * @result [<div id="main">, <span id="foo">, <input id="bar">]
+ */
+function q() {
+       var r = [];
+       for ( var i = 0; i < arguments.length; i++ )
+               r.push( document.getElementById( arguments[i] ) );
+       return r;
+}
+
+/**
+ * Asserts that a select matches the given IDs
+ * @example t("Check for something", "//[a]", ["foo", "baar"]);
+ * @result returns true if "//[a]" return two elements with the IDs 'foo' and 'baar'
+ */
+function t(a,b,c) {
+       var f = $(b);
+       var s = "";
+       for ( var i = 0; i < f.length; i++ )
+               s += (s && ",") + '"' + f[i].id + '"';
+       isSet(f, q.apply(q,c), a + " (" + b + ")");
+}
+
+/**
+ * Add random number to url to stop IE from caching
+ *
+ * @example url("data/test.html")
+ * @result "data/test.html?10538358428943"
+ *
+ * @example url("data/test.php?foo=bar")
+ * @result "data/test.php?foo=bar&10538358345554"
+ */
+function url(value) {
+       return value + (/\?/.test(value) ? "&" : "?") + new Date().getTime() + "" + parseInt(Math.random()*100000);
+}
+
+/**
+ * Checks that the first two arguments are equal, with an optional message.
+ * Prints out both actual and expected values.
+ *
+ * Prefered to ok( actual == expected, message )
+ *
+ * @example equals( $.format("Received {0} bytes.", 2), "Received 2 bytes." );
+ *
+ * @param Object actual
+ * @param Object expected
+ * @param String message (optional)
+ */
+function equals(actual, expected, message) {
+       push(expected == actual, actual, expected, message);
+}
+
+function push(result, actual, expected, message) {
+       message = message || (result ? "okay" : "failed");
+       QUnit.ok( result, result ? message + ": " + expected : message + ", expected: " + jsDump.parse(expected) + " result: " + jsDump.parse(actual) );
+}
+
+/**
+ * Trigger an event on an element.
+ *
+ * @example triggerEvent( document.body, "click" );
+ *
+ * @param DOMElement elem
+ * @param String type
+ */
+function triggerEvent( elem, type, event ) {
+       if ( $.browser.mozilla || $.browser.opera ) {
+               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 ( $.browser.msie ) {
+               elem.fireEvent("on"+type);
+       }
+}
+
+})(jQuery);
+
+/**
+ * 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}
+ */
+(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 ){
+               var i = arr.length,     ret = Array(i);                                 
+               this.up();
+               while( i-- )
+                       ret[i] = this.parse( arr[i] );                          
+               this.down();
+               return join( '[', ret, ']' );
+       };
+       
+       var reName = /^function (\w+)/;
+       
+       var jsDump = window.jsDump = {
+               parse:function( obj, type ){//type is used mostly internally, you can fix a (custom)type in advance
+                       var     parser = this.parsers[ type || this.typeOf(obj) ];
+                       type = typeof parser;                   
+                       
+                       return type == 'function' ? parser.call( this, obj ) :
+                                  type == 'string' ? parser :
+                                  this.parsers.error;
+               },
+               typeOf:function( obj ){
+                       var type = typeof obj,
+                               f = 'function';//we'll use it 3 times, save it
+                       return type != 'object' && type != f ? type :
+                               !obj ? 'null' :
+                               obj.exec ? 'regexp' :// some browsers (FF) consider regexps functions
+                               obj.getHours ? 'date' :
+                               obj.scrollBy ?  'window' :
+                               obj.nodeName == '#document' ? 'document' :
+                               obj.nodeName ? 'node' :
+                               obj.item ? 'nodelist' : // Safari reports nodelists as functions
+                               obj.callee ? 'arguments' :
+                               obj.call || obj.constructor != Array && //an array would also fall on this hack
+                                       (obj+'').indexOf(f) != -1 ? f : //IE reports functions like alert, as objects
+                               'length' in obj ? 'array' :
+                               type;
+               },
+               separator:function(){
+                       return this.multiline ? this.HTML ? '<br />' : '\n' : this.HTML ? '&nbsp;' : ' ';
+               },
+               indent:function( extra ){// extra can be a number, shortcut for increasing-calling-decreasing
+                       if( !this.multiline )
+                               return '';
+                       var chr = this.indentChar;
+                       if( this.HTML )
+                               chr = chr.replace(/\t/g,'   ').replace(/ /g,'&nbsp;');
+                       return 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:'[ERROR]', //when no parser is found, shouldn't happen
+                       unknown: '[Unknown]',
+                       'null':'null',
+                       undefined:'undefined',
+                       'function':function( fn ){
+                               var ret = 'function',
+                                       name = 'name' in fn ? fn.name : (reName.exec(fn)||[])[1];//functions never have name in IE
+                               if( name )
+                                       ret += ' ' + name;
+                               ret += '(';
+                               
+                               ret = [ ret, this.parse( fn, 'functionArgs' ), '){'].join('');
+                               return join( ret, this.parse(fn,'functionCode'), '}' );
+                       },
+                       array: array,
+                       nodelist: array,
+                       arguments: array,
+                       object:function( map ){
+                               var ret = [ ];
+                               this.up();
+                               for( var key in map )
+                                       ret.push( this.parse(key,'key') + ': ' + this.parse(map[key]) );
+                               this.down();
+                               return join( '{', ret, '}' );
+                       },
+                       node:function( node ){
+                               var open = this.HTML ? '&lt;' : '<',
+                                       close = this.HTML ? '&gt;' : '>';
+                                       
+                               var tag = node.nodeName.toLowerCase(),
+                                       ret = open + tag;
+                                       
+                               for( var a in this.DOMAttrs ){
+                                       var val = node[this.DOMAttrs[a]];
+                                       if( val )
+                                               ret += ' ' + a + '=' + this.parse( val, 'attribute' );
+                               }
+                               return ret + close + open + '/' + tag + close;
+                       },
+                       functionArgs:function( fn ){//function calls it internally, it's the arguments part of the function
+                               var l = fn.length;
+                               if( !l ) return '';                             
+                               
+                               var args = Array(l);
+                               while( l-- )
+                                       args[l] = String.fromCharCode(97+l);//97 is 'a'
+                               return ' ' + args.join(', ') + ' ';
+                       },
+                       key:quote, //object calls it internally, the key part of an item in a map
+                       functionCode:'[code]', //function calls it internally, it's the content of the function
+                       attribute:quote, //node calls it internally, it's an html attribute value
+                       string:quote,
+                       date:quote,
+                       regexp:literal, //regex
+                       number:literal,
+                       'boolean':literal
+               },
+               DOMAttrs:{//attributes to dump from nodes, name=>realName
+                       id:'id',
+                       name:'name',
+                       'class':'className'
+               },
+               HTML:false,//if true, entities are escaped ( <, >, \t, space and \n )
+               indentChar:'   ',//indentation unit
+               multiline:true //if true, items in a collection, are separated by a \n, else just a space.
+       };
+
+})();
diff --git a/js2/mwEmbed/jquery/jquery.ui/external/qunit/testsuite.css b/js2/mwEmbed/jquery/jquery.ui/external/qunit/testsuite.css
new file mode 100644 (file)
index 0000000..dbfc43a
--- /dev/null
@@ -0,0 +1,120 @@
+body, div, h1 { font-family: 'trebuchet ms', verdana, arial; margin: 0; padding: 0 }
+body {font-size: 10pt; }
+h1 { padding: 15px; font-size: large; background-color: #06b; color: white; }
+h1 a { color: white; }
+h2 { padding: 10px; background-color: #eee; color: black; margin: 0; font-size: small; font-weight: normal }
+
+.pass { color: green; } 
+.fail { color: red; } 
+p.result { margin-left: 1em; }
+
+#banner { height: 2em; border-bottom: 1px solid white; }
+h2.pass { background-color: green; }
+h2.fail { background-color: red; }
+
+div.testrunner-toolbar { background: #eee; border-top: 1px solid black; padding: 10px; }
+
+ol#tests > li > strong { cursor:pointer; }
+
+div#fx-tests h4 {
+       background: red;
+}
+
+div#fx-tests h4.pass {
+       background: green;
+}
+
+div#fx-tests div.box {
+       background: red url(data/cow.jpg) no-repeat;
+       overflow: hidden;
+       border: 2px solid #000;
+}
+
+div#fx-tests div.overflow {
+       overflow: visible;
+}
+
+div.inline {
+       display: inline;
+}
+
+div.autoheight {
+       height: auto;
+}
+
+div.autowidth {
+       width: auto;
+}
+
+div.autoopacity {
+       opacity: auto;
+}
+
+div.largewidth {
+       width: 100px;
+}
+
+div.largeheight {
+       height: 100px;
+}
+
+div.largeopacity {
+       filter: progid:DXImageTransform.Microsoft.Alpha(opacity=100);
+}
+
+div.medwidth {
+       width: 50px;
+}
+
+div.medheight {
+       height: 50px;
+}
+
+div.medopacity {
+       opacity: 0.5;
+       filter: progid:DXImageTransform.Microsoft.Alpha(opacity=50);
+}
+
+div.nowidth {
+       width: 0px;
+}
+
+div.noheight {
+       height: 0px;
+}
+
+div.noopacity {
+       opacity: 0;
+       filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0);
+}
+
+div.hidden {
+       display: none;
+}
+
+div#fx-tests div.widewidth {
+       background-repeat: repeat-x;
+}
+
+div#fx-tests div.wideheight {
+       background-repeat: repeat-y;
+}
+
+div#fx-tests div.widewidth.wideheight {
+       background-repeat: repeat;
+}
+
+div#fx-tests div.noback {
+       background-image: none;
+}
+
+div.chain, div.chain div { width: 100px; height: 20px; position: relative; float: left; }
+div.chain div { position: absolute; top: 0px; left: 0px; }
+
+div.chain.test { background: red; }
+div.chain.test div { background: green; }
+
+div.chain.out { background: green; }
+div.chain.out div { background: red; display: none; }
+
+div#show-tests * { display: none; }
diff --git a/js2/mwEmbed/jquery/jquery.ui/external/simulate/jquery.simulate.js b/js2/mwEmbed/jquery/jquery.ui/external/simulate/jquery.simulate.js
new file mode 100644 (file)
index 0000000..d52140b
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * jquery.simulate - simulate browser mouse and keyboard events
+ *
+ * Copyright (c) 2009 Eduardo Lundgren (eduardolundgren@gmail.com)
+ * and Richard D. Worth (rdworth@gmail.com)
+ *
+ * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 
+ * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
+ *
+ */
+
+;(function($) {
+
+$.fn.extend({
+       simulate: function(type, options) {
+               return this.each(function() {
+                       var opt = $.extend({}, $.simulate.defaults, options || {});
+                       new $.simulate(this, type, opt);
+               });
+       }
+});
+
+$.simulate = function(el, type, options) {
+       this.target = el;
+       this.options = options;
+
+       if (/^drag$/.test(type)) {
+               this[type].apply(this, [this.target, options]);
+       } else {
+               this.simulateEvent(el, type, options);
+       }
+}
+
+$.extend($.simulate.prototype, {
+       simulateEvent: function(el, type, options) {
+               var evt = this.createEvent(type, options);
+               this.dispatchEvent(el, type, evt, options);
+               return evt;
+       },
+       createEvent: function(type, options) {
+               if (/^mouse(over|out|down|up|move)|(dbl)?click$/.test(type)) {
+                       return this.mouseEvent(type, options);
+               } else if (/^key(up|down|press)$/.test(type)) {
+                       return this.keyboardEvent(type, options);
+               }
+       },
+       mouseEvent: function(type, options) {
+               var evt;
+               var e = $.extend({
+                       bubbles: true, cancelable: (type != "mousemove"), view: window, detail: 0,
+                       screenX: 0, screenY: 0, clientX: 0, clientY: 0,
+                       ctrlKey: false, altKey: false, shiftKey: false, metaKey: false,
+                       button: 0, relatedTarget: undefined
+               }, options);
+
+               var relatedTarget = $(e.relatedTarget)[0];
+
+               if ($.isFunction(document.createEvent)) {
+                       evt = document.createEvent("MouseEvents");
+                       evt.initMouseEvent(type, e.bubbles, e.cancelable, e.view, e.detail,
+                               e.screenX, e.screenY, e.clientX, e.clientY,
+                               e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
+                               e.button, e.relatedTarget || document.body.parentNode);
+               } else if (document.createEventObject) {
+                       evt = document.createEventObject();
+                       $.extend(evt, e);
+                       evt.button = { 0:1, 1:4, 2:2 }[evt.button] || evt.button;
+               }
+               return evt;
+       },
+       keyboardEvent: function(type, options) {
+               var evt;
+
+               var e = $.extend({ bubbles: true, cancelable: true, view: window,
+                       ctrlKey: false, altKey: false, shiftKey: false, metaKey: false,
+                       keyCode: 0, charCode: 0
+               }, options);
+
+               if ($.isFunction(document.createEvent)) {
+                       try {
+                               evt = document.createEvent("KeyEvents");
+                               evt.initKeyEvent(type, e.bubbles, e.cancelable, e.view,
+                                       e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
+                                       e.keyCode, e.charCode);
+                       } catch(err) {
+                               evt = document.createEvent("Events");
+                               evt.initEvent(type, e.bubbles, e.cancelable);
+                               $.extend(evt, { view: e.view,
+                                       ctrlKey: e.ctrlKey, altKey: e.altKey, shiftKey: e.shiftKey, metaKey: e.metaKey,
+                                       keyCode: e.keyCode, charCode: e.charCode
+                               });
+                       }
+               } else if (document.createEventObject) {
+                       evt = document.createEventObject();
+                       $.extend(evt, e);
+               }
+               if ($.browser.msie || $.browser.opera) {
+                       evt.keyCode = (e.charCode > 0) ? e.charCode : e.keyCode;
+                       evt.charCode = undefined;
+               }
+               return evt;
+       },
+
+       dispatchEvent: function(el, type, evt) {
+               if (el.dispatchEvent) {
+                       el.dispatchEvent(evt);
+               } else if (el.fireEvent) {
+                       el.fireEvent('on' + type, evt);
+               }
+               return evt;
+       },
+
+       drag: function(el) {
+               var self = this, center = this.findCenter(this.target), 
+                       options = this.options, x = Math.floor(center.x), y = Math.floor(center.y), 
+                       dx = options.dx || 0, dy = options.dy || 0, target = this.target;
+               var coord = { clientX: x, clientY: y };
+               this.simulateEvent(target, "mousedown", coord);
+               coord = { clientX: x + 1, clientY: y + 1 };
+               this.simulateEvent(document, "mousemove", coord);
+               coord = { clientX: x + dx, clientY: y + dy };
+               this.simulateEvent(document, "mousemove", coord);
+               this.simulateEvent(document, "mousemove", coord);
+               this.simulateEvent(target, "mouseup", coord);
+       },
+       findCenter: function(el) {
+               var el = $(this.target), o = el.offset();
+               return {
+                       x: o.left + el.outerWidth() / 2,
+                       y: o.top + el.outerHeight() / 2
+               };
+       }
+});
+
+$.extend($.simulate, {
+       defaults: {
+               speed: 'sync'
+       },
+       VK_TAB: 9,
+       VK_ENTER: 13,
+       VK_ESC: 27,
+       VK_PGUP: 33,
+       VK_PGDN: 34,
+       VK_END: 35,
+       VK_HOME: 36,
+       VK_LEFT: 37,
+       VK_UP: 38,
+       VK_RIGHT: 39,
+       VK_DOWN: 40
+});
+
+})(jQuery);
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_diagonals-thick_20_666666_40x40.png b/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_diagonals-thick_20_666666_40x40.png
new file mode 100644 (file)
index 0000000..64ece57
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_diagonals-thick_20_666666_40x40.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_flat_0_aaaaaa_40x100.png b/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_flat_0_aaaaaa_40x100.png
new file mode 100644 (file)
index 0000000..5b5dab2
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_flat_0_aaaaaa_40x100.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_glass_55_fbf9ee_1x400.png b/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_glass_55_fbf9ee_1x400.png
new file mode 100644 (file)
index 0000000..ad3d634
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_glass_55_fbf9ee_1x400.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_glass_65_ffffff_1x400.png b/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_glass_65_ffffff_1x400.png
new file mode 100644 (file)
index 0000000..42ccba2
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_glass_65_ffffff_1x400.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_glass_75_dadada_1x400.png b/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_glass_75_dadada_1x400.png
new file mode 100644 (file)
index 0000000..5a46b47
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_glass_75_dadada_1x400.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_glass_75_e6e6e6_1x400.png b/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_glass_75_e6e6e6_1x400.png
new file mode 100644 (file)
index 0000000..86c2baa
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_glass_75_e6e6e6_1x400.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_glass_75_ffffff_1x400.png b/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_glass_75_ffffff_1x400.png
new file mode 100644 (file)
index 0000000..e65ca12
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_glass_75_ffffff_1x400.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png
new file mode 100644 (file)
index 0000000..7c9fa6c
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_inset-soft_95_fef1ec_1x100.png b/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_inset-soft_95_fef1ec_1x100.png
new file mode 100644 (file)
index 0000000..0e05810
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-bg_inset-soft_95_fef1ec_1x100.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-icons_222222_256x240.png b/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-icons_222222_256x240.png
new file mode 100644 (file)
index 0000000..67560da
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-icons_222222_256x240.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-icons_2e83ff_256x240.png b/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-icons_2e83ff_256x240.png
new file mode 100644 (file)
index 0000000..b2c9052
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-icons_2e83ff_256x240.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-icons_454545_256x240.png b/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-icons_454545_256x240.png
new file mode 100644 (file)
index 0000000..0cd64a2
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-icons_454545_256x240.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-icons_888888_256x240.png b/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-icons_888888_256x240.png
new file mode 100644 (file)
index 0000000..2e5180e
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-icons_888888_256x240.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-icons_cd0a0a_256x240.png b/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-icons_cd0a0a_256x240.png
new file mode 100644 (file)
index 0000000..2db88b7
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/base/images/ui-icons_cd0a0a_256x240.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/base/jquery-ui-1.7.1.custom.css b/js2/mwEmbed/jquery/jquery.ui/themes/base/jquery-ui-1.7.1.custom.css
new file mode 100644 (file)
index 0000000..118def2
--- /dev/null
@@ -0,0 +1,287 @@
+\r
+/*\r
+* jQuery UI CSS Framework\r
+* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)\r
+* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.\r
+* To view and modify this theme, visit http://jqueryui.com/themeroller/\r
+*/\r
+\r
+/*** Begin CORE ***/\r
+\r
+/* Layout helpers\r
+----------------------------------*/\r
+.ui-helper-hidden { display: none; }\r
+.ui-helper-hidden-accessible { position: absolute; left: -99999999px; }\r
+.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }\r
+.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }\r
+.ui-helper-clearfix { display: inline-block; }\r
+/* required comment for clearfix to work in Opera \*/\r
+* html .ui-helper-clearfix { height:1%; }\r
+.ui-helper-clearfix { display:block; }\r
+/* end clearfix */\r
+.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }*/\r
+\r
+\r
+/* Interaction Cues\r
+----------------------------------*/\r
+.ui-state-disabled { cursor: default !important; }\r
+\r
+\r
+/* Icons\r
+----------------------------------*/\r
+\r
+/* states and images */\r
+.ui-icon { display: block; text-indents: -99999px; overflow: hidden; background-repeat: no-repeat; }\r
+\r
+\r
+/* Misc visuals\r
+----------------------------------*/\r
+\r
+/* Overlays */\r
+.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }\r
+\r
+/*** End Core ***/\r
+\r
+\r
+/*** Begin THEME ***/\r
+\r
+/* Component containers\r
+----------------------------------*/\r
+.ui-widget { font-family: Arial,sans-serif/*{ffDefault}*/; font-size: 11px/*{fsDefault}*/; }\r
+.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Arial,sans-serif/*{ffDefault}*/; font-size: 11px; }\r
+.ui-widget-content { border: none/*{borderColorContent}*/; background: #ffffff/*{bgColorContent}*/ url(images/ui-bg_flat_75_ffffff_40x100.png) 50%/*{bgContentXPos}*/ 50%/*{bgContentYPos}*/ repeat-x/*{bgContentRepeat}*//*{bgContentRepeat}*/; color: #A9A9A9/*{fcContent}*/; }\r
+.ui-widget-content a { color: #A9A9A9/*{fcContent}*/; }\r
+.ui-widget-header { border: none/*{borderColorHeader}*/; background: #cccccc/*{bgColorHeader}*/ url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50%/*{bgHeaderXPos}*/ 50%/*{bgHeaderYPos}*/ repeat-x/*{bgHeaderRepeat}*//*{bgHeaderRepeat}*/; color: #565656/*{fcHeader}*/; font-weight: bold; }\r
+.ui-widget-header a { color: #000/*{fcHeader}*/; }\r
+\r
+\r
+\r
+/* Interaction states\r
+----------------------------------*/\r
+.ui-state-default, .ui-widget-content .ui-state-default { border: none/*{borderColorDefault}*/; background: none/*{bgColorDefault}*/ /*{bgDefaultXPos}*/ /*{bgDefaultYPos}*/ /*{bgDefaultRepeat}*//*{bgDefaultRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #333/*{fcDefault}*/; outline: none; }\r
+.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #000/*{fcDefault}*/; text-decoration: none; outline: none; }\r
+.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: none/*{borderColorHover}*/; background: none/*{bgColorHover}*/ none /*{bgHoverXPos}*/ /*{bgHoverYPos}*/ /*{bgHoverRepeat}*//*{bgHoverRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #222/*{fcHover}*/; outline: none; }\r
+.ui-state-hover a, .ui-state-hover a:hover { color: #000/*{fcHover}*/; text-decoration: none; outline: none; }\r
+.ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #ccc/*{borderColorActive}*/; background: none/*{bgColorActive}*/ /*{bgActiveXPos}*/ 50%/*{bgActiveYPos}*/ repeat-x/*{bgActiveRepeat}*//*{bgActiveRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcActive}*/; outline: none; }\r
+.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121/*{fcActive}*/; outline: none; text-decoration: none; }\r
+\r
+/* Interaction Cues\r
+----------------------------------*/\r
+.ui-state-highlight, .ui-widget-content .ui-state-highlight {border: 1px solid #fcefa1/*{borderColorHighlight}*/; background: #fbf9ee/*{bgColorHighlight}*/ url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50%/*{bgHighlightXPos}*/ 50%/*{bgHighlightYPos}*/ repeat-x/*{bgHighlightRepeat}*//*{bgHighlightRepeat}*/; color: #363636/*{fcHighlight}*/; }\r
+.ui-state-highlight a, .ui-widget-content .ui-state-highlight a { color: #363636/*{fcHighlight}*/; }\r
+.ui-state-error, .ui-widget-content .ui-state-error {border: 1px solid #cd0a0a/*{borderColorError}*/; background: #fef1ec/*{bgColorError}*/ url(images/ui-bg_glass_95_fef1ec_1x400.png) 50%/*{bgErrorXPos}*/ 50%/*{bgErrorYPos}*/ repeat-x/*{bgErrorRepeat}*//*{bgErrorRepeat}*/; color: #cd0a0a/*{fcError}*/; }\r
+.ui-state-error a, .ui-widget-content .ui-state-error a { color: #cd0a0a/*{fcError}*/; }\r
+.ui-state-error-text, .ui-widget-content .ui-state-error-text { color: #cd0a0a/*{fcError}*/; }\r
+.ui-state-disabled, .ui-widget-content .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }\r
+.ui-priority-primary, .ui-widget-content .ui-priority-primary { font-weight: bold; }\r
+.ui-priority-secondary, .ui-widget-content .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }\r
+\r
+/* Icons\r
+----------------------------------*/\r
+\r
+/* states and images */\r
+.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; }\r
+.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; }\r
+.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsHeader}*/; }\r
+.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png)/*{iconsDefault}*/; }\r
+.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png)/*{iconsHover}*/; }\r
+.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png)/*{iconsActive}*/; }\r
+.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png)/*{iconsHighlight}*/; }\r
+.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png)/*{iconsError}*/; }\r
+\r
+/* positioning */\r
+.ui-icon-carat-1-n { background-position: 0 0; }\r
+.ui-icon-carat-1-ne { background-position: -16px 0; }\r
+.ui-icon-carat-1-e { background-position: -32px 0; }\r
+.ui-icon-carat-1-se { background-position: -48px 0; }\r
+.ui-icon-carat-1-s { background-position: -64px 0; }\r
+.ui-icon-carat-1-sw { background-position: -80px 0; }\r
+.ui-icon-carat-1-w { background-position: -96px 0; }\r
+.ui-icon-carat-1-nw { background-position: -112px 0; }\r
+.ui-icon-carat-2-n-s { background-position: -128px 0; }\r
+.ui-icon-carat-2-e-w { background-position: -144px 0; }\r
+.ui-icon-triangle-1-n { background-position: 0 -16px; }\r
+.ui-icon-triangle-1-ne { background-position: -16px -16px; }\r
+.ui-icon-triangle-1-e { background-position: -32px -16px; }\r
+.ui-icon-triangle-1-se { background-position: -48px -16px; }\r
+.ui-icon-triangle-1-s { background-position: -64px -16px; }\r
+.ui-icon-triangle-1-sw { background-position: -80px -16px; }\r
+.ui-icon-triangle-1-w { background-position: -96px -16px; }\r
+.ui-icon-triangle-1-nw { background-position: -112px -16px; }\r
+.ui-icon-triangle-2-n-s { background-position: -128px -16px; }\r
+.ui-icon-triangle-2-e-w { background-position: -144px -16px; }\r
+.ui-icon-arrow-1-n { background-position: 0 -32px; }\r
+.ui-icon-arrow-1-ne { background-position: -16px -32px; }\r
+.ui-icon-arrow-1-e { background-position: -32px -32px; }\r
+.ui-icon-arrow-1-se { background-position: -48px -32px; }\r
+.ui-icon-arrow-1-s { background-position: -64px -32px; }\r
+.ui-icon-arrow-1-sw { background-position: -80px -32px; }\r
+.ui-icon-arrow-1-w { background-position: -96px -32px; }\r
+.ui-icon-arrow-1-nw { background-position: -112px -32px; }\r
+.ui-icon-arrow-2-n-s { background-position: -128px -32px; }\r
+.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }\r
+.ui-icon-arrow-2-e-w { background-position: -160px -32px; }\r
+.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }\r
+.ui-icon-arrowstop-1-n { background-position: -192px -32px; }\r
+.ui-icon-arrowstop-1-e { background-position: -208px -32px; }\r
+.ui-icon-arrowstop-1-s { background-position: -224px -32px; }\r
+.ui-icon-arrowstop-1-w { background-position: -240px -32px; }\r
+.ui-icon-arrowthick-1-n { background-position: 0 -48px; }\r
+.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }\r
+.ui-icon-arrowthick-1-e { background-position: -32px -48px; }\r
+.ui-icon-arrowthick-1-se { background-position: -48px -48px; }\r
+.ui-icon-arrowthick-1-s { background-position: -64px -48px; }\r
+.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }\r
+.ui-icon-arrowthick-1-w { background-position: -96px -48px; }\r
+.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }\r
+.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }\r
+.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }\r
+.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }\r
+.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }\r
+.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }\r
+.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }\r
+.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }\r
+.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }\r
+.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }\r
+.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }\r
+.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }\r
+.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }\r
+.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }\r
+.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }\r
+.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }\r
+.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }\r
+.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }\r
+.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }\r
+.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }\r
+.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }\r
+.ui-icon-arrow-4 { background-position: 0 -80px; }\r
+.ui-icon-arrow-4-diag { background-position: -16px -80px; }\r
+.ui-icon-extlink { background-position: -32px -80px; }\r
+.ui-icon-newwin { background-position: -48px -80px; }\r
+.ui-icon-refresh { background-position: -64px -80px; }\r
+.ui-icon-shuffle { background-position: -80px -80px; }\r
+.ui-icon-transfer-e-w { background-position: -96px -80px; }\r
+.ui-icon-transferthick-e-w { background-position: -112px -80px; }\r
+.ui-icon-folder-collapsed { background-position: 0 -96px; }\r
+.ui-icon-folder-open { background-position: -16px -96px; }\r
+.ui-icon-document { background-position: -32px -96px; }\r
+.ui-icon-document-b { background-position: -48px -96px; }\r
+.ui-icon-note { background-position: -64px -96px; }\r
+.ui-icon-mail-closed { background-position: -80px -96px; }\r
+.ui-icon-mail-open { background-position: -96px -96px; }\r
+.ui-icon-suitcase { background-position: -112px -96px; }\r
+.ui-icon-comment { background-position: -128px -96px; }\r
+.ui-icon-person { background-position: -144px -96px; }\r
+.ui-icon-print { background-position: -160px -96px; }\r
+.ui-icon-trash { background-position: -176px -96px; }\r
+.ui-icon-locked { background-position: -192px -96px; }\r
+.ui-icon-unlocked { background-position: -208px -96px; }\r
+.ui-icon-bookmark { background-position: -224px -96px; }\r
+.ui-icon-tag { background-position: -240px -96px; }\r
+.ui-icon-home { background-position: 0 -112px; }\r
+.ui-icon-flag { background-position: -16px -112px; }\r
+.ui-icon-calendar { background-position: -32px -112px; }\r
+.ui-icon-cart { background-position: -48px -112px; }\r
+.ui-icon-pencil { background-position: -64px -112px; }\r
+.ui-icon-clock { background-position: -80px -112px; }\r
+.ui-icon-disk { background-position: -96px -112px; }\r
+.ui-icon-calculator { background-position: -112px -112px; }\r
+.ui-icon-zoomin { background-position: -128px -112px; }\r
+.ui-icon-zoomout { background-position: -144px -112px; }\r
+.ui-icon-search { background-position: -160px -112px; }\r
+.ui-icon-wrench { background-position: -176px -112px; }\r
+.ui-icon-gear { background-position: -192px -112px; }\r
+.ui-icon-heart { background-position: -208px -112px; }\r
+.ui-icon-star { background-position: -224px -112px; }\r
+.ui-icon-link { background-position: -240px -112px; }\r
+.ui-icon-cancel { background-position: 0 -128px; }\r
+.ui-icon-plus { background-position: -16px -128px; }\r
+.ui-icon-plusthick { background-position: -32px -128px; }\r
+.ui-icon-minus { background-position: -48px -128px; }\r
+.ui-icon-minusthick { background-position: -64px -128px; }\r
+.ui-icon-close { background-position: -80px -128px; }\r
+.ui-icon-closethick { background-position: -96px -128px; }\r
+.ui-icon-key { background-position: -112px -128px; }\r
+.ui-icon-lightbulb { background-position: -128px -128px; }\r
+.ui-icon-scissors { background-position: -144px -128px; }\r
+.ui-icon-clipboard { background-position: -160px -128px; }\r
+.ui-icon-copy { background-position: -176px -128px; }\r
+.ui-icon-contact { background-position: -192px -128px; }\r
+.ui-icon-image { background-position: -208px -128px; }\r
+.ui-icon-video { background-position: -224px -128px; }\r
+.ui-icon-script { background-position: -240px -128px; }\r
+.ui-icon-alert { background-position: 0 -144px; }\r
+.ui-icon-info { background-position: -16px -144px; }\r
+.ui-icon-notice { background-position: -32px -144px; }\r
+.ui-icon-help { background-position: -48px -144px; }\r
+.ui-icon-check { background-position: -64px -144px; }\r
+.ui-icon-bullet { background-position: -80px -144px; }\r
+.ui-icon-radio-off { background-position: -96px -144px; }\r
+.ui-icon-radio-on { background-position: -112px -144px; }\r
+.ui-icon-pin-w { background-position: -128px -144px; }\r
+.ui-icon-pin-s { background-position: -144px -144px; }\r
+.ui-icon-play { background-position: 0 -160px; }\r
+.ui-icon-pause { background-position: -16px -160px; }\r
+.ui-icon-seek-next { background-position: -32px -160px; }\r
+.ui-icon-seek-prev { background-position: -48px -160px; }\r
+.ui-icon-seek-end { background-position: -64px -160px; }\r
+.ui-icon-seek-first { background-position: -80px -160px; }\r
+.ui-icon-stop { background-position: -96px -160px; }\r
+.ui-icon-eject { background-position: -112px -160px; }\r
+.ui-icon-volume-off { background-position: -128px -160px; }\r
+.ui-icon-volume-on { background-position: -144px -160px; }\r
+.ui-icon-power { background-position: 0 -176px; }\r
+.ui-icon-signal-diag { background-position: -16px -176px; }\r
+.ui-icon-signal { background-position: -32px -176px; }\r
+.ui-icon-battery-0 { background-position: -48px -176px; }\r
+.ui-icon-battery-1 { background-position: -64px -176px; }\r
+.ui-icon-battery-2 { background-position: -80px -176px; }\r
+.ui-icon-battery-3 { background-position: -96px -176px; }\r
+.ui-icon-circle-plus { background-position: 0 -192px; }\r
+.ui-icon-circle-minus { background-position: -16px -192px; }\r
+.ui-icon-circle-close { background-position: -32px -192px; }\r
+.ui-icon-circle-triangle-e { background-position: -48px -192px; }\r
+.ui-icon-circle-triangle-s { background-position: -64px -192px; }\r
+.ui-icon-circle-triangle-w { background-position: -80px -192px; }\r
+.ui-icon-circle-triangle-n { background-position: -96px -192px; }\r
+.ui-icon-circle-arrow-e { background-position: -112px -192px; }\r
+.ui-icon-circle-arrow-s { background-position: -128px -192px; }\r
+.ui-icon-circle-arrow-w { background-position: -144px -192px; }\r
+.ui-icon-circle-arrow-n { background-position: -160px -192px; }\r
+.ui-icon-circle-zoomin { background-position: -176px -192px; }\r
+.ui-icon-circle-zoomout { background-position: -192px -192px; }\r
+.ui-icon-circle-check { background-position: -208px -192px; }\r
+.ui-icon-circlesmall-plus { background-position: 0 -208px; }\r
+.ui-icon-circlesmall-minus { background-position: -16px -208px; }\r
+.ui-icon-circlesmall-close { background-position: -32px -208px; }\r
+.ui-icon-squaresmall-plus { background-position: -48px -208px; }\r
+.ui-icon-squaresmall-minus { background-position: -64px -208px; }\r
+.ui-icon-squaresmall-close { background-position: -80px -208px; }\r
+.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }\r
+.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }\r
+.ui-icon-grip-solid-vertical { background-position: -32px -224px; }\r
+.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }\r
+.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }\r
+.ui-icon-grip-diagonal-se { background-position: -80px -224px; }\r
+\r
+\r
+/* Misc visuals\r
+----------------------------------*/\r
+\r
+/* Corner radius */\r
+.ui-corner-tl { -moz-border-radius-topleft: 5px/*{cornerRadius}*/; -webkit-border-top-left-radius: 5px/*{cornerRadius}*/; }\r
+.ui-corner-tr { -moz-border-radius-topright: 5px/*{cornerRadius}*/; -webkit-border-top-right-radius: 5px/*{cornerRadius}*/; }\r
+.ui-corner-bl { -moz-border-radius-bottomleft: 5px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 5px/*{cornerRadius}*/; }\r
+.ui-corner-br { -moz-border-radius-bottomright: 5px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 5px/*{cornerRadius}*/; }\r
+.ui-corner-top { -moz-border-radius-topleft: 5px/*{cornerRadius}*/; -webkit-border-top-left-radius: 5px/*{cornerRadius}*/; -moz-border-radius-topright: 5px/*{cornerRadius}*/; -webkit-border-top-right-radius: 5px/*{cornerRadius}*/; }\r
+.ui-corner-bottom { -moz-border-radius-bottomleft: 5px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 5px/*{cornerRadius}*/; -moz-border-radius-bottomright: 5px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 5px/*{cornerRadius}*/; }\r
+.ui-corner-right {  -moz-border-radius-topright: 5px/*{cornerRadius}*/; -webkit-border-top-right-radius: 5px/*{cornerRadius}*/; -moz-border-radius-bottomright: 5px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 5px/*{cornerRadius}*/; }\r
+.ui-corner-left { -moz-border-radius-topleft: 5px/*{cornerRadius}*/; -webkit-border-top-left-radius: 5px/*{cornerRadius}*/; -moz-border-radius-bottomleft: 5px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 5px/*{cornerRadius}*/; }\r
+.ui-corner-all { -moz-border-radius: 5px/*{cornerRadius}*/; -webkit-border-radius: 5px/*{cornerRadius}*/; }\r
+\r
+/* Overlays */\r
+.ui-widget-overlay { background: #aaaaaa/*{bgColorOverlay}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50%/*{bgOverlayXPos}*/ 50%/*{bgOverlayYPos}*/ repeat-x/*{bgOverlayRepeat}*//*{bgOverlayRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityOverlay}*/; }\r
+.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) 50%/*{bgShadowXPos}*/ 50%/*{bgShadowYPos}*/ repeat-x/*{bgShadowRepeat}*//*{bgShadowRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityShadow}*/; -moz-border-radius: 8px/*{cornerRadiusShadow}*/; -webkit-border-radius: 8px/*{cornerRadiusShadow}*/; }\r
+\r
+\r
+
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/base/ui.accordion.css b/js2/mwEmbed/jquery/jquery.ui/themes/base/ui.accordion.css
new file mode 100644 (file)
index 0000000..ee1b1b6
--- /dev/null
@@ -0,0 +1,9 @@
+/* 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 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; }
+.ui-accordion .ui-accordion-content-active { display: block; }
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/base/ui.all.css b/js2/mwEmbed/jquery/jquery.ui/themes/base/ui.all.css
new file mode 100644 (file)
index 0000000..543e4c3
--- /dev/null
@@ -0,0 +1,2 @@
+@import "ui.base.css";
+@import "ui.theme.css";
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/base/ui.base.css b/js2/mwEmbed/jquery/jquery.ui/themes/base/ui.base.css
new file mode 100644 (file)
index 0000000..d716095
--- /dev/null
@@ -0,0 +1,8 @@
+@import url("ui.core.css");
+@import url("ui.resizable.css");
+@import url("ui.accordion.css");
+@import url("ui.dialog.css");
+@import url("ui.slider.css");
+@import url("ui.tabs.css");
+@import url("ui.datepicker.css");
+@import url("ui.progressbar.css");
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/base/ui.core.css b/js2/mwEmbed/jquery/jquery.ui/themes/base/ui.core.css
new file mode 100644 (file)
index 0000000..c2f18f2
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+* jQuery UI CSS Framework
+* Copyright (c) 2009 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%; }
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/base/ui.datepicker.css b/js2/mwEmbed/jquery/jquery.ui/themes/base/ui.datepicker.css
new file mode 100644 (file)
index 0000000..d18ee63
--- /dev/null
@@ -0,0 +1,62 @@
+/* Datepicker
+----------------------------------*/
+.ui-datepicker { width: 17em; padding: .2em .2em 0; }
+.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 { float:left; 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 .ui-datepicker-title select.ui-datepicker-year { float: right; }
+.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%; }
+
+/* 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 {
+       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/js2/mwEmbed/jquery/jquery.ui/themes/base/ui.dialog.css b/js2/mwEmbed/jquery/jquery.ui/themes/base/ui.dialog.css
new file mode 100644 (file)
index 0000000..2997595
--- /dev/null
@@ -0,0 +1,13 @@
+/* Dialog
+----------------------------------*/
+.ui-dialog { position: relative; padding: .2em; width: 300px; }
+.ui-dialog .ui-dialog-titlebar { padding: .5em .3em .3em 1em; position: relative;  }
+.ui-dialog .ui-dialog-title { float: left; margin: .1em 0 .2em; } 
+.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 { 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 button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; }
+.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
+.ui-draggable .ui-dialog-titlebar { cursor: move; }
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/base/ui.progressbar.css b/js2/mwEmbed/jquery/jquery.ui/themes/base/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/js2/mwEmbed/jquery/jquery.ui/themes/base/ui.resizable.css b/js2/mwEmbed/jquery/jquery.ui/themes/base/ui.resizable.css
new file mode 100644 (file)
index 0000000..44efeb2
--- /dev/null
@@ -0,0 +1,13 @@
+/* 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: 0px; }
+.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0px; }
+.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0px; height: 100%; }
+.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0px; 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/js2/mwEmbed/jquery/jquery.ui/themes/base/ui.slider.css b/js2/mwEmbed/jquery/jquery.ui/themes/base/ui.slider.css
new file mode 100644 (file)
index 0000000..4c56218
--- /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; }
+
+.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/js2/mwEmbed/jquery/jquery.ui/themes/base/ui.tabs.css b/js2/mwEmbed/jquery/jquery.ui/themes/base/ui.tabs.css
new file mode 100644 (file)
index 0000000..3ca6b9a
--- /dev/null
@@ -0,0 +1,11 @@
+/* Tabs
+----------------------------------*/
+.ui-tabs { padding: .2em; zoom: 1; }
+.ui-tabs .ui-tabs-nav { list-style: none; position: relative; padding: .2em .2em 0; }
+.ui-tabs .ui-tabs-nav li { position: relative; float: left; border-bottom-width: 0 !important; margin: 0 .2em -1px 0; padding: 0; }
+.ui-tabs .ui-tabs-nav li a { float: left; text-decoration: none; padding: .5em 1em; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 1px; border-bottom-width: 0; }
+.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 { padding: 1em 1.4em; display: block; border-width: 0; background: none; }
+.ui-tabs .ui-tabs-hide { display: none !important; }
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/base/ui.theme.css b/js2/mwEmbed/jquery/jquery.ui/themes/base/ui.theme.css
new file mode 100644 (file)
index 0000000..014fcfc
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+* jQuery UI CSS Framework
+* Copyright (c) 2009 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/
+*/
+
+
+/* Component containers
+----------------------------------*/
+.ui-widget { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1.1em/*{fsDefault}*/; }
+.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_glass_75_ffffff_1x400.png)/*{bgImgUrlContent}*/ 0/*{bgContentXPos}*/ 0/*{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}*/ 0/*{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 { border: 1px solid #d3d3d3/*{borderColorDefault}*/; background: #e6e6e6/*{bgColorDefault}*/ url(images/ui-bg_glass_75_e6e6e6_1x400.png)/*{bgImgUrlDefault}*/ 0/*{bgDefaultXPos}*/ 50%/*{bgDefaultYPos}*/ repeat-x/*{bgDefaultRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #555555/*{fcDefault}*/; outline: none; }
+.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555/*{fcDefault}*/; text-decoration: none; outline: none; }
+.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: 1px solid #999999/*{borderColorHover}*/; background: #dadada/*{bgColorHover}*/ url(images/ui-bg_glass_75_dadada_1x400.png)/*{bgImgUrlHover}*/ 0/*{bgHoverXPos}*/ 50%/*{bgHoverYPos}*/ repeat-x/*{bgHoverRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcHover}*/; outline: none; }
+.ui-state-hover a, .ui-state-hover a:hover { color: #212121/*{fcHover}*/; text-decoration: none; outline: none; }
+.ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #aaaaaa/*{borderColorActive}*/; background: #ffffff/*{bgColorActive}*/ url(images/ui-bg_glass_65_ffffff_1x400.png)/*{bgImgUrlActive}*/ 0/*{bgActiveXPos}*/ 50%/*{bgActiveYPos}*/ repeat-x/*{bgActiveRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcActive}*/; outline: none; }
+.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121/*{fcActive}*/; outline: none; text-decoration: none; }
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-highlight, .ui-widget-content .ui-state-highlight {border: 1px solid #fcefa1/*{borderColorHighlight}*/; background: #fbf9ee/*{bgColorHighlight}*/ url(images/ui-bg_glass_55_fbf9ee_1x400.png)/*{bgImgUrlHighlight}*/ 0/*{bgHighlightXPos}*/ 50%/*{bgHighlightYPos}*/ repeat-x/*{bgHighlightRepeat}*/; color: #363636/*{fcHighlight}*/; }
+.ui-state-highlight a, .ui-widget-content .ui-state-highlight a { color: #363636/*{fcHighlight}*/; }
+.ui-state-error, .ui-widget-content .ui-state-error {border: 1px solid #cd0a0a/*{borderColorError}*/; background: #fef1ec/*{bgColorError}*/ url(images/ui-bg_inset-soft_95_fef1ec_1x100.png)/*{bgImgUrlError}*/ 0/*{bgErrorXPos}*/ 50%/*{bgErrorYPos}*/ repeat-x/*{bgErrorRepeat}*/; color: #cd0a0a/*{fcError}*/; }
+.ui-state-error a, .ui-widget-content .ui-state-error a { color: #363636/*{fcError}*/; }
+.ui-state-error-text, .ui-widget-content .ui-state-error-text { color: #cd0a0a/*{fcError}*/; }
+.ui-state-disabled, .ui-widget-content .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
+.ui-priority-primary, .ui-widget-content .ui-priority-primary { font-weight: bold; }
+.ui-priority-secondary, .ui-widget-content .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
+
+/* 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-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: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; }
+.ui-corner-tr { -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; }
+.ui-corner-bl { -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; }
+.ui-corner-br { -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; }
+.ui-corner-top { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; }
+.ui-corner-bottom { -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; }
+.ui-corner-right {  -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; }
+.ui-corner-left { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; }
+.ui-corner-all { -moz-border-radius: 4px/*{cornerRadius}*/; -webkit-border-radius: 4px/*{cornerRadius}*/; }
+
+/* Overlays */
+.ui-widget-overlay { background: #aaaaaa/*{bgColorOverlay}*/ none/*{bgImgUrlOverlay}*/ 0/*{bgOverlayXPos}*/ 0/*{bgOverlayYPos}*/ repeat-x/*{bgOverlayRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityOverlay}*/; }
+.ui-widget-shadow { margin: -4px/*{offsetTopShadow}*/ 0 0 -4px/*{offsetLeftShadow}*/; padding: 4px/*{thicknessShadow}*/; background: #aaaaaa/*{bgColorShadow}*/ none/*{bgImgUrlShadow}*/ 0/*{bgShadowXPos}*/ 0/*{bgShadowYPos}*/ repeat-x/*{bgShadowRepeat}*/; opacity: .35;filter:Alpha(Opacity=35)/*{opacityShadow}*/; -moz-border-radius: 4px/*{cornerRadiusShadow}*/; -webkit-border-radius: 4px/*{cornerRadiusShadow}*/; }
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-bg_flat_0_aaaaaa_40x100.png b/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-bg_flat_0_aaaaaa_40x100.png
new file mode 100644 (file)
index 0000000..5b5dab2
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-bg_flat_0_aaaaaa_40x100.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-bg_flat_55_fbec88_40x100.png b/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-bg_flat_55_fbec88_40x100.png
new file mode 100644 (file)
index 0000000..47acaad
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-bg_flat_55_fbec88_40x100.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-bg_glass_75_d0e5f5_1x400.png b/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-bg_glass_75_d0e5f5_1x400.png
new file mode 100644 (file)
index 0000000..9fb564f
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-bg_glass_75_d0e5f5_1x400.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-bg_glass_85_dfeffc_1x400.png b/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-bg_glass_85_dfeffc_1x400.png
new file mode 100644 (file)
index 0000000..0149515
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-bg_glass_85_dfeffc_1x400.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-bg_glass_95_fef1ec_1x400.png b/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-bg_glass_95_fef1ec_1x400.png
new file mode 100644 (file)
index 0000000..4443fdc
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-bg_glass_95_fef1ec_1x400.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png b/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png
new file mode 100644 (file)
index 0000000..81ecc36
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png b/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png
new file mode 100644 (file)
index 0000000..4f3faf8
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png b/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png
new file mode 100644 (file)
index 0000000..38c3833
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-icons_217bc0_256x240.png b/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-icons_217bc0_256x240.png
new file mode 100644 (file)
index 0000000..9c88458
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-icons_217bc0_256x240.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-icons_2e83ff_256x240.png b/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-icons_2e83ff_256x240.png
new file mode 100644 (file)
index 0000000..b425c44
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-icons_2e83ff_256x240.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-icons_469bdd_256x240.png b/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-icons_469bdd_256x240.png
new file mode 100644 (file)
index 0000000..5e7915f
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-icons_469bdd_256x240.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-icons_6da8d5_256x240.png b/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-icons_6da8d5_256x240.png
new file mode 100644 (file)
index 0000000..60e20ca
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-icons_6da8d5_256x240.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-icons_cd0a0a_256x240.png b/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-icons_cd0a0a_256x240.png
new file mode 100644 (file)
index 0000000..2db88b7
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-icons_cd0a0a_256x240.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-icons_d8e7f3_256x240.png b/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-icons_d8e7f3_256x240.png
new file mode 100644 (file)
index 0000000..2c8aac4
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-icons_d8e7f3_256x240.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-icons_f9bd01_256x240.png b/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-icons_f9bd01_256x240.png
new file mode 100644 (file)
index 0000000..e81603f
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/redmond/images/ui-icons_f9bd01_256x240.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/redmond/jquery-ui-1.7.1.custom.css b/js2/mwEmbed/jquery/jquery.ui/themes/redmond/jquery-ui-1.7.1.custom.css
new file mode 100644 (file)
index 0000000..5876717
--- /dev/null
@@ -0,0 +1,404 @@
+/*
+* jQuery UI CSS Framework
+* Copyright (c) 2009 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%; }
+
+/*
+* jQuery UI CSS Framework
+* Copyright (c) 2009 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=Lucida%20Grande,%20Lucida%20Sans,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=5px&bgColorHeader=5c9ccc&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=55&borderColorHeader=4297d7&fcHeader=ffffff&iconColorHeader=d8e7f3&bgColorContent=fcfdfd&bgTextureContent=06_inset_hard.png&bgImgOpacityContent=100&borderColorContent=a6c9e2&fcContent=222222&iconColorContent=469bdd&bgColorDefault=dfeffc&bgTextureDefault=02_glass.png&bgImgOpacityDefault=85&borderColorDefault=c5dbec&fcDefault=2e6e9e&iconColorDefault=6da8d5&bgColorHover=d0e5f5&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=79b7e7&fcHover=1d5987&iconColorHover=217bc0&bgColorActive=f5f8f9&bgTextureActive=06_inset_hard.png&bgImgOpacityActive=100&borderColorActive=79b7e7&fcActive=e17009&iconColorActive=f9bd01&bgColorHighlight=fbec88&bgTextureHighlight=01_flat.png&bgImgOpacityHighlight=55&borderColorHighlight=fad42e&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
+*/
+
+
+/* Component containers
+----------------------------------*/
+.ui-widget { font-family: Lucida Grande, Lucida Sans, Arial, sans-serif; font-size: 1.1em; }
+.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Lucida Grande, Lucida Sans, Arial, sans-serif; font-size: 1em; }
+.ui-widget-content { border: 1px solid #a6c9e2; background: #fcfdfd url(images/ui-bg_inset-hard_100_fcfdfd_1x100.png) 50% bottom repeat-x; color: #222222; }
+.ui-widget-content a { color: #222222; }
+.ui-widget-header { border: 1px solid #4297d7; background: #5c9ccc url(images/ui-bg_gloss-wave_55_5c9ccc_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; }
+.ui-widget-header a { color: #ffffff; }
+
+/* Interaction states
+----------------------------------*/
+.ui-state-default, .ui-widget-content .ui-state-default { border: 1px solid #c5dbec; background: #dfeffc url(images/ui-bg_glass_85_dfeffc_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #2e6e9e; outline: none; }
+.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #2e6e9e; text-decoration: none; outline: none; }
+.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: 1px solid #79b7e7; background: #d0e5f5 url(images/ui-bg_glass_75_d0e5f5_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1d5987; outline: none; }
+.ui-state-hover a, .ui-state-hover a:hover { color: #1d5987; text-decoration: none; outline: none; }
+.ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #79b7e7; background: #f5f8f9 url(images/ui-bg_inset-hard_100_f5f8f9_1x100.png) 50% 50% repeat-x; font-weight: bold; color: #e17009; outline: none; }
+.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #e17009; outline: none; text-decoration: none; }
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-highlight, .ui-widget-content .ui-state-highlight {border: 1px solid #fad42e; background: #fbec88 url(images/ui-bg_flat_55_fbec88_40x100.png) 50% 50% repeat-x; color: #363636; }
+.ui-state-highlight a, .ui-widget-content .ui-state-highlight a { color: #363636; }
+.ui-state-error, .ui-widget-content .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
+.ui-state-error a, .ui-widget-content .ui-state-error a { color: #cd0a0a; }
+.ui-state-error-text, .ui-widget-content .ui-state-error-text { color: #cd0a0a; }
+.ui-state-disabled, .ui-widget-content .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
+.ui-priority-primary, .ui-widget-content .ui-priority-primary { font-weight: bold; }
+.ui-priority-secondary, .ui-widget-content .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_469bdd_256x240.png); }
+.ui-widget-content .ui-icon {background-image: url(images/ui-icons_469bdd_256x240.png); }
+.ui-widget-header .ui-icon {background-image: url(images/ui-icons_d8e7f3_256x240.png); }
+.ui-state-default .ui-icon { background-image: url(images/ui-icons_6da8d5_256x240.png); }
+.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_217bc0_256x240.png); }
+.ui-state-active .ui-icon {background-image: url(images/ui-icons_f9bd01_256x240.png); }
+.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
+.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_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-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: 5px; -webkit-border-top-left-radius: 5px; }
+.ui-corner-tr { -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; }
+.ui-corner-bl { -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; }
+.ui-corner-br { -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; }
+.ui-corner-top { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; }
+.ui-corner-bottom { -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; }
+.ui-corner-right {  -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; }
+.ui-corner-left { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; }
+.ui-corner-all { -moz-border-radius: 5px; -webkit-border-radius: 5px; }
+
+/* Overlays */
+.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
+.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; }/* 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 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; }
+.ui-accordion .ui-accordion-content-active { display: block; }/* Datepicker
+----------------------------------*/
+.ui-datepicker { width: 17em; padding: .2em .2em 0; }
+.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 { float:left; 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 .ui-datepicker-title select.ui-datepicker-year { float: right; }
+.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%; }
+
+/* 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 {
+    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*/
+}/* Dialog
+----------------------------------*/
+.ui-dialog { position: relative; padding: .2em; width: 300px; }
+.ui-dialog .ui-dialog-titlebar { padding: .5em .3em .3em 1em; position: relative;  }
+.ui-dialog .ui-dialog-title { float: left; margin: .1em 0 .2em; } 
+.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 { 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 button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; }
+.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
+.ui-draggable .ui-dialog-titlebar { cursor: move; }
+/* Progressbar
+----------------------------------*/
+.ui-progressbar { height:2em; text-align: left; }
+.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }/* 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: 0px; }
+.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0px; }
+.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0px; height: 100%; }
+.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0px; 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;}/* 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; }
+
+.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; }/* Tabs
+----------------------------------*/
+.ui-tabs { padding: .2em; zoom: 1; }
+.ui-tabs .ui-tabs-nav { list-style: none; position: relative; padding: .2em .2em 0; }
+.ui-tabs .ui-tabs-nav li { position: relative; float: left; border-bottom-width: 0 !important; margin: 0 .2em -1px 0; padding: 0; }
+.ui-tabs .ui-tabs-nav li a { float: left; text-decoration: none; padding: .5em 1em; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 1px; border-bottom-width: 0; }
+.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 { padding: 1em 1.4em; display: block; border-width: 0; background: none; }
+.ui-tabs .ui-tabs-hide { display: none !important; }
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_diagonals-thick_20_666666_40x40.png b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_diagonals-thick_20_666666_40x40.png
new file mode 100644 (file)
index 0000000..64ece57
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_diagonals-thick_20_666666_40x40.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png
new file mode 100644 (file)
index 0000000..5b5dab2
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_flat_75_ffffff_40x100.png b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_flat_75_ffffff_40x100.png
new file mode 100644 (file)
index 0000000..ac8b229
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_flat_75_ffffff_40x100.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png
new file mode 100644 (file)
index 0000000..ad3d634
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_glass_65_ffffff_1x400.png b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_glass_65_ffffff_1x400.png
new file mode 100644 (file)
index 0000000..42ccba2
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_glass_65_ffffff_1x400.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_glass_75_dadada_1x400.png b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_glass_75_dadada_1x400.png
new file mode 100644 (file)
index 0000000..5a46b47
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_glass_75_dadada_1x400.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png
new file mode 100644 (file)
index 0000000..86c2baa
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png
new file mode 100644 (file)
index 0000000..4443fdc
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png
new file mode 100644 (file)
index 0000000..7c9fa6c
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-icons_222222_256x240.png b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-icons_222222_256x240.png
new file mode 100644 (file)
index 0000000..67560da
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-icons_222222_256x240.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-icons_2e83ff_256x240.png b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-icons_2e83ff_256x240.png
new file mode 100644 (file)
index 0000000..b425c44
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-icons_2e83ff_256x240.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-icons_454545_256x240.png b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-icons_454545_256x240.png
new file mode 100644 (file)
index 0000000..0cd64a2
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-icons_454545_256x240.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-icons_888888_256x240.png b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-icons_888888_256x240.png
new file mode 100644 (file)
index 0000000..2e5180e
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-icons_888888_256x240.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-icons_cd0a0a_256x240.png b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-icons_cd0a0a_256x240.png
new file mode 100644 (file)
index 0000000..2db88b7
Binary files /dev/null and b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/images/ui-icons_cd0a0a_256x240.png differ
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/jquery-ui-1.7.1.custom.css b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/jquery-ui-1.7.1.custom.css
new file mode 100644 (file)
index 0000000..303ec94
--- /dev/null
@@ -0,0 +1,404 @@
+/*
+* jQuery UI CSS Framework
+* Copyright (c) 2009 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%; }
+
+/*
+* jQuery UI CSS Framework
+* Copyright (c) 2009 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=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
+*/
+
+
+/* Component containers
+----------------------------------*/
+.ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; }
+.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; }
+.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; }
+.ui-widget-content a { color: #222222; }
+.ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_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 { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; outline: none; }
+.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; outline: none; }
+.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; outline: none; }
+.ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; outline: none; }
+.ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; outline: none; }
+.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; outline: none; text-decoration: none; }
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-highlight, .ui-widget-content .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; }
+.ui-state-highlight a, .ui-widget-content .ui-state-highlight a { color: #363636; }
+.ui-state-error, .ui-widget-content .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
+.ui-state-error a, .ui-widget-content .ui-state-error a { color: #cd0a0a; }
+.ui-state-error-text, .ui-widget-content .ui-state-error-text { color: #cd0a0a; }
+.ui-state-disabled, .ui-widget-content .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
+.ui-priority-primary, .ui-widget-content .ui-priority-primary { font-weight: bold; }
+.ui-priority-secondary, .ui-widget-content .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
+.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
+.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
+.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); }
+.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
+.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
+.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
+.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_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-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: 4px; -webkit-border-top-left-radius: 4px; }
+.ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; }
+.ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; }
+.ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }
+.ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; }
+.ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }
+.ui-corner-right {  -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }
+.ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; }
+.ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; }
+
+/* Overlays */
+.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat; opacity: .30;filter:Alpha(Opacity=30); }
+.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; }/* 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 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; }
+.ui-accordion .ui-accordion-content-active { display: block; }/* Datepicker
+----------------------------------*/
+.ui-datepicker { width: 17em; padding: .2em .2em 0; }
+.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 { float:left; 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 .ui-datepicker-title select.ui-datepicker-year { float: right; }
+.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%; }
+
+/* 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 {
+       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*/
+}/* Dialog
+----------------------------------*/
+.ui-dialog { position: relative; padding: .2em; width: 300px; }
+.ui-dialog .ui-dialog-titlebar { padding: .5em .3em .3em 1em; position: relative;  }
+.ui-dialog .ui-dialog-title { float: left; margin: .1em 0 .2em; } 
+.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 { 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 button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; }
+.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
+.ui-draggable .ui-dialog-titlebar { cursor: move; }
+/* Progressbar
+----------------------------------*/
+.ui-progressbar { height:2em; text-align: left; }
+.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }/* 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: 0px; }
+.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0px; }
+.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0px; height: 100%; }
+.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0px; 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;}/* 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; }
+
+.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; }/* Tabs
+----------------------------------*/
+.ui-tabs { padding: .2em; zoom: 1; }
+.ui-tabs .ui-tabs-nav { list-style: none; position: relative; padding: .2em .2em 0; }
+.ui-tabs .ui-tabs-nav li { position: relative; float: left; border-bottom-width: 0 !important; margin: 0 .2em -1px 0; padding: 0; }
+.ui-tabs .ui-tabs-nav li a { float: left; text-decoration: none; padding: .5em 1em; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 1px; border-bottom-width: 0; }
+.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 { padding: 1em 1.4em; display: block; border-width: 0; background: none; }
+.ui-tabs .ui-tabs-hide { display: none !important; }
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/ui.accordion.css b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/ui.accordion.css
new file mode 100644 (file)
index 0000000..ee1b1b6
--- /dev/null
@@ -0,0 +1,9 @@
+/* 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 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; }
+.ui-accordion .ui-accordion-content-active { display: block; }
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/ui.all.css b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/ui.all.css
new file mode 100644 (file)
index 0000000..543e4c3
--- /dev/null
@@ -0,0 +1,2 @@
+@import "ui.base.css";
+@import "ui.theme.css";
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/ui.base.css b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/ui.base.css
new file mode 100644 (file)
index 0000000..d716095
--- /dev/null
@@ -0,0 +1,8 @@
+@import url("ui.core.css");
+@import url("ui.resizable.css");
+@import url("ui.accordion.css");
+@import url("ui.dialog.css");
+@import url("ui.slider.css");
+@import url("ui.tabs.css");
+@import url("ui.datepicker.css");
+@import url("ui.progressbar.css");
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/ui.core.css b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/ui.core.css
new file mode 100644 (file)
index 0000000..c2f18f2
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+* jQuery UI CSS Framework
+* Copyright (c) 2009 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%; }
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/ui.datepicker.css b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/ui.datepicker.css
new file mode 100644 (file)
index 0000000..d18ee63
--- /dev/null
@@ -0,0 +1,62 @@
+/* Datepicker
+----------------------------------*/
+.ui-datepicker { width: 17em; padding: .2em .2em 0; }
+.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 { float:left; 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 .ui-datepicker-title select.ui-datepicker-year { float: right; }
+.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%; }
+
+/* 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 {
+       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/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/ui.dialog.css b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/ui.dialog.css
new file mode 100644 (file)
index 0000000..2997595
--- /dev/null
@@ -0,0 +1,13 @@
+/* Dialog
+----------------------------------*/
+.ui-dialog { position: relative; padding: .2em; width: 300px; }
+.ui-dialog .ui-dialog-titlebar { padding: .5em .3em .3em 1em; position: relative;  }
+.ui-dialog .ui-dialog-title { float: left; margin: .1em 0 .2em; } 
+.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 { 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 button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; }
+.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
+.ui-draggable .ui-dialog-titlebar { cursor: move; }
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/ui.progressbar.css b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/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/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/ui.resizable.css b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/ui.resizable.css
new file mode 100644 (file)
index 0000000..44efeb2
--- /dev/null
@@ -0,0 +1,13 @@
+/* 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: 0px; }
+.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0px; }
+.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0px; height: 100%; }
+.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0px; 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/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/ui.slider.css b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/ui.slider.css
new file mode 100644 (file)
index 0000000..4c56218
--- /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; }
+
+.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/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/ui.tabs.css b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/ui.tabs.css
new file mode 100644 (file)
index 0000000..3ca6b9a
--- /dev/null
@@ -0,0 +1,11 @@
+/* Tabs
+----------------------------------*/
+.ui-tabs { padding: .2em; zoom: 1; }
+.ui-tabs .ui-tabs-nav { list-style: none; position: relative; padding: .2em .2em 0; }
+.ui-tabs .ui-tabs-nav li { position: relative; float: left; border-bottom-width: 0 !important; margin: 0 .2em -1px 0; padding: 0; }
+.ui-tabs .ui-tabs-nav li a { float: left; text-decoration: none; padding: .5em 1em; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 1px; border-bottom-width: 0; }
+.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 { padding: 1em 1.4em; display: block; border-width: 0; background: none; }
+.ui-tabs .ui-tabs-hide { display: none !important; }
diff --git a/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/ui.theme.css b/js2/mwEmbed/jquery/jquery.ui/themes/smoothness/ui.theme.css
new file mode 100644 (file)
index 0000000..10f76b4
--- /dev/null
@@ -0,0 +1,245 @@
+
+
+/*
+* jQuery UI CSS Framework
+* Copyright (c) 2009 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=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
+*/
+
+
+/* Component containers
+----------------------------------*/
+.ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; }
+.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; }
+.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; }
+.ui-widget-content a { color: #222222; }
+.ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_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 { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; outline: none; }
+.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; outline: none; }
+.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; outline: none; }
+.ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; outline: none; }
+.ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; outline: none; }
+.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; outline: none; text-decoration: none; }
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-highlight, .ui-widget-content .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; }
+.ui-state-highlight a, .ui-widget-content .ui-state-highlight a { color: #363636; }
+.ui-state-error, .ui-widget-content .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
+.ui-state-error a, .ui-widget-content .ui-state-error a { color: #cd0a0a; }
+.ui-state-error-text, .ui-widget-content .ui-state-error-text { color: #cd0a0a; }
+.ui-state-disabled, .ui-widget-content .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
+.ui-priority-primary, .ui-widget-content .ui-priority-primary { font-weight: bold; }
+.ui-priority-secondary, .ui-widget-content .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
+.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
+.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
+.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); }
+.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
+.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
+.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
+.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_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-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: 4px; -webkit-border-top-left-radius: 4px; }
+.ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; }
+.ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; }
+.ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }
+.ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; }
+.ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }
+.ui-corner-right {  -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }
+.ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; }
+.ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; }
+
+/* Overlays */
+.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
+.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; }
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/effects.blind.js b/js2/mwEmbed/jquery/jquery.ui/ui/effects.blind.js
new file mode 100644 (file)
index 0000000..e49d96c
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * jQuery UI Effects Blind 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Blind
+ *
+ * Depends:
+ *     effects.core.js
+ */
+(function($) {
+
+$.effects.blind = function(o) {
+
+       return this.queue(function() {
+
+               // Create element
+               var el = $(this), props = ['position','top','left'];
+
+               // 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/js2/mwEmbed/jquery/jquery.ui/ui/effects.bounce.js b/js2/mwEmbed/jquery/jquery.ui/ui/effects.bounce.js
new file mode 100644 (file)
index 0000000..fae3d1e
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * jQuery UI Effects Bounce 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Bounce
+ *
+ * Depends:
+ *     effects.core.js
+ */
+(function($) {
+
+$.effects.bounce = function(o) {
+
+       return this.queue(function() {
+
+               // Create element
+               var el = $(this), props = ['position','top','left'];
+
+               // 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({margin:true}) / 3 : el.outerWidth({margin: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/js2/mwEmbed/jquery/jquery.ui/ui/effects.clip.js b/js2/mwEmbed/jquery/jquery.ui/ui/effects.clip.js
new file mode 100644 (file)
index 0000000..a14a194
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * jQuery UI Effects Clip 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Clip
+ *
+ * Depends:
+ *     effects.core.js
+ */
+(function($) {
+
+$.effects.clip = function(o) {
+
+       return this.queue(function() {
+
+               // Create element
+               var el = $(this), props = ['position','top','left','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/js2/mwEmbed/jquery/jquery.ui/ui/effects.core.js b/js2/mwEmbed/jquery/jquery.ui/ui/effects.core.js
new file mode 100644 (file)
index 0000000..c52a312
--- /dev/null
@@ -0,0 +1,543 @@
+/*
+ * jQuery UI Effects 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/
+ */
+;jQuery.effects || (function($) {
+
+$.effects = {
+       version: "1.7.1",
+
+       // 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();
+
+               //Cache width,height and float properties of the element, and create a wrapper around it
+               var props = { width: element.outerWidth(true), height: element.outerHeight(true), 'float': element.css('float') };
+               element.wrap('<div class="ui-effects-wrapper" style="font-size:100%;background:transparent;border:none;margin:0;padding:0"></div>');
+               var wrapper = element.parent();
+
+               //Transfer the positioning of the element to the wrapper
+               if (element.css('position') == 'static') {
+                       wrapper.css({ position: 'relative' });
+                       element.css({ position: 'relative'} );
+               } else {
+                       var top = element.css('top'); if(isNaN(parseInt(top,10))) top = 'auto';
+                       var left = element.css('left'); if(isNaN(parseInt(left,10))) left = 'auto';
+                       wrapper.css({ position: element.css('position'), top: top, left: left, zIndex: element.css('z-index') }).show();
+                       element.css({position: 'relative', top: 0, left: 0 });
+               }
+
+               wrapper.css(props);
+               return wrapper;
+       },
+
+       removeWrapper: function(element) {
+               if (element.parent().is('.ui-effects-wrapper'))
+                       return element.parent().replaceWith(element);
+               return element;
+       },
+
+       setTransition: function(element, list, factor, value) {
+               value = value || {};
+               $.each(list, function(i, x){
+                       unit = element.cssUnit(x);
+                       if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];
+               });
+               return value;
+       },
+
+       //Base function to animate from one class to another in a seamless transition
+       animateClass: function(value, duration, easing, callback) {
+
+               var cb = (typeof easing == "function" ? easing : (callback ? callback : null));
+               var ea = (typeof easing == "string" ? easing : null);
+
+               return this.each(function() {
+
+                       var offset = {}; var that = $(this); var oldStyleAttr = that.attr("style") || '';
+                       if(typeof oldStyleAttr == 'object') oldStyleAttr = oldStyleAttr["cssText"]; /* Stupidly in IE, style is a object.. */
+                       if(value.toggle) { that.hasClass(value.toggle) ? value.remove = value.toggle : value.add = value.toggle; }
+
+                       //Let's get a style offset
+                       var oldStyle = $.extend({}, (document.defaultView ? document.defaultView.getComputedStyle(this,null) : this.currentStyle));
+                       if(value.add) that.addClass(value.add); if(value.remove) that.removeClass(value.remove);
+                       var newStyle = $.extend({}, (document.defaultView ? document.defaultView.getComputedStyle(this,null) : this.currentStyle));
+                       if(value.add) that.removeClass(value.add); if(value.remove) that.addClass(value.remove);
+
+                       // The main function to form the object for animation
+                       for(var n in newStyle) {
+                               if( typeof newStyle[n] != "function" && newStyle[n] /* No functions and null properties */
+                               && n.indexOf("Moz") == -1 && n.indexOf("length") == -1 /* No mozilla spezific render properties. */
+                               && newStyle[n] != oldStyle[n] /* Only values that have changed are used for the animation */
+                               && (n.match(/color/i) || (!n.match(/color/i) && !isNaN(parseInt(newStyle[n],10)))) /* Only things that can be parsed to integers or colors */
+                               && (oldStyle.position != "static" || (oldStyle.position == "static" && !n.match(/left|top|bottom|right/))) /* No need for positions when dealing with static positions */
+                               ) offset[n] = newStyle[n];
+                       }
+
+                       that.animate(offset, duration, ea, function() { // Animate the newly constructed offset object
+                               // Change style attribute back to original. For stupid IE, we need to clear the damn object.
+                               if(typeof $(this).attr("style") == 'object') { $(this).attr("style")["cssText"] = ""; $(this).attr("style")["cssText"] = oldStyleAttr; } else $(this).attr("style", oldStyleAttr);
+                               if(value.add) $(this).addClass(value.add); if(value.remove) $(this).removeClass(value.remove);
+                               if(cb) cb.apply(this, arguments);
+                       });
+
+               });
+       }
+};
+
+
+function _normalizeArguments(a, m) {
+
+       var o = a[1] && a[1].constructor == Object ? a[1] : {}; if(m) o.mode = m;
+       var speed = a[1] && a[1].constructor != Object ? a[1] : (o.duration ? o.duration : a[2]); //either comes from options.duration or the secon/third argument
+               speed = $.fx.off ? 0 : typeof speed === "number" ? speed : $.fx.speeds[speed] || $.fx.speeds._default;
+       var callback = o.callback || ( $.isFunction(a[1]) && a[1] ) || ( $.isFunction(a[2]) && a[2] ) || ( $.isFunction(a[3]) && a[3] );
+
+       return [a[0], o, speed, callback];
+       
+}
+
+//Extend the methods of jQuery
+$.fn.extend({
+
+       //Save old methods
+       _show: $.fn.show,
+       _hide: $.fn.hide,
+       __toggle: $.fn.toggle,
+       _addClass: $.fn.addClass,
+       _removeClass: $.fn.removeClass,
+       _toggleClass: $.fn.toggleClass,
+
+       // New effect methods
+       effect: function(fx, options, speed, callback) {
+               return $.effects[fx] ? $.effects[fx].call(this, {method: fx, options: options || {}, duration: speed, callback: callback }) : null;
+       },
+
+       show: function() {
+               if(!arguments[0] || (arguments[0].constructor == Number || (/(slow|normal|fast)/).test(arguments[0])))
+                       return this._show.apply(this, arguments);
+               else {
+                       return this.effect.apply(this, _normalizeArguments(arguments, 'show'));
+               }
+       },
+
+       hide: function() {
+               if(!arguments[0] || (arguments[0].constructor == Number || (/(slow|normal|fast)/).test(arguments[0])))
+                       return this._hide.apply(this, arguments);
+               else {
+                       return this.effect.apply(this, _normalizeArguments(arguments, 'hide'));
+               }
+       },
+
+       toggle: function(){
+               if(!arguments[0] || (arguments[0].constructor == Number || (/(slow|normal|fast)/).test(arguments[0])) || (arguments[0].constructor == Function))
+                       return this.__toggle.apply(this, arguments);
+               else {
+                       return this.effect.apply(this, _normalizeArguments(arguments, 'toggle'));
+               }
+       },
+
+       addClass: function(classNames, speed, easing, callback) {
+               return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);
+       },
+       removeClass: function(classNames,speed,easing,callback) {
+               return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);
+       },
+       toggleClass: function(classNames,speed,easing,callback) {
+               return ( (typeof speed !== "boolean") && speed ) ? $.effects.animateClass.apply(this, [{ toggle: classNames },speed,easing,callback]) : this._toggleClass(classNames, speed);
+       },
+       morph: function(remove,add,speed,easing,callback) {
+               return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
+       },
+       switchClass: function() {
+               return this.morph.apply(this, arguments);
+       },
+
+       // 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;
+       }
+});
+
+/*
+ * jQuery Color Animations
+ * Copyright 2007 John Resig
+ * Released under the MIT and GPL licenses.
+ */
+
+// 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.state == 0 ) {
+                                               fx.start = getColor( fx.elem, attr );
+                                               fx.end = getRGB( fx.end );
+                               }
+
+                               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(",") + ")";
+                       };
+});
+
+// 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 {
+                               color = $.curCSS(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]
+};
+
+/*
+ * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
+ *
+ * Uses the built in easing capabilities added In jQuery 1.1
+ * to offer multiple easing options
+ *
+ * TERMS OF USE - jQuery Easing
+ *
+ * Open source under the BSD License.
+ *
+ * Copyright 2008 George McGinley Smith
+ * 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 the author nor the names of 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 OWNER 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.
+ *
+*/
+
+// t: current time, b: begInnIng value, c: change In value, d: duration
+$.easing.jswing = $.easing.swing;
+
+$.extend($.easing,
+{
+       def: 'easeOutQuad',
+       swing: function (x, t, b, c, d) {
+               //alert($.easing.default);
+               return $.easing[$.easing.def](x, t, b, c, d);
+       },
+       easeInQuad: function (x, t, b, c, d) {
+               return c*(t/=d)*t + b;
+       },
+       easeOutQuad: function (x, t, b, c, d) {
+               return -c *(t/=d)*(t-2) + b;
+       },
+       easeInOutQuad: function (x, t, b, c, d) {
+               if ((t/=d/2) < 1) return c/2*t*t + b;
+               return -c/2 * ((--t)*(t-2) - 1) + b;
+       },
+       easeInCubic: function (x, t, b, c, d) {
+               return c*(t/=d)*t*t + b;
+       },
+       easeOutCubic: function (x, t, b, c, d) {
+               return c*((t=t/d-1)*t*t + 1) + b;
+       },
+       easeInOutCubic: function (x, t, b, c, d) {
+               if ((t/=d/2) < 1) return c/2*t*t*t + b;
+               return c/2*((t-=2)*t*t + 2) + b;
+       },
+       easeInQuart: function (x, t, b, c, d) {
+               return c*(t/=d)*t*t*t + b;
+       },
+       easeOutQuart: function (x, t, b, c, d) {
+               return -c * ((t=t/d-1)*t*t*t - 1) + b;
+       },
+       easeInOutQuart: function (x, t, b, c, d) {
+               if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
+               return -c/2 * ((t-=2)*t*t*t - 2) + b;
+       },
+       easeInQuint: function (x, t, b, c, d) {
+               return c*(t/=d)*t*t*t*t + b;
+       },
+       easeOutQuint: function (x, t, b, c, d) {
+               return c*((t=t/d-1)*t*t*t*t + 1) + b;
+       },
+       easeInOutQuint: function (x, t, b, c, d) {
+               if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
+               return c/2*((t-=2)*t*t*t*t + 2) + b;
+       },
+       easeInSine: function (x, t, b, c, d) {
+               return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
+       },
+       easeOutSine: function (x, t, b, c, d) {
+               return c * Math.sin(t/d * (Math.PI/2)) + b;
+       },
+       easeInOutSine: function (x, t, b, c, d) {
+               return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
+       },
+       easeInExpo: function (x, t, b, c, d) {
+               return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
+       },
+       easeOutExpo: function (x, t, b, c, d) {
+               return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
+       },
+       easeInOutExpo: function (x, t, b, c, d) {
+               if (t==0) return b;
+               if (t==d) return b+c;
+               if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
+               return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
+       },
+       easeInCirc: function (x, t, b, c, d) {
+               return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
+       },
+       easeOutCirc: function (x, t, b, c, d) {
+               return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
+       },
+       easeInOutCirc: function (x, t, b, c, d) {
+               if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
+               return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
+       },
+       easeInElastic: function (x, t, b, c, d) {
+               var s=1.70158;var p=0;var a=c;
+               if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
+               if (a < Math.abs(c)) { a=c; var s=p/4; }
+               else var s = p/(2*Math.PI) * Math.asin (c/a);
+               return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
+       },
+       easeOutElastic: function (x, t, b, c, d) {
+               var s=1.70158;var p=0;var a=c;
+               if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
+               if (a < Math.abs(c)) { a=c; var s=p/4; }
+               else var s = p/(2*Math.PI) * Math.asin (c/a);
+               return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
+       },
+       easeInOutElastic: function (x, t, b, c, d) {
+               var s=1.70158;var p=0;var a=c;
+               if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
+               if (a < Math.abs(c)) { a=c; var s=p/4; }
+               else var s = p/(2*Math.PI) * Math.asin (c/a);
+               if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
+               return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
+       },
+       easeInBack: function (x, t, b, c, d, s) {
+               if (s == undefined) s = 1.70158;
+               return c*(t/=d)*t*((s+1)*t - s) + b;
+       },
+       easeOutBack: function (x, t, b, c, d, s) {
+               if (s == undefined) s = 1.70158;
+               return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
+       },
+       easeInOutBack: function (x, t, b, c, d, s) {
+               if (s == undefined) s = 1.70158;
+               if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
+               return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
+       },
+       easeInBounce: function (x, t, b, c, d) {
+               return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b;
+       },
+       easeOutBounce: function (x, t, b, c, d) {
+               if ((t/=d) < (1/2.75)) {
+                       return c*(7.5625*t*t) + b;
+               } else if (t < (2/2.75)) {
+                       return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
+               } else if (t < (2.5/2.75)) {
+                       return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
+               } else {
+                       return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
+               }
+       },
+       easeInOutBounce: function (x, t, b, c, d) {
+               if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
+               return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
+       }
+});
+
+/*
+ *
+ * TERMS OF USE - EASING EQUATIONS
+ *
+ * Open source under the BSD License.
+ *
+ * Copyright 2001 Robert Penner
+ * 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 the author nor the names of 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 OWNER 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.
+ *
+ */
+
+})(jQuery);
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/effects.drop.js b/js2/mwEmbed/jquery/jquery.ui/ui/effects.drop.js
new file mode 100644 (file)
index 0000000..2a3ffd4
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * jQuery UI Effects Drop 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Drop
+ *
+ * Depends:
+ *     effects.core.js
+ */
+(function($) {
+
+$.effects.drop = function(o) {
+
+       return this.queue(function() {
+
+               // Create element
+               var el = $(this), props = ['position','top','left','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({margin:true}) / 2 : el.outerWidth({margin: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/js2/mwEmbed/jquery/jquery.ui/ui/effects.explode.js b/js2/mwEmbed/jquery/jquery.ui/ui/effects.explode.js
new file mode 100644 (file)
index 0000000..5bfc854
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * jQuery UI Effects Explode 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Explode
+ *
+ * Depends:
+ *     effects.core.js
+ */
+(function($) {
+
+$.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/js2/mwEmbed/jquery/jquery.ui/ui/effects.fold.js b/js2/mwEmbed/jquery/jquery.ui/ui/effects.fold.js
new file mode 100644 (file)
index 0000000..77f8a9d
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * jQuery UI Effects Fold 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Fold
+ *
+ * Depends:
+ *     effects.core.js
+ */
+(function($) {
+
+$.effects.fold = function(o) {
+
+       return this.queue(function() {
+
+               // Create element
+               var el = $(this), props = ['position','top','left'];
+
+               // 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/js2/mwEmbed/jquery/jquery.ui/ui/effects.highlight.js b/js2/mwEmbed/jquery/jquery.ui/ui/effects.highlight.js
new file mode 100644 (file)
index 0000000..680bacd
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * jQuery UI Effects Highlight 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Highlight
+ *
+ * Depends:
+ *     effects.core.js
+ */
+(function($) {
+
+$.effects.highlight = function(o) {
+
+       return this.queue(function() {
+
+               // Create element
+               var el = $(this), props = ['backgroundImage','backgroundColor','opacity'];
+
+               // Set options
+               var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
+               var color = o.options.color || "#ffff99"; // Default highlight color
+               var oldColor = el.css("backgroundColor");
+
+               // Adjust
+               $.effects.save(el, props); el.show(); // Save & Show
+               el.css({backgroundImage: 'none', backgroundColor: color}); // Shift
+
+               // Animation
+               var animation = {backgroundColor: oldColor };
+               if (mode == "hide") animation['opacity'] = 0;
+
+               // Animate
+               el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
+                       if(mode == "hide") el.hide();
+                       $.effects.restore(el, props);
+               if (mode == "show" && $.browser.msie) this.style.removeAttribute('filter');
+                       if(o.callback) o.callback.apply(this, arguments);
+                       el.dequeue();
+               }});
+
+       });
+
+};
+
+})(jQuery);
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/effects.pulsate.js b/js2/mwEmbed/jquery/jquery.ui/ui/effects.pulsate.js
new file mode 100644 (file)
index 0000000..e845634
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * jQuery UI Effects Pulsate 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Pulsate
+ *
+ * Depends:
+ *     effects.core.js
+ */
+(function($) {
+
+$.effects.pulsate = function(o) {
+
+       return this.queue(function() {
+
+               // Create element
+               var el = $(this);
+
+               // Set options
+               var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
+               var times = o.options.times || 5; // Default # of times
+               var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2;
+
+               // Adjust
+               if (mode == 'hide') times--;
+               if (el.is(':hidden')) { // Show fadeIn
+                       el.css('opacity', 0);
+                       el.show(); // Show
+                       el.animate({opacity: 1}, duration, o.options.easing);
+                       times = times-2;
+               }
+
+               // Animate
+               for (var i = 0; i < times; i++) { // Pulsate
+                       el.animate({opacity: 0}, duration, o.options.easing).animate({opacity: 1}, duration, o.options.easing);
+               };
+               if (mode == 'hide') { // Last Pulse
+                       el.animate({opacity: 0}, duration, o.options.easing, function(){
+                               el.hide(); // Hide
+                               if(o.callback) o.callback.apply(this, arguments); // Callback
+                       });
+               } else {
+                       el.animate({opacity: 0}, duration, o.options.easing).animate({opacity: 1}, duration, o.options.easing, function(){
+                               if(o.callback) o.callback.apply(this, arguments); // Callback
+                       });
+               };
+               el.queue('fx', function() { el.dequeue(); });
+               el.dequeue();
+       });
+
+};
+
+})(jQuery);
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/effects.scale.js b/js2/mwEmbed/jquery/jquery.ui/ui/effects.scale.js
new file mode 100644 (file)
index 0000000..e02dca0
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * jQuery UI Effects Scale 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Scale
+ *
+ * Depends:
+ *     effects.core.js
+ */
+(function($) {
+
+$.effects.puff = 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 || 'hide'); // Set Mode
+               var percent = parseInt(o.options.percent,10) || 150; // Set default puff percent
+               options.fade = true; // It's not a puff if it doesn't fade! :)
+               var original = {height: el.height(), width: el.width()}; // Save original
+
+               // Adjust
+               var factor = percent / 100;
+               el.from = (mode == 'hide') ? original : {height: original.height * factor, width: original.width * factor};
+
+               // Animation
+               options.from = el.from;
+               options.percent = (mode == 'hide') ? percent : 100;
+               options.mode = mode;
+
+               // Animate
+               el.effect('scale', options, o.duration, o.callback);
+               el.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','left','width','height','overflow','opacity'];
+               var props1 = ['position','top','left','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(){
+                               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(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/js2/mwEmbed/jquery/jquery.ui/ui/effects.shake.js b/js2/mwEmbed/jquery/jquery.ui/ui/effects.shake.js
new file mode 100644 (file)
index 0000000..3bcf822
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * jQuery UI Effects Shake 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Shake
+ *
+ * Depends:
+ *     effects.core.js
+ */
+(function($) {
+
+$.effects.shake = function(o) {
+
+       return this.queue(function() {
+
+               // Create element
+               var el = $(this), props = ['position','top','left'];
+
+               // 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/js2/mwEmbed/jquery/jquery.ui/ui/effects.slide.js b/js2/mwEmbed/jquery/jquery.ui/ui/effects.slide.js
new file mode 100644 (file)
index 0000000..1085ae6
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * jQuery UI Effects Slide 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Slide
+ *
+ * Depends:
+ *     effects.core.js
+ */
+(function($) {
+
+$.effects.slide = function(o) {
+
+       return this.queue(function() {
+
+               // Create element
+               var el = $(this), props = ['position','top','left'];
+
+               // 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({margin:true}) : el.outerWidth({margin:true}));
+               if (mode == 'show') el.css(ref, motion == 'pos' ? -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/js2/mwEmbed/jquery/jquery.ui/ui/effects.transfer.js b/js2/mwEmbed/jquery/jquery.ui/ui/effects.transfer.js
new file mode 100644 (file)
index 0000000..b042cfd
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * jQuery UI Effects Transfer 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Transfer
+ *
+ * Depends:
+ *     effects.core.js
+ */
+(function($) {
+
+$.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/js2/mwEmbed/jquery/jquery.ui/ui/i18n/jquery-ui-i18n.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/jquery-ui-i18n.js
new file mode 100644 (file)
index 0000000..2d90b4f
--- /dev/null
@@ -0,0 +1,771 @@
+/* Arabic Translation for jQuery UI date picker plugin. */\r
+/* Khaled Al Horani -- koko.dw@gmail.com */\r
+/* خالد الحوراني -- koko.dw@gmail.com */\r
+/* 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 */\r
+jQuery(function($){\r
+       $.datepicker.regional['ar'] = {\r
+               closeText: 'إغلاق',\r
+               prevText: '&#x3c;السابق',\r
+               nextText: 'التالي&#x3e;',\r
+               currentText: 'اليوم',\r
+               monthNames: ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'آذار', 'حزيران',\r
+               'تموز', 'آب', 'أيلول',       'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],\r
+               monthNamesShort: ['1','2','3','4','5','6','7','8','9','10','11','12'],\r
+               dayNames: ['السبت', 'الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة'],\r
+               dayNamesShort: ['سبت', 'أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة'],\r
+               dayNamesMin: ['سبت', 'أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة'],\r
+               dateFormat: 'dd/mm/yy', firstDay: 0,\r
+  isRTL: true};\r
+       $.datepicker.setDefaults($.datepicker.regional['ar']);\r
+});/* Bulgarian initialisation for the jQuery UI date picker plugin. */\r
+/* Written by Stoyan Kyosev (http://svest.org). */\r
+jQuery(function($){\r
+    $.datepicker.regional['bg'] = {\r
+        closeText: 'затвори',\r
+        prevText: '&#x3c;назад',\r
+        nextText: 'напред&#x3e;',\r
+               nextBigText: '&#x3e;&#x3e;',\r
+        currentText: 'днес',\r
+        monthNames: ['Януари','Февруари','Март','Април','Май','Юни',\r
+        'Юли','Август','Септември','Октомври','Ноември','Декември'],\r
+        monthNamesShort: ['Яну','Фев','Мар','Апр','Май','Юни',\r
+        'Юли','Авг','Сеп','Окт','Нов','Дек'],\r
+        dayNames: ['Неделя','Понеделник','Вторник','Сряда','Четвъртък','Петък','Събота'],\r
+        dayNamesShort: ['Нед','Пон','Вто','Сря','Чет','Пет','Съб'],\r
+        dayNamesMin: ['Не','По','Вт','Ср','Че','Пе','Съ'],\r
+        dateFormat: 'dd.mm.yy', firstDay: 1,\r
+        isRTL: false};\r
+    $.datepicker.setDefaults($.datepicker.regional['bg']);\r
+});\r
+/* Inicialitzaci� en catal� per a l'extenci� 'calendar' per jQuery. */\r
+/* Writers: (joan.leon@gmail.com). */\r
+jQuery(function($){\r
+       $.datepicker.regional['ca'] = {\r
+               closeText: 'Tancar',\r
+               prevText: '&#x3c;Ant',\r
+               nextText: 'Seg&#x3e;',\r
+               currentText: 'Avui',\r
+               monthNames: ['Gener','Febrer','Mar&ccedil;','Abril','Maig','Juny',\r
+               'Juliol','Agost','Setembre','Octubre','Novembre','Desembre'],\r
+               monthNamesShort: ['Gen','Feb','Mar','Abr','Mai','Jun',\r
+               'Jul','Ago','Set','Oct','Nov','Des'],\r
+               dayNames: ['Diumenge','Dilluns','Dimarts','Dimecres','Dijous','Divendres','Dissabte'],\r
+               dayNamesShort: ['Dug','Dln','Dmt','Dmc','Djs','Dvn','Dsb'],\r
+               dayNamesMin: ['Dg','Dl','Dt','Dc','Dj','Dv','Ds'],\r
+               dateFormat: 'mm/dd/yy', firstDay: 0,\r
+               isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional['ca']);\r
+});/* Czech initialisation for the jQuery UI date picker plugin. */\r
+/* Written by Tomas Muller (tomas@tomas-muller.net). */\r
+jQuery(function($){\r
+       $.datepicker.regional['cs'] = {\r
+               closeText: 'Zavřít',\r
+               prevText: '&#x3c;Dříve',\r
+               nextText: 'Později&#x3e;',\r
+               currentText: 'Nyní',\r
+               monthNames: ['leden','únor','březen','duben','květen','červen',\r
+        'červenec','srpen','září','říjen','listopad','prosinec'],\r
+               monthNamesShort: ['led','úno','bře','dub','kvě','čer',\r
+               'čvc','srp','zář','říj','lis','pro'],\r
+               dayNames: ['neděle', 'pondělí', 'úterý', 'středa', 'čtvrtek', 'pátek', 'sobota'],\r
+               dayNamesShort: ['ne', 'po', 'út', 'st', 'čt', 'pá', 'so'],\r
+               dayNamesMin: ['ne','po','út','st','čt','pá','so'],\r
+               dateFormat: 'dd.mm.yy', firstDay: 1,\r
+               isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional['cs']);\r
+});\r
+/* Danish initialisation for the jQuery UI date picker plugin. */\r
+/* Written by Jan Christensen ( deletestuff@gmail.com). */\r
+jQuery(function($){\r
+    $.datepicker.regional['da'] = {\r
+               closeText: 'Luk',\r
+        prevText: '&#x3c;Forrige',\r
+               nextText: 'Næste&#x3e;',\r
+               currentText: 'Idag',\r
+        monthNames: ['Januar','Februar','Marts','April','Maj','Juni',\r
+        'Juli','August','September','Oktober','November','December'],\r
+        monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',\r
+        'Jul','Aug','Sep','Okt','Nov','Dec'],\r
+               dayNames: ['Søndag','Mandag','Tirsdag','Onsdag','Torsdag','Fredag','Lørdag'],\r
+               dayNamesShort: ['Søn','Man','Tir','Ons','Tor','Fre','Lør'],\r
+               dayNamesMin: ['Sø','Ma','Ti','On','To','Fr','Lø'],\r
+        dateFormat: 'dd-mm-yy', firstDay: 0,\r
+               isRTL: false};\r
+    $.datepicker.setDefaults($.datepicker.regional['da']);\r
+});\r
+/* German initialisation for the jQuery UI date picker plugin. */\r
+/* Written by Milian Wolff (mail@milianw.de). */\r
+jQuery(function($){\r
+       $.datepicker.regional['de'] = {\r
+               closeText: 'schließen',\r
+               prevText: '&#x3c;zurück',\r
+               nextText: 'Vor&#x3e;',\r
+               currentText: 'heute',\r
+               monthNames: ['Januar','Februar','März','April','Mai','Juni',\r
+               'Juli','August','September','Oktober','November','Dezember'],\r
+               monthNamesShort: ['Jan','Feb','Mär','Apr','Mai','Jun',\r
+               'Jul','Aug','Sep','Okt','Nov','Dez'],\r
+               dayNames: ['Sonntag','Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag'],\r
+               dayNamesShort: ['So','Mo','Di','Mi','Do','Fr','Sa'],\r
+               dayNamesMin: ['So','Mo','Di','Mi','Do','Fr','Sa'],\r
+               dateFormat: 'dd.mm.yy', firstDay: 1,\r
+               isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional['de']);\r
+});\r
+/* Greek (el) initialisation for the jQuery UI date picker plugin. */\r
+/* Written by Alex Cicovic (http://www.alexcicovic.com) */\r
+jQuery(function($){\r
+       $.datepicker.regional['el'] = {\r
+               closeText: 'Κλείσιμο',\r
+               prevText: 'Προηγούμενος',\r
+               nextText: 'Επόμενος',\r
+               currentText: 'Τρέχων Μήνας',\r
+               monthNames: ['Ιανουάριος','Φεβρουάριος','Μάρτιος','Απρίλιος','Μάιος','Ιούνιος',\r
+               'Ιούλιος','Αύγουστος','Σεπτέμβριος','Οκτώβριος','Νοέμβριος','Δεκέμβριος'],\r
+               monthNamesShort: ['Ιαν','Φεβ','Μαρ','Απρ','Μαι','Ιουν',\r
+               'Ιουλ','Αυγ','Σεπ','Οκτ','Νοε','Δεκ'],\r
+               dayNames: ['Κυριακή','Δευτέρα','Τρίτη','Τετάρτη','Πέμπτη','Παρασκευή','Σάββατο'],\r
+               dayNamesShort: ['Κυρ','Δευ','Τρι','Τετ','Πεμ','Παρ','Σαβ'],\r
+               dayNamesMin: ['Κυ','Δε','Τρ','Τε','Πε','Πα','Σα'],\r
+               dateFormat: 'dd/mm/yy', firstDay: 1,\r
+               isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional['el']);\r
+});/* Esperanto initialisation for the jQuery UI date picker plugin. */\r
+/* Written by Olivier M. (olivierweb@ifrance.com). */\r
+jQuery(function($){\r
+       $.datepicker.regional['eo'] = {\r
+               closeText: 'Fermi',\r
+               prevText: '&lt;Anta',\r
+               nextText: 'Sekv&gt;',\r
+               currentText: 'Nuna',\r
+               monthNames: ['Januaro','Februaro','Marto','Aprilo','Majo','Junio',\r
+               'Julio','Aŭgusto','Septembro','Oktobro','Novembro','Decembro'],\r
+               monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',\r
+               'Jul','Aŭg','Sep','Okt','Nov','Dec'],\r
+               dayNames: ['Dimanĉo','Lundo','Mardo','Merkredo','Ĵaŭdo','Vendredo','Sabato'],\r
+               dayNamesShort: ['Dim','Lun','Mar','Mer','Ĵaŭ','Ven','Sab'],\r
+               dayNamesMin: ['Di','Lu','Ma','Me','Ĵa','Ve','Sa'],\r
+               dateFormat: 'dd/mm/yy', firstDay: 0,\r
+               isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional['eo']);\r
+});\r
+/* Inicializaci�n en espa�ol para la extensi�n 'UI date picker' para jQuery. */\r
+/* Traducido por Vester (xvester@gmail.com). */\r
+jQuery(function($){\r
+       $.datepicker.regional['es'] = {\r
+               closeText: 'Cerrar',\r
+               prevText: '&#x3c;Ant',\r
+               nextText: 'Sig&#x3e;',\r
+               currentText: 'Hoy',\r
+               monthNames: ['Enero','Febrero','Marzo','Abril','Mayo','Junio',\r
+               'Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre'],\r
+               monthNamesShort: ['Ene','Feb','Mar','Abr','May','Jun',\r
+               'Jul','Ago','Sep','Oct','Nov','Dic'],\r
+               dayNames: ['Domingo','Lunes','Martes','Mi&eacute;rcoles','Jueves','Viernes','S&aacute;bado'],\r
+               dayNamesShort: ['Dom','Lun','Mar','Mi&eacute;','Juv','Vie','S&aacute;b'],\r
+               dayNamesMin: ['Do','Lu','Ma','Mi','Ju','Vi','S&aacute;'],\r
+               dateFormat: 'dd/mm/yy', firstDay: 0,\r
+               isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional['es']);\r
+});/* Persian (Farsi) Translation for the jQuery UI date picker plugin. */\r
+/* Javad Mowlanezhad -- jmowla@gmail.com */\r
+/* Jalali calendar should supported soon! (Its implemented but I have to test it) */\r
+jQuery(function($) {\r
+       $.datepicker.regional['fa'] = {\r
+               closeText: 'بستن',\r
+               prevText: '&#x3c;قبلي',\r
+               nextText: 'بعدي&#x3e;',\r
+               currentText: 'امروز',\r
+               monthNames: ['فروردين','ارديبهشت','خرداد','تير','مرداد','شهريور',\r
+               'مهر','آبان','آذر','دي','بهمن','اسفند'],\r
+               monthNamesShort: ['1','2','3','4','5','6','7','8','9','10','11','12'],\r
+               dayNames: ['يکشنبه','دوشنبه','سه‌شنبه','چهارشنبه','پنجشنبه','جمعه','شنبه'],\r
+               dayNamesShort: ['ي','د','س','چ','پ','ج', 'ش'],\r
+               dayNamesMin: ['ي','د','س','چ','پ','ج', 'ش'],\r
+               dateFormat: 'yy/mm/dd', firstDay: 6,\r
+  isRTL: true};\r
+       $.datepicker.setDefaults($.datepicker.regional['fa']);\r
+});/* Finnish initialisation for the jQuery UI date picker plugin. */\r
+/* Written by Harri Kilpi� (harrikilpio@gmail.com). */\r
+jQuery(function($){\r
+    $.datepicker.regional['fi'] = {\r
+               closeText: 'Sulje',\r
+               prevText: '&laquo;Edellinen',\r
+               nextText: 'Seuraava&raquo;',\r
+               currentText: 'T&auml;n&auml;&auml;n',\r
+        monthNames: ['Tammikuu','Helmikuu','Maaliskuu','Huhtikuu','Toukokuu','Kes&auml;kuu',\r
+        'Hein&auml;kuu','Elokuu','Syyskuu','Lokakuu','Marraskuu','Joulukuu'],\r
+        monthNamesShort: ['Tammi','Helmi','Maalis','Huhti','Touko','Kes&auml;',\r
+        'Hein&auml;','Elo','Syys','Loka','Marras','Joulu'],\r
+               dayNamesShort: ['Su','Ma','Ti','Ke','To','Pe','Su'],\r
+               dayNames: ['Sunnuntai','Maanantai','Tiistai','Keskiviikko','Torstai','Perjantai','Lauantai'],\r
+               dayNamesMin: ['Su','Ma','Ti','Ke','To','Pe','La'],\r
+        dateFormat: 'dd.mm.yy', firstDay: 1,\r
+               isRTL: false};\r
+    $.datepicker.setDefaults($.datepicker.regional['fi']);\r
+});\r
+/* French initialisation for the jQuery UI date picker plugin. */\r
+/* Written by Keith Wood (kbwood@virginbroadband.com.au) and Stéphane Nahmani (sholby@sholby.net). */\r
+jQuery(function($){\r
+       $.datepicker.regional['fr'] = {\r
+               closeText: 'Fermer',\r
+               prevText: '&#x3c;Préc',\r
+               nextText: 'Suiv&#x3e;',\r
+               currentText: 'Courant',\r
+               monthNames: ['Janvier','Février','Mars','Avril','Mai','Juin',\r
+               'Juillet','Août','Septembre','Octobre','Novembre','Décembre'],\r
+               monthNamesShort: ['Jan','Fév','Mar','Avr','Mai','Jun',\r
+               'Jul','Aoû','Sep','Oct','Nov','Déc'],\r
+               dayNames: ['Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi'],\r
+               dayNamesShort: ['Dim','Lun','Mar','Mer','Jeu','Ven','Sam'],\r
+               dayNamesMin: ['Di','Lu','Ma','Me','Je','Ve','Sa'],\r
+               dateFormat: 'dd/mm/yy', firstDay: 1,\r
+               isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional['fr']);\r
+});/* Hebrew initialisation for the UI Datepicker extension. */\r
+/* Written by Amir Hardon (ahardon at gmail dot com). */\r
+jQuery(function($){\r
+       $.datepicker.regional['he'] = {\r
+               closeText: 'סגור',\r
+               prevText: '&#x3c;הקודם',\r
+               nextText: 'הבא&#x3e;',\r
+               currentText: 'היום',\r
+               monthNames: ['ינואר','פברואר','מרץ','אפריל','מאי','יוני',\r
+               'יולי','אוגוסט','ספטמבר','אוקטובר','נובמבר','דצמבר'],\r
+               monthNamesShort: ['1','2','3','4','5','6',\r
+               '7','8','9','10','11','12'],\r
+               dayNames: ['ראשון','שני','שלישי','רביעי','חמישי','שישי','שבת'],\r
+               dayNamesShort: ['א\'','ב\'','ג\'','ד\'','ה\'','ו\'','שבת'],\r
+               dayNamesMin: ['א\'','ב\'','ג\'','ד\'','ה\'','ו\'','שבת'],\r
+               dateFormat: 'dd/mm/yy', firstDay: 0,\r
+               isRTL: true};\r
+       $.datepicker.setDefaults($.datepicker.regional['he']);\r
+});\r
+/* Croatian i18n for the jQuery UI date picker plugin. */\r
+/* Written by Vjekoslav Nesek. */\r
+jQuery(function($){\r
+       $.datepicker.regional['hr'] = {\r
+               closeText: 'Zatvori',\r
+               prevText: '&#x3c;',\r
+               nextText: '&#x3e;',\r
+               currentText: 'Danas',\r
+               monthNames: ['Siječanj','Veljača','Ožujak','Travanj','Svibanj','Lipani',\r
+               'Srpanj','Kolovoz','Rujan','Listopad','Studeni','Prosinac'],\r
+               monthNamesShort: ['Sij','Velj','Ožu','Tra','Svi','Lip',\r
+               'Srp','Kol','Ruj','Lis','Stu','Pro'],\r
+               dayNames: ['Nedjalja','Ponedjeljak','Utorak','Srijeda','Četvrtak','Petak','Subota'],\r
+               dayNamesShort: ['Ned','Pon','Uto','Sri','Čet','Pet','Sub'],\r
+               dayNamesMin: ['Ne','Po','Ut','Sr','Če','Pe','Su'],\r
+               dateFormat: 'dd.mm.yy.', firstDay: 1,\r
+               isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional['hr']);\r
+});/* Hungarian initialisation for the jQuery UI date picker plugin. */\r
+/* Written by Istvan Karaszi (jquerycalendar@spam.raszi.hu). */\r
+jQuery(function($){\r
+       $.datepicker.regional['hu'] = {\r
+               closeText: 'bezárás',\r
+               prevText: '&laquo;&nbsp;vissza',\r
+               nextText: 'előre&nbsp;&raquo;',\r
+               currentText: 'ma',\r
+               monthNames: ['Január', 'Február', 'Március', 'Április', 'Május', 'Június',\r
+               'Július', 'Augusztus', 'Szeptember', 'Október', 'November', 'December'],\r
+               monthNamesShort: ['Jan', 'Feb', 'Már', 'Ápr', 'Máj', 'Jún',\r
+               'Júl', 'Aug', 'Szep', 'Okt', 'Nov', 'Dec'],\r
+               dayNames: ['Vasámap', 'Hétfö', 'Kedd', 'Szerda', 'Csütörtök', 'Péntek', 'Szombat'],\r
+               dayNamesShort: ['Vas', 'Hét', 'Ked', 'Sze', 'Csü', 'Pén', 'Szo'],\r
+               dayNamesMin: ['V', 'H', 'K', 'Sze', 'Cs', 'P', 'Szo'],\r
+               dateFormat: 'yy-mm-dd', firstDay: 1,\r
+               isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional['hu']);\r
+});\r
+/* Armenian(UTF-8) initialisation for the jQuery UI date picker plugin. */\r
+/* Written by Levon Zakaryan (levon.zakaryan@gmail.com)*/\r
+jQuery(function($){\r
+       $.datepicker.regional['hy'] = {\r
+               closeText: 'Փակել',\r
+               prevText: '&#x3c;Նախ.',\r
+               nextText: 'Հաջ.&#x3e;',\r
+               currentText: 'Այսօր',\r
+               monthNames: ['Հունվար','Փետրվար','Մարտ','Ապրիլ','Մայիս','Հունիս',\r
+               'Հուլիս','Օգոստոս','Սեպտեմբեր','Հոկտեմբեր','Նոյեմբեր','Դեկտեմբեր'],\r
+               monthNamesShort: ['Հունվ','Փետր','Մարտ','Ապր','Մայիս','Հունիս',\r
+               'Հուլ','Օգս','Սեպ','Հոկ','Նոյ','Դեկ'],\r
+               dayNames: ['կիրակի','եկուշաբթի','երեքշաբթի','չորեքշաբթի','հինգշաբթի','ուրբաթ','շաբաթ'],\r
+               dayNamesShort: ['կիր','երկ','երք','չրք','հնգ','ուրբ','շբթ'],\r
+               dayNamesMin: ['կիր','երկ','երք','չրք','հնգ','ուրբ','շբթ'],\r
+               dateFormat: 'dd.mm.yy', firstDay: 1,\r
+               isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional['hy']);\r
+});/* Indonesian initialisation for the jQuery UI date picker plugin. */\r
+/* Written by Deden Fathurahman (dedenf@gmail.com). */\r
+jQuery(function($){\r
+       $.datepicker.regional['id'] = {\r
+               closeText: 'Tutup',\r
+               prevText: '&#x3c;mundur',\r
+               nextText: 'maju&#x3e;',\r
+               currentText: 'hari ini',\r
+               monthNames: ['Januari','Februari','Maret','April','Mei','Juni',\r
+               'Juli','Agustus','September','Oktober','Nopember','Desember'],\r
+               monthNamesShort: ['Jan','Feb','Mar','Apr','Mei','Jun',\r
+               'Jul','Agus','Sep','Okt','Nop','Des'],\r
+               dayNames: ['Minggu','Senin','Selasa','Rabu','Kamis','Jumat','Sabtu'],\r
+               dayNamesShort: ['Min','Sen','Sel','Rab','kam','Jum','Sab'],\r
+               dayNamesMin: ['Mg','Sn','Sl','Rb','Km','jm','Sb'],\r
+               dateFormat: 'dd/mm/yy', firstDay: 0,\r
+               isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional['id']);\r
+});/* Icelandic initialisation for the jQuery UI date picker plugin. */\r
+/* Written by Haukur H. Thorsson (haukur@eskill.is). */\r
+jQuery(function($){\r
+       $.datepicker.regional['is'] = {\r
+               closeText: 'Loka',\r
+               prevText: '&#x3c; Fyrri',\r
+               nextText: 'N&aelig;sti &#x3e;',\r
+               currentText: '&Iacute; dag',\r
+               monthNames: ['Jan&uacute;ar','Febr&uacute;ar','Mars','Apr&iacute;l','Ma&iacute','J&uacute;n&iacute;',\r
+               'J&uacute;l&iacute;','&Aacute;g&uacute;st','September','Okt&oacute;ber','N&oacute;vember','Desember'],\r
+               monthNamesShort: ['Jan','Feb','Mar','Apr','Ma&iacute;','J&uacute;n',\r
+               'J&uacute;l','&Aacute;g&uacute;','Sep','Okt','N&oacute;v','Des'],\r
+               dayNames: ['Sunnudagur','M&aacute;nudagur','&THORN;ri&eth;judagur','Mi&eth;vikudagur','Fimmtudagur','F&ouml;studagur','Laugardagur'],\r
+               dayNamesShort: ['Sun','M&aacute;n','&THORN;ri','Mi&eth;','Fim','F&ouml;s','Lau'],\r
+               dayNamesMin: ['Su','M&aacute;','&THORN;r','Mi','Fi','F&ouml;','La'],\r
+               dateFormat: 'dd/mm/yy', firstDay: 0,\r
+               isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional['is']);\r
+});/* Italian initialisation for the jQuery UI date picker plugin. */\r
+/* Written by Apaella (apaella@gmail.com). */\r
+jQuery(function($){\r
+       $.datepicker.regional['it'] = {\r
+               closeText: 'Chiudi',\r
+               prevText: '&#x3c;Prec',\r
+               nextText: 'Succ&#x3e;',\r
+               currentText: 'Oggi',\r
+               monthNames: ['Gennaio','Febbraio','Marzo','Aprile','Maggio','Giugno',\r
+               'Luglio','Agosto','Settembre','Ottobre','Novembre','Dicembre'],\r
+               monthNamesShort: ['Gen','Feb','Mar','Apr','Mag','Giu',\r
+               'Lug','Ago','Set','Ott','Nov','Dic'],\r
+               dayNames: ['Domenica','Luned&#236','Marted&#236','Mercoled&#236','Gioved&#236','Venerd&#236','Sabato'],\r
+               dayNamesShort: ['Dom','Lun','Mar','Mer','Gio','Ven','Sab'],\r
+               dayNamesMin: ['Do','Lu','Ma','Me','Gio','Ve','Sa'],\r
+               dateFormat: 'dd/mm/yy', firstDay: 1,\r
+               isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional['it']);\r
+});\r
+/* Japanese initialisation for the jQuery UI date picker plugin. */\r
+/* Written by Kentaro SATO (kentaro@ranvis.com). */\r
+jQuery(function($){\r
+       $.datepicker.regional['ja'] = {\r
+               closeText: '閉じる',\r
+               prevText: '&#x3c;前',\r
+               nextText: '次&#x3e;',\r
+               currentText: '今日',\r
+               monthNames: ['1月','2月','3月','4月','5月','6月',\r
+               '7月','8月','9月','10月','11月','12月'],\r
+               monthNamesShort: ['1月','2月','3月','4月','5月','6月',\r
+               '7月','8月','9月','10月','11月','12月'],\r
+               dayNames: ['日曜日','月曜日','火曜日','水曜日','木曜日','金曜日','土曜日'],\r
+               dayNamesShort: ['日','月','火','水','木','金','土'],\r
+               dayNamesMin: ['日','月','火','水','木','金','土'],\r
+               dateFormat: 'yy/mm/dd', firstDay: 0,\r
+               isRTL: false,\r
+               showMonthAfterYear: true};\r
+       $.datepicker.setDefaults($.datepicker.regional['ja']);\r
+});/* Korean initialisation for the jQuery calendar extension. */\r
+/* Written by DaeKwon Kang (ncrash.dk@gmail.com). */\r
+jQuery(function($){\r
+       $.datepicker.regional['ko'] = {\r
+               closeText: '닫기',\r
+               prevText: '이전달',\r
+               nextText: '다음달',\r
+               currentText: '오늘',\r
+               monthNames: ['1월(JAN)','2월(FEB)','3월(MAR)','4월(APR)','5월(MAY)','6월(JUN)',\r
+               '7월(JUL)','8월(AUG)','9월(SEP)','10월(OCT)','11월(NOV)','12월(DEC)'],\r
+               monthNamesShort: ['1월(JAN)','2월(FEB)','3월(MAR)','4월(APR)','5월(MAY)','6월(JUN)',\r
+               '7월(JUL)','8월(AUG)','9월(SEP)','10월(OCT)','11월(NOV)','12월(DEC)'],\r
+               dayNames: ['일','월','화','수','목','금','토'],\r
+               dayNamesShort: ['일','월','화','수','목','금','토'],\r
+               dayNamesMin: ['일','월','화','수','목','금','토'],\r
+               dateFormat: 'yy-mm-dd', firstDay: 0,\r
+               isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional['ko']);\r
+});/* Lithuanian (UTF-8) initialisation for the jQuery UI date picker plugin. */\r
+/* @author Arturas Paleicikas <arturas@avalon.lt> */\r
+jQuery(function($){\r
+       $.datepicker.regional['lt'] = {\r
+               closeText: 'Uždaryti',\r
+               prevText: '&#x3c;Atgal',\r
+               nextText: 'Pirmyn&#x3e;',\r
+               currentText: 'Šiandien',\r
+               monthNames: ['Sausis','Vasaris','Kovas','Balandis','Gegužė','Birželis',\r
+               'Liepa','Rugpjūtis','Rugsėjis','Spalis','Lapkritis','Gruodis'],\r
+               monthNamesShort: ['Sau','Vas','Kov','Bal','Geg','Bir',\r
+               'Lie','Rugp','Rugs','Spa','Lap','Gru'],\r
+               dayNames: ['sekmadienis','pirmadienis','antradienis','trečiadienis','ketvirtadienis','penktadienis','šeštadienis'],\r
+               dayNamesShort: ['sek','pir','ant','tre','ket','pen','šeš'],\r
+               dayNamesMin: ['Se','Pr','An','Tr','Ke','Pe','Še'],\r
+               dateFormat: 'yy-mm-dd', firstDay: 1,\r
+               isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional['lt']);\r
+});/* Latvian (UTF-8) initialisation for the jQuery UI date picker plugin. */\r
+/* @author Arturas Paleicikas <arturas.paleicikas@metasite.net> */\r
+jQuery(function($){\r
+       $.datepicker.regional['lv'] = {\r
+               closeText: 'Aizvērt',\r
+               prevText: 'Iepr',\r
+               nextText: 'Nāka',\r
+               currentText: 'Šodien',\r
+               monthNames: ['Janvāris','Februāris','Marts','Aprīlis','Maijs','Jūnijs',\r
+               'Jūlijs','Augusts','Septembris','Oktobris','Novembris','Decembris'],\r
+               monthNamesShort: ['Jan','Feb','Mar','Apr','Mai','Jūn',\r
+               'Jūl','Aug','Sep','Okt','Nov','Dec'],\r
+               dayNames: ['svētdiena','pirmdiena','otrdiena','trešdiena','ceturtdiena','piektdiena','sestdiena'],\r
+               dayNamesShort: ['svt','prm','otr','tre','ctr','pkt','sst'],\r
+               dayNamesMin: ['Sv','Pr','Ot','Tr','Ct','Pk','Ss'],\r
+               dateFormat: 'dd-mm-yy', firstDay: 1,\r
+               isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional['lv']);\r
+});/* Malaysian initialisation for the jQuery UI date picker plugin. */\r
+/* Written by Mohd Nawawi Mohamad Jamili (nawawi@ronggeng.net). */\r
+jQuery(function($){\r
+       $.datepicker.regional['ms'] = {\r
+               closeText: 'Tutup',\r
+               prevText: '&#x3c;Sebelum',\r
+               nextText: 'Selepas&#x3e;',\r
+               currentText: 'hari ini',\r
+               monthNames: ['Januari','Februari','Mac','April','Mei','Jun',\r
+               'Julai','Ogos','September','Oktober','November','Disember'],\r
+               monthNamesShort: ['Jan','Feb','Mac','Apr','Mei','Jun',\r
+               'Jul','Ogo','Sep','Okt','Nov','Dis'],\r
+               dayNames: ['Ahad','Isnin','Selasa','Rabu','Khamis','Jumaat','Sabtu'],\r
+               dayNamesShort: ['Aha','Isn','Sel','Rab','kha','Jum','Sab'],\r
+               dayNamesMin: ['Ah','Is','Se','Ra','Kh','Ju','Sa'],\r
+               dateFormat: 'dd/mm/yy', firstDay: 0,\r
+               isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional['ms']);\r
+});/* Dutch (UTF-8) initialisation for the jQuery UI date picker plugin. */\r
+/* Written by Mathias Bynens <http://mathiasbynens.be/> */\r
+jQuery(function($){\r
+       $.datepicker.regional.nl = {\r
+               closeText: 'Sluiten',\r
+               prevText: '←',\r
+               nextText: '→',\r
+               currentText: 'Vandaag',\r
+               monthNames: ['januari', 'februari', 'maart', 'april', 'mei', 'juni',\r
+               'juli', 'augustus', 'september', 'oktober', 'november', 'december'],\r
+               monthNamesShort: ['jan', 'feb', 'maa', 'apr', 'mei', 'jun',\r
+               'jul', 'aug', 'sep', 'okt', 'nov', 'dec'],\r
+               dayNames: ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag', 'zaterdag'],\r
+               dayNamesShort: ['zon', 'maa', 'din', 'woe', 'don', 'vri', 'zat'],\r
+               dayNamesMin: ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],\r
+               dateFormat: 'dd/mm/yy', firstDay: 1,\r
+               isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional.nl);\r
+});/* Norwegian initialisation for the jQuery UI date picker plugin. */\r
+/* Written by Naimdjon Takhirov (naimdjon@gmail.com). */\r
+jQuery(function($){\r
+    $.datepicker.regional['no'] = {\r
+               closeText: 'Lukk',\r
+        prevText: '&laquo;Forrige',\r
+               nextText: 'Neste&raquo;',\r
+               currentText: 'I dag',\r
+        monthNames: ['Januar','Februar','Mars','April','Mai','Juni',\r
+        'Juli','August','September','Oktober','November','Desember'],\r
+        monthNamesShort: ['Jan','Feb','Mar','Apr','Mai','Jun',\r
+        'Jul','Aug','Sep','Okt','Nov','Des'],\r
+               dayNamesShort: ['Søn','Man','Tir','Ons','Tor','Fre','Lør'],\r
+               dayNames: ['Søndag','Mandag','Tirsdag','Onsdag','Torsdag','Fredag','Lørdag'],\r
+               dayNamesMin: ['Sø','Ma','Ti','On','To','Fr','Lø'],\r
+        dateFormat: 'yy-mm-dd', firstDay: 0,\r
+               isRTL: false};\r
+    $.datepicker.setDefaults($.datepicker.regional['no']);\r
+});\r
+/* Polish initialisation for the jQuery UI date picker plugin. */\r
+/* Written by Jacek Wysocki (jacek.wysocki@gmail.com). */\r
+jQuery(function($){\r
+       $.datepicker.regional['pl'] = {\r
+               closeText: 'Zamknij',\r
+               prevText: '&#x3c;Poprzedni',\r
+               nextText: 'Następny&#x3e;',\r
+               currentText: 'Dziś',\r
+               monthNames: ['Styczeń','Luty','Marzec','Kwiecień','Maj','Czerwiec',\r
+               'Lipiec','Sierpień','Wrzesień','Październik','Listopad','Grudzień'],\r
+               monthNamesShort: ['Sty','Lu','Mar','Kw','Maj','Cze',\r
+               'Lip','Sie','Wrz','Pa','Lis','Gru'],\r
+               dayNames: ['Niedziela','Poniedzialek','Wtorek','Środa','Czwartek','Piątek','Sobota'],\r
+               dayNamesShort: ['Nie','Pn','Wt','Śr','Czw','Pt','So'],\r
+               dayNamesMin: ['N','Pn','Wt','Śr','Cz','Pt','So'],\r
+               dateFormat: 'yy-mm-dd', firstDay: 1,\r
+               isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional['pl']);\r
+});\r
+/* Brazilian initialisation for the jQuery UI date picker plugin. */\r
+/* Written by Leonildo Costa Silva (leocsilva@gmail.com). */\r
+jQuery(function($){\r
+       $.datepicker.regional['pt-BR'] = {\r
+               closeText: 'Fechar',\r
+               prevText: '&#x3c;Anterior',\r
+               nextText: 'Pr&oacute;ximo&#x3e;',\r
+               currentText: 'Hoje',\r
+               monthNames: ['Janeiro','Fevereiro','Mar&ccedil;o','Abril','Maio','Junho',\r
+               'Julho','Agosto','Setembro','Outubro','Novembro','Dezembro'],\r
+               monthNamesShort: ['Jan','Fev','Mar','Abr','Mai','Jun',\r
+               'Jul','Ago','Set','Out','Nov','Dez'],\r
+               dayNames: ['Domingo','Segunda-feira','Ter&ccedil;a-feira','Quarta-feira','Quinta-feira','Sexta-feira','Sabado'],\r
+               dayNamesShort: ['Dom','Seg','Ter','Qua','Qui','Sex','Sab'],\r
+               dayNamesMin: ['Dom','Seg','Ter','Qua','Qui','Sex','Sab'],\r
+               dateFormat: 'dd/mm/yy', firstDay: 0,\r
+               isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional['pt-BR']);\r
+});/* Romanian initialisation for the jQuery UI date picker plugin.\r
+ *\r
+ * Written by Edmond L. (ll_edmond@walla.com)\r
+ * and Ionut G. Stan (ionut.g.stan@gmail.com)\r
+ */\r
+jQuery(function($){\r
+       $.datepicker.regional['ro'] = {\r
+               closeText: 'Închide',\r
+               prevText: '&laquo; Luna precedentă',\r
+               nextText: 'Luna următoare &raquo;',\r
+               currentText: 'Azi',\r
+               monthNames: ['Ianuarie','Februarie','Martie','Aprilie','Mai','Iunie',\r
+               'Iulie','August','Septembrie','Octombrie','Noiembrie','Decembrie'],\r
+               monthNamesShort: ['Ian', 'Feb', 'Mar', 'Apr', 'Mai', 'Iun',\r
+               'Iul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],\r
+               dayNames: ['Duminică', 'Luni', 'Marţi', 'Miercuri', 'Joi', 'Vineri', 'Sâmbătă'],\r
+               dayNamesShort: ['Dum', 'Lun', 'Mar', 'Mie', 'Joi', 'Vin', 'Sâm'],\r
+               dayNamesMin: ['Du','Lu','Ma','Mi','Jo','Vi','Sâ'],\r
+               dateFormat: 'dd MM yy', firstDay: 1,\r
+               isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional['ro']);\r
+});\r
+/* Russian (UTF-8) initialisation for the jQuery UI date picker plugin. */\r
+/* Written by Andrew Stromnov (stromnov@gmail.com). */\r
+jQuery(function($){\r
+       $.datepicker.regional['ru'] = {\r
+               closeText: 'Закрыть',\r
+               prevText: '&#x3c;Пред',\r
+               nextText: 'След&#x3e;',\r
+               currentText: 'Сегодня',\r
+               monthNames: ['Январь','Февраль','Март','Апрель','Май','Июнь',\r
+               'Июль','Август','Сентябрь','Октябрь','Ноябрь','Декабрь'],\r
+               monthNamesShort: ['Янв','Фев','Мар','Апр','Май','Июн',\r
+               'Июл','Авг','Сен','Окт','Ноя','Дек'],\r
+               dayNames: ['воскресенье','понедельник','вторник','среда','четверг','пятница','суббота'],\r
+               dayNamesShort: ['вск','пнд','втр','срд','чтв','птн','сбт'],\r
+               dayNamesMin: ['Вс','Пн','Вт','Ср','Чт','Пт','Сб'],\r
+               dateFormat: 'dd.mm.yy', firstDay: 1,\r
+               isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional['ru']);\r
+});/* Slovak initialisation for the jQuery UI date picker plugin. */\r
+/* Written by Vojtech Rinik (vojto@hmm.sk). */\r
+jQuery(function($){\r
+       $.datepicker.regional['sk'] = {\r
+               closeText: 'Zavrieť',\r
+               prevText: '&#x3c;Predchádzajúci',\r
+               nextText: 'Nasledujúci&#x3e;',\r
+               currentText: 'Dnes',\r
+               monthNames: ['Január','Február','Marec','Apríl','Máj','Jún',\r
+               'Júl','August','September','Október','November','December'],\r
+               monthNamesShort: ['Jan','Feb','Mar','Apr','Máj','Jún',\r
+               'Júl','Aug','Sep','Okt','Nov','Dec'],\r
+               dayNames: ['Nedel\'a','Pondelok','Utorok','Streda','Štvrtok','Piatok','Sobota'],\r
+               dayNamesShort: ['Ned','Pon','Uto','Str','Štv','Pia','Sob'],\r
+               dayNamesMin: ['Ne','Po','Ut','St','Št','Pia','So'],\r
+               dateFormat: 'dd.mm.yy', firstDay: 0,\r
+               isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional['sk']);\r
+});\r
+/* Slovenian initialisation for the jQuery UI date picker plugin. */\r
+/* Written by Jaka Jancar (jaka@kubje.org). */\r
+/* c = &#x10D;, s = &#x161; z = &#x17E; C = &#x10C; S = &#x160; Z = &#x17D; */\r
+jQuery(function($){\r
+       $.datepicker.regional['sl'] = {\r
+               closeText: 'Zapri',\r
+               prevText: '&lt;Prej&#x161;nji',\r
+               nextText: 'Naslednji&gt;',\r
+               currentText: 'Trenutni',\r
+               monthNames: ['Januar','Februar','Marec','April','Maj','Junij',\r
+               'Julij','Avgust','September','Oktober','November','December'],\r
+               monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',\r
+               'Jul','Avg','Sep','Okt','Nov','Dec'],\r
+               dayNames: ['Nedelja','Ponedeljek','Torek','Sreda','&#x10C;etrtek','Petek','Sobota'],\r
+               dayNamesShort: ['Ned','Pon','Tor','Sre','&#x10C;et','Pet','Sob'],\r
+               dayNamesMin: ['Ne','Po','To','Sr','&#x10C;e','Pe','So'],\r
+               dateFormat: 'dd.mm.yy', firstDay: 1,\r
+               isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional['sl']);\r
+});\r
+/* Albanian initialisation for the jQuery UI date picker plugin. */\r
+/* Written by Flakron Bytyqi (flakron@gmail.com). */\r
+jQuery(function($){\r
+       $.datepicker.regional['sq'] = {\r
+               closeText: 'mbylle',\r
+               prevText: '&#x3c;mbrapa',\r
+               nextText: 'Përpara&#x3e;',\r
+               currentText: 'sot',\r
+               monthNames: ['Janar','Shkurt','Mars','Prill','Maj','Qershor',\r
+               'Korrik','Gusht','Shtator','Tetor','Nëntor','Dhjetor'],\r
+               monthNamesShort: ['Jan','Shk','Mar','Pri','Maj','Qer',\r
+               'Kor','Gus','Sht','Tet','Nën','Dhj'],\r
+               dayNames: ['E Diel','E Hënë','E Martë','E Mërkurë','E Enjte','E Premte','E Shtune'],\r
+               dayNamesShort: ['Di','Hë','Ma','Më','En','Pr','Sh'],\r
+               dayNamesMin: ['Di','Hë','Ma','Më','En','Pr','Sh'],\r
+               dateFormat: 'dd.mm.yy', firstDay: 1,\r
+               isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional['sq']);\r
+});\r
+/* Serbian i18n for the jQuery UI date picker plugin. */\r
+/* Written by Dejan Dimić. */\r
+jQuery(function($){\r
+       $.datepicker.regional['sr-SR'] = {\r
+               closeText: 'Zatvori',\r
+               prevText: '&#x3c;',\r
+               nextText: '&#x3e;',\r
+               currentText: 'Danas',\r
+               monthNames: ['Januar','Februar','Mart','April','Maj','Jun',\r
+               'Jul','Avgust','Septembar','Oktobar','Novembar','Decembar'],\r
+               monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',\r
+               'Jul','Avg','Sep','Okt','Nov','Dec'],\r
+               dayNames: ['Nedelja','Ponedeljak','Utorak','Sreda','Četvrtak','Petak','Subota'],\r
+               dayNamesShort: ['Ned','Pon','Uto','Sre','Čet','Pet','Sub'],\r
+               dayNamesMin: ['Ne','Po','Ut','Sr','Če','Pe','Su'],\r
+               dateFormat: 'dd/mm/yy', firstDay: 1,\r
+               isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional['sr-SR']);\r
+});
+/* Serbian i18n for the jQuery UI date picker plugin. */\r
+/* Written by Dejan Dimić. */\r
+jQuery(function($){\r
+       $.datepicker.regional['sr'] = {\r
+               closeText: 'Затвори',\r
+               prevText: '&#x3c;',\r
+               nextText: '&#x3e;',\r
+               currentText: 'Данас',\r
+               monthNames: ['Јануар','Фебруар','Март','Април','Мај','Јун',\r
+               'Јул','Август','Септембар','Октобар','Новембар','Децембар'],\r
+               monthNamesShort: ['Јан','Феб','Мар','Апр','Мај','Јун',\r
+               'Јул','Авг','Сеп','Окт','Нов','Дец'],\r
+               dayNames: ['Недеља','Понедељак','Уторак','Среда','Четвртак','Петак','Субота'],\r
+               dayNamesShort: ['Нед','Пон','Уто','Сре','Чет','Пет','Суб'],\r
+               dayNamesMin: ['Не','По','Ут','Ср','Че','Пе','Су'],\r
+               dateFormat: 'dd/mm/yy', firstDay: 1,\r
+               isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional['sr']);\r
+});
+/* Swedish initialisation for the jQuery UI date picker plugin. */\r
+/* Written by Anders Ekdahl ( anders@nomadiz.se). */\r
+jQuery(function($){\r
+    $.datepicker.regional['sv'] = {\r
+               closeText: 'Stäng',\r
+        prevText: '&laquo;Förra',\r
+               nextText: 'Nästa&raquo;',\r
+               currentText: 'Idag',\r
+        monthNames: ['Januari','Februari','Mars','April','Maj','Juni',\r
+        'Juli','Augusti','September','Oktober','November','December'],\r
+        monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',\r
+        'Jul','Aug','Sep','Okt','Nov','Dec'],\r
+               dayNamesShort: ['Sön','Mån','Tis','Ons','Tor','Fre','Lör'],\r
+               dayNames: ['Söndag','Måndag','Tisdag','Onsdag','Torsdag','Fredag','Lördag'],\r
+               dayNamesMin: ['Sö','Må','Ti','On','To','Fr','Lö'],\r
+        dateFormat: 'yy-mm-dd', firstDay: 1,\r
+               isRTL: false};\r
+    $.datepicker.setDefaults($.datepicker.regional['sv']);\r
+});\r
+/* Thai initialisation for the jQuery UI date picker plugin. */\r
+/* Written by pipo (pipo@sixhead.com). */\r
+jQuery(function($){\r
+       $.datepicker.regional['th'] = {\r
+               closeText: 'ปิด',\r
+               prevText: '&laquo;&nbsp;ย้อน',\r
+               nextText: 'ถัดไป&nbsp;&raquo;',\r
+               currentText: 'วันนี้',\r
+               monthNames: ['มกราคม','กุมภาพันธ์','มีนาคม','เมษายน','พฤษภาคม','มิถุนายน',\r
+               'กรกฏาคม','สิงหาคม','กันยายน','ตุลาคม','พฤศจิกายน','ธันวาคม'],\r
+               monthNamesShort: ['ม.ค.','ก.พ.','มี.ค.','เม.ย.','พ.ค.','มิ.ย.',\r
+               'ก.ค.','ส.ค.','ก.ย.','ต.ค.','พ.ย.','ธ.ค.'],\r
+               dayNames: ['อาทิตย์','จันทร์','อังคาร','พุธ','พฤหัสบดี','ศุกร์','เสาร์'],\r
+               dayNamesShort: ['อา.','จ.','อ.','พ.','พฤ.','ศ.','ส.'],\r
+               dayNamesMin: ['อา.','จ.','อ.','พ.','พฤ.','ศ.','ส.'],\r
+               dateFormat: 'dd/mm/yy', firstDay: 0,\r
+               isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional['th']);\r
+});/* Turkish initialisation for the jQuery UI date picker plugin. */\r
+/* Written by Izzet Emre Erkan (kara@karalamalar.net). */\r
+jQuery(function($){\r
+       $.datepicker.regional['tr'] = {\r
+               closeText: 'kapat',\r
+               prevText: '&#x3c;geri',\r
+               nextText: 'ileri&#x3e',\r
+               currentText: 'bugün',\r
+               monthNames: ['Ocak','Şubat','Mart','Nisan','Mayıs','Haziran',\r
+               'Temmuz','Ağustos','Eylül','Ekim','Kasım','Aralık'],\r
+               monthNamesShort: ['Oca','Şub','Mar','Nis','May','Haz',\r
+               'Tem','Ağu','Eyl','Eki','Kas','Ara'],\r
+               dayNames: ['Pazar','Pazartesi','Salı','Çarşamba','Perşembe','Cuma','Cumartesi'],\r
+               dayNamesShort: ['Pz','Pt','Sa','Ça','Pe','Cu','Ct'],\r
+               dayNamesMin: ['Pz','Pt','Sa','Ça','Pe','Cu','Ct'],\r
+               dateFormat: 'dd.mm.yy', firstDay: 1,\r
+               isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional['tr']);\r
+});/* Ukrainian (UTF-8) initialisation for the jQuery UI date picker plugin. */\r
+/* Written by Maxim Drogobitskiy (maxdao@gmail.com). */\r
+jQuery(function($){\r
+       $.datepicker.regional['uk'] = {\r
+               clearText: 'Очистити', clearStatus: '',\r
+               closeText: 'Закрити', closeStatus: '',\r
+               prevText: '&#x3c;',  prevStatus: '',\r
+               prevBigText: '&#x3c;&#x3c;', prevBigStatus: '',\r
+               nextText: '&#x3e;', nextStatus: '',\r
+               nextBigText: '&#x3e;&#x3e;', nextBigStatus: '',\r
+               currentText: 'Сьогодні', currentStatus: '',\r
+               monthNames: ['Січень','Лютий','Березень','Квітень','Травень','Червень',\r
+               'Липень','Серпень','Вересень','Жовтень','Листопад','Грудень'],\r
+               monthNamesShort: ['Січ','Лют','Бер','Кві','Тра','Чер',\r
+               'Лип','Сер','Вер','Жов','Лис','Гру'],\r
+               monthStatus: '', yearStatus: '',\r
+               weekHeader: 'Не', weekStatus: '',\r
+               dayNames: ['неділя','понеділок','вівторок','середа','четвер','п’ятниця','субота'],\r
+               dayNamesShort: ['нед','пнд','вів','срд','чтв','птн','сбт'],\r
+               dayNamesMin: ['Нд','Пн','Вт','Ср','Чт','Пт','Сб'],\r
+               dayStatus: 'DD', dateStatus: 'D, M d',\r
+               dateFormat: 'dd/mm/yy', firstDay: 1,\r
+               initStatus: '', isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional['uk']);\r
+});/* Chinese initialisation for the jQuery UI date picker plugin. */\r
+/* Written by Cloudream (cloudream@gmail.com). */\r
+jQuery(function($){\r
+       $.datepicker.regional['zh-CN'] = {\r
+               closeText: '关闭',\r
+               prevText: '&#x3c;上月',\r
+               nextText: '下月&#x3e;',\r
+               currentText: '今天',\r
+               monthNames: ['一月','二月','三月','四月','五月','六月',\r
+               '七月','八月','九月','十月','十一月','十二月'],\r
+               monthNamesShort: ['一','二','三','四','五','六',\r
+               '七','八','九','十','十一','十二'],\r
+               dayNames: ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'],\r
+               dayNamesShort: ['周日','周一','周二','周三','周四','周五','周六'],\r
+               dayNamesMin: ['日','一','二','三','四','五','六'],\r
+               dateFormat: 'yy-mm-dd', firstDay: 1,\r
+               isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional['zh-CN']);\r
+});\r
+/* Chinese initialisation for the jQuery UI date picker plugin. */\r
+/* Written by Ressol (ressol@gmail.com). */\r
+jQuery(function($){\r
+       $.datepicker.regional['zh-TW'] = {\r
+               closeText: '關閉',\r
+               prevText: '&#x3c;上月',\r
+               nextText: '下月&#x3e;',\r
+               currentText: '今天',\r
+               monthNames: ['一月','二月','三月','四月','五月','六月',\r
+               '七月','八月','九月','十月','十一月','十二月'],\r
+               monthNamesShort: ['一','二','三','四','五','六',\r
+               '七','八','九','十','十一','十二'],\r
+               dayNames: ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'],\r
+               dayNamesShort: ['周日','周一','周二','周三','周四','周五','周六'],\r
+               dayNamesMin: ['日','一','二','三','四','五','六'],\r
+               dateFormat: 'yy/mm/dd', firstDay: 1,\r
+               isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional['zh-TW']);\r
+});\r
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-ar.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-ar.js
new file mode 100644 (file)
index 0000000..b605878
--- /dev/null
@@ -0,0 +1,20 @@
+/* Arabic Translation for jQuery UI date picker plugin. */
+/* Khaled Al Horani -- koko.dw@gmail.com */
+/* خالد الحوراني -- koko.dw@gmail.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: ['سبت', 'أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة'],
+               dateFormat: 'dd/mm/yy', firstDay: 0,
+  isRTL: true};
+       $.datepicker.setDefaults($.datepicker.regional['ar']);
+});
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-bg.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-bg.js
new file mode 100644 (file)
index 0000000..a73884e
--- /dev/null
@@ -0,0 +1,20 @@
+/* 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: ['Не','По','Вт','Ср','Че','Пе','Съ'],
+        dateFormat: 'dd.mm.yy', firstDay: 1,
+        isRTL: false};
+    $.datepicker.setDefaults($.datepicker.regional['bg']);
+});
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-ca.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-ca.js
new file mode 100644 (file)
index 0000000..ad47af0
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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'],
+               dateFormat: 'mm/dd/yy', firstDay: 0,
+               isRTL: false};
+       $.datepicker.setDefaults($.datepicker.regional['ca']);
+});
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-cs.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-cs.js
new file mode 100644 (file)
index 0000000..334ae2f
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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'],
+               dateFormat: 'dd.mm.yy', firstDay: 1,
+               isRTL: false};
+       $.datepicker.setDefaults($.datepicker.regional['cs']);
+});
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-da.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-da.js
new file mode 100644 (file)
index 0000000..8ad1e2c
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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ø'],
+        dateFormat: 'dd-mm-yy', firstDay: 0,
+               isRTL: false};
+    $.datepicker.setDefaults($.datepicker.regional['da']);
+});
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-de.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-de.js
new file mode 100644 (file)
index 0000000..f9299c8
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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'],
+               dateFormat: 'dd.mm.yy', firstDay: 1,
+               isRTL: false};
+       $.datepicker.setDefaults($.datepicker.regional['de']);
+});
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-el.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-el.js
new file mode 100644 (file)
index 0000000..535080d
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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: ['Κυ','Δε','Τρ','Τε','Πε','Πα','Σα'],
+               dateFormat: 'dd/mm/yy', firstDay: 1,
+               isRTL: false};
+       $.datepicker.setDefaults($.datepicker.regional['el']);
+});
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-eo.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-eo.js
new file mode 100644 (file)
index 0000000..28abac4
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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'],
+               dateFormat: 'dd/mm/yy', firstDay: 0,
+               isRTL: false};
+       $.datepicker.setDefaults($.datepicker.regional['eo']);
+});
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-es.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-es.js
new file mode 100644 (file)
index 0000000..0a699af
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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;'],
+               dateFormat: 'dd/mm/yy', firstDay: 0,
+               isRTL: false};
+       $.datepicker.setDefaults($.datepicker.regional['es']);
+});
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-fa.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-fa.js
new file mode 100644 (file)
index 0000000..e40e1ac
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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: ['ي','د','س','چ','پ','ج', 'ش'],
+               dateFormat: 'yy/mm/dd', firstDay: 6,
+  isRTL: true};
+       $.datepicker.setDefaults($.datepicker.regional['fa']);
+});
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-fi.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-fi.js
new file mode 100644 (file)
index 0000000..980e0bb
--- /dev/null
@@ -0,0 +1,19 @@
+/* Finnish initialisation for the jQuery UI date picker plugin. */
+/* Written by Harri Kilpi� (harrikilpio@gmail.com). */
+jQuery(function($){
+       $.datepicker.regional['fi'] = {
+               closeText: 'Sulje',
+               prevText: '&laquo;Edellinen',
+               nextText: 'Seuraava&raquo;',
+               currentText: 'T&auml;n&auml;&auml;n',
+               monthNames: ['Tammikuu','Helmikuu','Maaliskuu','Huhtikuu','Toukokuu','Kes&auml;kuu',
+               'Hein&auml;kuu','Elokuu','Syyskuu','Lokakuu','Marraskuu','Joulukuu'],
+               monthNamesShort: ['Tammi','Helmi','Maalis','Huhti','Touko','Kes&auml;',
+               'Hein&auml;','Elo','Syys','Loka','Marras','Joulu'],
+               dayNamesShort: ['Su','Ma','Ti','Ke','To','Pe','Su'],
+               dayNames: ['Sunnuntai','Maanantai','Tiistai','Keskiviikko','Torstai','Perjantai','Lauantai'],
+               dayNamesMin: ['Su','Ma','Ti','Ke','To','Pe','La'],
+               dateFormat: 'dd.mm.yy', firstDay: 1,
+               isRTL: false};
+       $.datepicker.setDefaults($.datepicker.regional['fi']);
+});
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-fr.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-fr.js
new file mode 100644 (file)
index 0000000..02edda2
--- /dev/null
@@ -0,0 +1,19 @@
+/* French initialisation for the jQuery UI date picker plugin. */
+/* Written by Keith Wood (kbwood@virginbroadband.com.au) and Stéphane Nahmani (sholby@sholby.net). */
+jQuery(function($){
+       $.datepicker.regional['fr'] = {
+               closeText: 'Fermer',
+               prevText: '&#x3c;Préc',
+               nextText: 'Suiv&#x3e;',
+               currentText: 'Courant',
+               monthNames: ['Janvier','Février','Mars','Avril','Mai','Juin',
+               'Juillet','Août','Septembre','Octobre','Novembre','Décembre'],
+               monthNamesShort: ['Jan','Fév','Mar','Avr','Mai','Jun',
+               'Jul','Aoû','Sep','Oct','Nov','Déc'],
+               dayNames: ['Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi'],
+               dayNamesShort: ['Dim','Lun','Mar','Mer','Jeu','Ven','Sam'],
+               dayNamesMin: ['Di','Lu','Ma','Me','Je','Ve','Sa'],
+               dateFormat: 'dd/mm/yy', firstDay: 1,
+               isRTL: false};
+       $.datepicker.setDefaults($.datepicker.regional['fr']);
+});
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-he.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-he.js
new file mode 100644 (file)
index 0000000..38e0a03
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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: ['1','2','3','4','5','6',
+               '7','8','9','10','11','12'],
+               dayNames: ['ראשון','שני','שלישי','רביעי','חמישי','שישי','שבת'],
+               dayNamesShort: ['א\'','ב\'','ג\'','ד\'','ה\'','ו\'','שבת'],
+               dayNamesMin: ['א\'','ב\'','ג\'','ד\'','ה\'','ו\'','שבת'],
+               dateFormat: 'dd/mm/yy', firstDay: 0,
+               isRTL: true};
+       $.datepicker.setDefaults($.datepicker.regional['he']);
+});
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-hr.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-hr.js
new file mode 100644 (file)
index 0000000..78e4006
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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','Lipani',
+               'Srpanj','Kolovoz','Rujan','Listopad','Studeni','Prosinac'],
+               monthNamesShort: ['Sij','Velj','Ožu','Tra','Svi','Lip',
+               'Srp','Kol','Ruj','Lis','Stu','Pro'],
+               dayNames: ['Nedjalja','Ponedjeljak','Utorak','Srijeda','Četvrtak','Petak','Subota'],
+               dayNamesShort: ['Ned','Pon','Uto','Sri','Čet','Pet','Sub'],
+               dayNamesMin: ['Ne','Po','Ut','Sr','Če','Pe','Su'],
+               dateFormat: 'dd.mm.yy.', firstDay: 1,
+               isRTL: false};
+       $.datepicker.setDefaults($.datepicker.regional['hr']);
+});
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-hu.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-hu.js
new file mode 100644 (file)
index 0000000..ee102ac
--- /dev/null
@@ -0,0 +1,19 @@
+/* Hungarian initialisation for the jQuery UI date picker plugin. */
+/* Written by Istvan Karaszi (jquerycalendar@spam.raszi.hu). */
+jQuery(function($){
+       $.datepicker.regional['hu'] = {
+               closeText: 'bezárás',
+               prevText: '&laquo;&nbsp;vissza',
+               nextText: 'előre&nbsp;&raquo;',
+               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ámap', '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'],
+               dateFormat: 'yy-mm-dd', firstDay: 1,
+               isRTL: false};
+       $.datepicker.setDefaults($.datepicker.regional['hu']);
+});
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-hy.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-hy.js
new file mode 100644 (file)
index 0000000..1ffbeaa
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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: ['կիր','երկ','երք','չրք','հնգ','ուրբ','շբթ'],
+               dateFormat: 'dd.mm.yy', firstDay: 1,
+               isRTL: false};
+       $.datepicker.setDefaults($.datepicker.regional['hy']);
+});
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-id.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-id.js
new file mode 100644 (file)
index 0000000..e5246c8
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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'],
+               dateFormat: 'dd/mm/yy', firstDay: 0,
+               isRTL: false};
+       $.datepicker.setDefaults($.datepicker.regional['id']);
+});
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-is.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-is.js
new file mode 100644 (file)
index 0000000..68c1a07
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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'],
+               dateFormat: 'dd/mm/yy', firstDay: 0,
+               isRTL: false};
+       $.datepicker.setDefaults($.datepicker.regional['is']);
+});
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-it.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-it.js
new file mode 100644 (file)
index 0000000..f3e691e
--- /dev/null
@@ -0,0 +1,19 @@
+/* Italian initialisation for the jQuery UI date picker plugin. */
+/* Written by Apaella (apaella@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','Gio','Ve','Sa'],
+               dateFormat: 'dd/mm/yy', firstDay: 1,
+               isRTL: false};
+       $.datepicker.setDefaults($.datepicker.regional['it']);
+});
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-ja.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-ja.js
new file mode 100644 (file)
index 0000000..a6a5f45
--- /dev/null
@@ -0,0 +1,20 @@
+/* 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: ['日','月','火','水','木','金','土'],
+               dateFormat: 'yy/mm/dd', firstDay: 0,
+               isRTL: false,
+               showMonthAfterYear: true};
+       $.datepicker.setDefaults($.datepicker.regional['ja']);
+});
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-ko.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-ko.js
new file mode 100644 (file)
index 0000000..53ede91
--- /dev/null
@@ -0,0 +1,19 @@
+/* Korean initialisation for the jQuery calendar extension. */
+/* Written by DaeKwon Kang (ncrash.dk@gmail.com). */
+jQuery(function($){
+       $.datepicker.regional['ko'] = {
+               closeText: '닫기',
+               prevText: '이전달',
+               nextText: '다음달',
+               currentText: '오늘',
+               monthNames: ['1월(JAN)','2월(FEB)','3월(MAR)','4월(APR)','5월(MAY)','6월(JUN)',
+               '7월(JUL)','8월(AUG)','9월(SEP)','10월(OCT)','11월(NOV)','12월(DEC)'],
+               monthNamesShort: ['1월(JAN)','2월(FEB)','3월(MAR)','4월(APR)','5월(MAY)','6월(JUN)',
+               '7월(JUL)','8월(AUG)','9월(SEP)','10월(OCT)','11월(NOV)','12월(DEC)'],
+               dayNames: ['일','월','화','수','목','금','토'],
+               dayNamesShort: ['일','월','화','수','목','금','토'],
+               dayNamesMin: ['일','월','화','수','목','금','토'],
+               dateFormat: 'yy-mm-dd', firstDay: 0,
+               isRTL: false};
+       $.datepicker.setDefaults($.datepicker.regional['ko']);
+});
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-lt.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-lt.js
new file mode 100644 (file)
index 0000000..a8a6aa1
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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'],
+               dateFormat: 'yy-mm-dd', firstDay: 1,
+               isRTL: false};
+       $.datepicker.setDefaults($.datepicker.regional['lt']);
+});
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-lv.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-lv.js
new file mode 100644 (file)
index 0000000..12c32f8
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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'],
+               dateFormat: 'dd-mm-yy', firstDay: 1,
+               isRTL: false};
+       $.datepicker.setDefaults($.datepicker.regional['lv']);
+});
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-ms.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-ms.js
new file mode 100644 (file)
index 0000000..fa25305
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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'],
+               dateFormat: 'dd/mm/yy', firstDay: 0,
+               isRTL: false};
+       $.datepicker.setDefaults($.datepicker.regional['ms']);
+});
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-nl.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-nl.js
new file mode 100644 (file)
index 0000000..938dc5e
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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', 'maa', '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'],
+               dateFormat: 'dd/mm/yy', firstDay: 1,
+               isRTL: false};
+       $.datepicker.setDefaults($.datepicker.regional.nl);
+});
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-no.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-no.js
new file mode 100644 (file)
index 0000000..efe5b0d
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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ø'],
+               dateFormat: 'yy-mm-dd', firstDay: 0,
+               isRTL: false};
+       $.datepicker.setDefaults($.datepicker.regional['no']);
+});
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-pl.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-pl.js
new file mode 100644 (file)
index 0000000..0ce38be
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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','Poniedzialek','Wtorek','Środa','Czwartek','Piątek','Sobota'],
+               dayNamesShort: ['Nie','Pn','Wt','Śr','Czw','Pt','So'],
+               dayNamesMin: ['N','Pn','Wt','Śr','Cz','Pt','So'],
+               dateFormat: 'yy-mm-dd', firstDay: 1,
+               isRTL: false};
+       $.datepicker.setDefaults($.datepicker.regional['pl']);
+});
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-pt-BR.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-pt-BR.js
new file mode 100644 (file)
index 0000000..e3ac652
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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','Sabado'],
+               dayNamesShort: ['Dom','Seg','Ter','Qua','Qui','Sex','Sab'],
+               dayNamesMin: ['Dom','Seg','Ter','Qua','Qui','Sex','Sab'],
+               dateFormat: 'dd/mm/yy', firstDay: 0,
+               isRTL: false};
+       $.datepicker.setDefaults($.datepicker.regional['pt-BR']);
+});
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-ro.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-ro.js
new file mode 100644 (file)
index 0000000..ec4033c
--- /dev/null
@@ -0,0 +1,22 @@
+/* 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â'],
+               dateFormat: 'dd MM yy', firstDay: 1,
+               isRTL: false};
+       $.datepicker.setDefaults($.datepicker.regional['ro']);
+});
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-ru.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-ru.js
new file mode 100644 (file)
index 0000000..62752c7
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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: ['Вс','Пн','Вт','Ср','Чт','Пт','Сб'],
+               dateFormat: 'dd.mm.yy', firstDay: 1,
+               isRTL: false};
+       $.datepicker.setDefaults($.datepicker.regional['ru']);
+});
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-sk.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-sk.js
new file mode 100644 (file)
index 0000000..a023ffa
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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: ['Nedel\'a','Pondelok','Utorok','Streda','Štvrtok','Piatok','Sobota'],
+               dayNamesShort: ['Ned','Pon','Uto','Str','Štv','Pia','Sob'],
+               dayNamesMin: ['Ne','Po','Ut','St','Št','Pia','So'],
+               dateFormat: 'dd.mm.yy', firstDay: 0,
+               isRTL: false};
+       $.datepicker.setDefaults($.datepicker.regional['sk']);
+});
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-sl.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-sl.js
new file mode 100644 (file)
index 0000000..480a4d8
--- /dev/null
@@ -0,0 +1,20 @@
+/* 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'],
+               dateFormat: 'dd.mm.yy', firstDay: 1,
+               isRTL: false};
+       $.datepicker.setDefaults($.datepicker.regional['sl']);
+});
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-sq.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-sq.js
new file mode 100644 (file)
index 0000000..ac67e68
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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'],
+               dateFormat: 'dd.mm.yy', firstDay: 1,
+               isRTL: false};
+       $.datepicker.setDefaults($.datepicker.regional['sq']);
+});
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-sr-SR.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-sr-SR.js
new file mode 100644 (file)
index 0000000..059fc38
--- /dev/null
@@ -0,0 +1,19 @@
+/* Serbian i18n for the jQuery UI date picker plugin. */\r
+/* Written by Dejan Dimić. */\r
+jQuery(function($){\r
+       $.datepicker.regional['sr-SR'] = {\r
+               closeText: 'Zatvori',\r
+               prevText: '&#x3c;',\r
+               nextText: '&#x3e;',\r
+               currentText: 'Danas',\r
+               monthNames: ['Januar','Februar','Mart','April','Maj','Jun',\r
+               'Jul','Avgust','Septembar','Oktobar','Novembar','Decembar'],\r
+               monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',\r
+               'Jul','Avg','Sep','Okt','Nov','Dec'],\r
+               dayNames: ['Nedelja','Ponedeljak','Utorak','Sreda','Četvrtak','Petak','Subota'],\r
+               dayNamesShort: ['Ned','Pon','Uto','Sre','Čet','Pet','Sub'],\r
+               dayNamesMin: ['Ne','Po','Ut','Sr','Če','Pe','Su'],\r
+               dateFormat: 'dd/mm/yy', firstDay: 1,\r
+               isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional['sr-SR']);\r
+});
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-sr.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-sr.js
new file mode 100644 (file)
index 0000000..179458b
--- /dev/null
@@ -0,0 +1,19 @@
+/* Serbian i18n for the jQuery UI date picker plugin. */\r
+/* Written by Dejan Dimić. */\r
+jQuery(function($){\r
+       $.datepicker.regional['sr'] = {\r
+               closeText: 'Затвори',\r
+               prevText: '&#x3c;',\r
+               nextText: '&#x3e;',\r
+               currentText: 'Данас',\r
+               monthNames: ['Јануар','Фебруар','Март','Април','Мај','Јун',\r
+               'Јул','Август','Септембар','Октобар','Новембар','Децембар'],\r
+               monthNamesShort: ['Јан','Феб','Мар','Апр','Мај','Јун',\r
+               'Јул','Авг','Сеп','Окт','Нов','Дец'],\r
+               dayNames: ['Недеља','Понедељак','Уторак','Среда','Четвртак','Петак','Субота'],\r
+               dayNamesShort: ['Нед','Пон','Уто','Сре','Чет','Пет','Суб'],\r
+               dayNamesMin: ['Не','По','Ут','Ср','Че','Пе','Су'],\r
+               dateFormat: 'dd/mm/yy', firstDay: 1,\r
+               isRTL: false};\r
+       $.datepicker.setDefaults($.datepicker.regional['sr']);\r
+});
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-sv.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-sv.js
new file mode 100644 (file)
index 0000000..47c4b24
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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ö'],
+        dateFormat: 'yy-mm-dd', firstDay: 1,
+               isRTL: false};
+    $.datepicker.setDefaults($.datepicker.regional['sv']);
+});
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-th.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-th.js
new file mode 100644 (file)
index 0000000..3c2a02b
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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: ['อา.','จ.','อ.','พ.','พฤ.','ศ.','ส.'],
+               dateFormat: 'dd/mm/yy', firstDay: 0,
+               isRTL: false};
+       $.datepicker.setDefaults($.datepicker.regional['th']);
+});
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-tr.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-tr.js
new file mode 100644 (file)
index 0000000..5817b2a
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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'],
+               dateFormat: 'dd.mm.yy', firstDay: 1,
+               isRTL: false};
+       $.datepicker.setDefaults($.datepicker.regional['tr']);
+});
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-uk.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-uk.js
new file mode 100644 (file)
index 0000000..1043d7c
--- /dev/null
@@ -0,0 +1,25 @@
+/* Ukrainian (UTF-8) initialisation for the jQuery UI date picker plugin. */
+/* Written by Maxim Drogobitskiy (maxdao@gmail.com). */
+jQuery(function($){
+       $.datepicker.regional['uk'] = {
+               clearText: 'Очистити', clearStatus: '',
+               closeText: 'Закрити', closeStatus: '',
+               prevText: '&#x3c;',  prevStatus: '',
+               prevBigText: '&#x3c;&#x3c;', prevBigStatus: '',
+               nextText: '&#x3e;', nextStatus: '',
+               nextBigText: '&#x3e;&#x3e;', nextBigStatus: '',
+               currentText: 'Сьогодні', currentStatus: '',
+               monthNames: ['Січень','Лютий','Березень','Квітень','Травень','Червень',
+               'Липень','Серпень','Вересень','Жовтень','Листопад','Грудень'],
+               monthNamesShort: ['Січ','Лют','Бер','Кві','Тра','Чер',
+               'Лип','Сер','Вер','Жов','Лис','Гру'],
+               monthStatus: '', yearStatus: '',
+               weekHeader: 'Не', weekStatus: '',
+               dayNames: ['неділя','понеділок','вівторок','середа','четвер','п’ятниця','субота'],
+               dayNamesShort: ['нед','пнд','вів','срд','чтв','птн','сбт'],
+               dayNamesMin: ['Нд','Пн','Вт','Ср','Чт','Пт','Сб'],
+               dayStatus: 'DD', dateStatus: 'D, M d',
+               dateFormat: 'dd/mm/yy', firstDay: 1,
+               initStatus: '', isRTL: false};
+       $.datepicker.setDefaults($.datepicker.regional['uk']);
+});
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-zh-CN.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-zh-CN.js
new file mode 100644 (file)
index 0000000..e3a69dc
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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: ['日','一','二','三','四','五','六'],
+               dateFormat: 'yy-mm-dd', firstDay: 1,
+               isRTL: false};
+       $.datepicker.setDefaults($.datepicker.regional['zh-CN']);
+});
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-zh-TW.js b/js2/mwEmbed/jquery/jquery.ui/ui/i18n/ui.datepicker-zh-TW.js
new file mode 100644 (file)
index 0000000..9cb49b7
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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: ['日','一','二','三','四','五','六'],
+               dateFormat: 'yy/mm/dd', firstDay: 1,
+               isRTL: false};
+       $.datepicker.setDefaults($.datepicker.regional['zh-TW']);
+});
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/jquery-ui-1.7.1.custom.js b/js2/mwEmbed/jquery/jquery.ui/ui/jquery-ui-1.7.1.custom.js
new file mode 100644 (file)
index 0000000..eac07e6
--- /dev/null
@@ -0,0 +1,9074 @@
+/*
+ * jQuery UI 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI
+ */
+;jQuery.ui || (function($) {
+
+var _remove = $.fn.remove,
+       isFF2 = $.browser.mozilla && (parseFloat($.browser.version) < 1.9);
+
+//Helper functions and ui object
+$.ui = {
+       version: "1.7.1",
+
+       // $.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);
+                               }
+                       }
+               }
+       },
+
+       contains: function(a, b) {
+               return document.compareDocumentPosition
+                       ? a.compareDocumentPosition(b) & 16
+                       : a !== b && a.contains(b);
+       },
+
+       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;
+       },
+
+       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);
+       },
+
+       keyCode: {
+               BACKSPACE: 8,
+               CAPS_LOCK: 20,
+               COMMA: 188,
+               CONTROL: 17,
+               DELETE: 46,
+               DOWN: 40,
+               END: 35,
+               ENTER: 13,
+               ESCAPE: 27,
+               HOME: 36,
+               INSERT: 45,
+               LEFT: 37,
+               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
+       }
+};
+
+// WAI-ARIA normalization
+if (isFF2) {
+       var attr = $.attr,
+               removeAttr = $.fn.removeAttr,
+               ariaNS = "http://www.w3.org/2005/07/aaa",
+               ariaState = /^aria-/,
+               ariaRole = /^wairole:/;
+
+       $.attr = function(elem, name, value) {
+               var set = value !== undefined;
+
+               return (name == 'role'
+                       ? (set
+                               ? attr.call(this, elem, name, "wairole:" + value)
+                               : (attr.apply(this, arguments) || "").replace(ariaRole, ""))
+                       : (ariaState.test(name)
+                               ? (set
+                                       ? elem.setAttributeNS(ariaNS,
+                                               name.replace(ariaState, "aaa:"), value)
+                                       : attr.call(this, elem, name.replace(ariaState, "aaa:")))
+                               : attr.apply(this, arguments)));
+       };
+
+       $.fn.removeAttr = function(name) {
+               return (ariaState.test(name)
+                       ? this.each(function() {
+                               this.removeAttributeNS(ariaNS, name.replace(ariaState, ""));
+                       }) : removeAttr.call(this, name));
+       };
+}
+
+//jQuery plugins
+$.fn.extend({
+       remove: function() {
+               // Safari has a native remove event which actually removes DOM elements,
+               // so we have to use triggerHandler instead of trigger (#3037).
+               $("*", this).add(this).each(function() {
+                       $(this).triggerHandler("remove");
+               });
+               return _remove.apply(this, arguments );
+       },
+
+       enableSelection: function() {
+               return this
+                       .attr('unselectable', 'off')
+                       .css('MozUserSelect', '')
+                       .unbind('selectstart.ui');
+       },
+
+       disableSelection: function() {
+               return this
+                       .attr('unselectable', 'on')
+                       .css('MozUserSelect', 'none')
+                       .bind('selectstart.ui', function() { return false; });
+       },
+
+       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;
+       }
+});
+
+
+//Additional selectors
+$.extend($.expr[':'], {
+       data: function(elem, i, match) {
+               return !!$.data(elem, match[3]);
+       },
+
+       focusable: function(element) {
+               var nodeName = element.nodeName.toLowerCase(),
+                       tabIndex = $.attr(element, 'tabindex');
+               return (/input|select|textarea|button|object/.test(nodeName)
+                       ? !element.disabled
+                       : 'a' == nodeName || 'area' == nodeName
+                               ? element.href || !isNaN(tabIndex)
+                               : !isNaN(tabIndex))
+                       // the element and all of its ancestors must be visible
+                       // the browser may report that the area is hidden
+                       && !$(element)['area' == nodeName ? 'parents' : 'closest'](':hidden').length;
+       },
+
+       tabbable: function(element) {
+               var tabIndex = $.attr(element, 'tabindex');
+               return (isNaN(tabIndex) || tabIndex >= 0) && $(element).is(':focusable');
+       }
+});
+
+
+// $.widget is a factory to create jQuery plugins
+// taking some boilerplate code out of the plugin code
+function getter(namespace, plugin, method, args) {
+       function getMethods(type) {
+               var methods = $[namespace][plugin][type] || [];
+               return (typeof methods == 'string' ? methods.split(/,?\s+/) : methods);
+       }
+
+       var methods = getMethods('getter');
+       if (args.length == 1 && typeof args[0] == 'string') {
+               methods = methods.concat(getMethods('getterSetter'));
+       }
+       return ($.inArray(method, methods) != -1);
+}
+
+$.widget = function(name, prototype) {
+       var namespace = name.split(".")[0];
+       name = name.split(".")[1];
+
+       // create plugin method
+       $.fn[name] = function(options) {
+               var isMethodCall = (typeof options == 'string'),
+                       args = Array.prototype.slice.call(arguments, 1);
+
+               // prevent calls to internal methods
+               if (isMethodCall && options.substring(0, 1) == '_') {
+                       return this;
+               }
+
+               // handle getter methods
+               if (isMethodCall && getter(namespace, name, options, args)) {
+                       var instance = $.data(this[0], name);
+                       return (instance ? instance[options].apply(instance, args)
+                               : undefined);
+               }
+
+               // handle initialization and non-getter methods
+               return this.each(function() {
+                       var instance = $.data(this, name);
+
+                       // constructor
+                       (!instance && !isMethodCall &&
+                               $.data(this, name, new $[namespace][name](this, options))._init());
+
+                       // method call
+                       (instance && isMethodCall && $.isFunction(instance[options]) &&
+                               instance[options].apply(instance, args));
+               });
+       };
+
+       // create widget constructor
+       $[namespace] = $[namespace] || {};
+       $[namespace][name] = function(element, options) {
+               var self = this;
+
+               this.namespace = namespace;
+               this.widgetName = name;
+               this.widgetEventPrefix = $[namespace][name].eventPrefix || name;
+               this.widgetBaseClass = namespace + '-' + name;
+
+               this.options = $.extend({},
+                       $.widget.defaults,
+                       $[namespace][name].defaults,
+                       $.metadata && $.metadata.get(element)[name],
+                       options);
+
+               this.element = $(element)
+                       .bind('setData.' + name, function(event, key, value) {
+                               if (event.target == element) {
+                                       return self._setData(key, value);
+                               }
+                       })
+                       .bind('getData.' + name, function(event, key) {
+                               if (event.target == element) {
+                                       return self._getData(key);
+                               }
+                       })
+                       .bind('remove', function() {
+                               return self.destroy();
+                       });
+       };
+
+       // add widget prototype
+       $[namespace][name].prototype = $.extend({}, $.widget.prototype, prototype);
+
+       // TODO: merge getter and getterSetter properties from widget prototype
+       // and plugin prototype
+       $[namespace][name].getterSetter = 'option';
+};
+
+$.widget.prototype = {
+       _init: function() {},
+       destroy: function() {
+               this.element.removeData(this.widgetName)
+                       .removeClass(this.widgetBaseClass + '-disabled' + ' ' + this.namespace + '-state-disabled')
+                       .removeAttr('aria-disabled');
+       },
+
+       option: function(key, value) {
+               var options = key,
+                       self = this;
+
+               if (typeof key == "string") {
+                       if (value === undefined) {
+                               return this._getData(key);
+                       }
+                       options = {};
+                       options[key] = value;
+               }
+
+               $.each(options, function(key, value) {
+                       self._setData(key, value);
+               });
+       },
+       _getData: function(key) {
+               return this.options[key];
+       },
+       _setData: function(key, value) {
+               this.options[key] = value;
+
+               if (key == 'disabled') {
+                       this.element
+                               [value ? 'addClass' : 'removeClass'](
+                                       this.widgetBaseClass + '-disabled' + ' ' +
+                                       this.namespace + '-state-disabled')
+                               .attr("aria-disabled", value);
+               }
+       },
+
+       enable: function() {
+               this._setData('disabled', false);
+       },
+       disable: function() {
+               this._setData('disabled', true);
+       },
+
+       _trigger: function(type, event, data) {
+               var callback = this.options[type],
+                       eventName = (type == this.widgetEventPrefix
+                               ? type : this.widgetEventPrefix + type);
+
+               event = $.Event(event);
+               event.type = eventName;
+
+               // copy original event properties over to the new event
+               // this would happen if we could call $.event.fix instead of $.Event
+               // but we don't have a way to force an event to be fixed multiple times
+               if (event.originalEvent) {
+                       for (var i = $.event.props.length, prop; i;) {
+                               prop = $.event.props[--i];
+                               event[prop] = event.originalEvent[prop];
+                       }
+               }
+
+               this.element.trigger(event, data);
+
+               return !($.isFunction(callback) && callback.call(this.element[0], event, data) === false
+                       || event.isDefaultPrevented());
+       }
+};
+
+$.widget.defaults = {
+       disabled: false
+};
+
+
+/** Mouse Interaction Plugin **/
+
+$.ui.mouse = {
+       _mouseInit: function() {
+               var self = this;
+
+               this.element
+                       .bind('mousedown.'+this.widgetName, function(event) {
+                               return self._mouseDown(event);
+                       })
+                       .bind('click.'+this.widgetName, function(event) {
+                               if(self._preventClickEvent) {
+                                       self._preventClickEvent = false;
+                                       event.stopImmediatePropagation();
+                                       return false;
+                               }
+                       });
+
+               // Prevent text selection in IE
+               if ($.browser.msie) {
+                       this._mouseUnselectable = this.element.attr('unselectable');
+                       this.element.attr('unselectable', 'on');
+               }
+
+               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);
+
+               // Restore text selection in IE
+               ($.browser.msie
+                       && this.element.attr('unselectable', this._mouseUnselectable));
+       },
+
+       _mouseDown: function(event) {
+               // don't let more than one widget handle mouseStart
+               // TODO: figure out why we have to use originalEvent
+               event.originalEvent = event.originalEvent || {};
+               if (event.originalEvent.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),
+                       elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(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;
+                       }
+               }
+
+               // 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);
+
+               // preventDefault() is used to prevent the selection of text here -
+               // however, in Safari, this causes select boxes not to be selectable
+               // anymore, so this fix is needed
+               ($.browser.safari || event.preventDefault());
+
+               event.originalEvent.mouseHandled = true;
+               return true;
+       },
+
+       _mouseMove: function(event) {
+               // IE mouseup check - mouseup happened when mouse was out of window
+               if ($.browser.msie && !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;
+                       this._preventClickEvent = (event.target == this._mouseDownEvent.target);
+                       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; }
+};
+
+$.ui.mouse.defaults = {
+       cancel: null,
+       distance: 1,
+       delay: 0
+};
+
+})(jQuery);
+/*
+ * jQuery UI Draggable 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Draggables
+ *
+ * Depends:
+ *     ui.core.js
+ */
+(function($) {
+
+$.widget("ui.draggable", $.extend({}, $.ui.mouse, {
+
+       _init: 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();
+       },
+
+       _mouseCapture: function(event) {
+
+               var o = this.options;
+
+               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;
+
+               return true;
+
+       },
+
+       _mouseStart: function(event) {
+
+               var o = this.options;
+
+               //Create and append the visible helper
+               this.helper = this._createHelper(event);
+
+               //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.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._generatePosition(event);
+               this.originalPageX = event.pageX;
+               this.originalPageY = event.pageY;
+
+               //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
+               if(o.cursorAt)
+                       this._adjustOffsetFromHelper(o.cursorAt);
+
+               //Set a containment if given in the options
+               if(o.containment)
+                       this._setContainment();
+
+               //Call plugins and callbacks
+               this._trigger("start", event);
+
+               //Recache the helper size
+               this._cacheHelperProportions();
+
+               //Prepare the droppable offsets
+               if ($.ui.ddmanager && !o.dropBehaviour)
+                       $.ui.ddmanager.prepareOffsets(this, event);
+
+               this.helper.addClass("ui-draggable-dragging");
+               this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
+               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();
+                       this._trigger('drag', event, ui);
+                       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((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() {
+                               self._trigger("stop", event);
+                               self._clear();
+                       });
+               } else {
+                       this._trigger("stop", event);
+                       this._clear();
+               }
+
+               return false;
+       },
+
+       _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() : 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(obj.left != undefined) this.offset.click.left = obj.left + this.margins.left;
+               if(obj.right != undefined) this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
+               if(obj.top != undefined) this.offset.click.top = obj.top + this.margins.top;
+               if(obj.bottom != undefined) 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)
+               };
+       },
+
+       _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) && o.containment.constructor != Array) {
+                       var ce = $(o.containment)[0]; if(!ce) return;
+                       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
+                       ];
+               } 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 && 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() ))
+                       )
+               };
+
+       },
+
+       _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,
+                       absolutePosition: this.positionAbs, //deprecated
+                       offset: this.positionAbs
+               };
+       }
+
+}));
+
+$.extend($.ui.draggable, {
+       version: "1.7.1",
+       eventPrefix: "drag",
+       defaults: {
+               addClasses: true,
+               appendTo: "parent",
+               axis: false,
+               cancel: ":input,option",
+               connectToSortable: false,
+               containment: false,
+               cursor: "auto",
+               cursorAt: false,
+               delay: 0,
+               distance: 1,
+               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
+       }
+});
+
+$.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._refreshItems();       //Do a one-time refresh at start to refresh the containerCache
+                               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().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", "iframeFix", {
+       start: function(event, ui) {
+               var o = $(this).data('draggable').options;
+               $(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");
+               });
+       },
+       stop: function(event, ui) {
+               $("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers
+       }
+});
+
+$.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.group)).sort(function(a,b) {
+                       return (parseInt($(a).css("zIndex"),10) || o.stack.min) - (parseInt($(b).css("zIndex"),10) || o.stack.min);
+               });
+
+               $(group).each(function(i) {
+                       this.style.zIndex = o.stack.min + i;
+               });
+
+               this[0].style.zIndex = o.stack.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);
+/*
+ * jQuery UI Droppable 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Droppables
+ *
+ * Depends:
+ *     ui.core.js
+ *     ui.draggable.js
+ */
+(function($) {
+
+$.widget("ui.droppable", {
+
+       _init: function() {
+
+               var o = this.options, accept = o.accept;
+               this.isover = 0; this.isout = 1;
+
+               this.options.accept = this.options.accept && $.isFunction(this.options.accept) ? this.options.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[this.options.scope] = $.ui.ddmanager.droppables[this.options.scope] || [];
+               $.ui.ddmanager.droppables[this.options.scope].push(this);
+
+               (this.options.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");
+       },
+
+       _setData: function(key, value) {
+
+               if(key == 'accept') {
+                       this.options.accept = value && $.isFunction(value) ? value : function(d) {
+                               return d.is(value);
+                       };
+               } else {
+                       $.widget.prototype._setData.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.options.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.options.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 && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)) {
+                               childrenIntersection = true; return false;
+                       }
+               });
+               if(childrenIntersection) return false;
+
+               if(this.options.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,
+                       absolutePosition: c.positionAbs, //deprecated
+                       offset: c.positionAbs
+               };
+       }
+
+});
+
+$.extend($.ui.droppable, {
+       version: "1.7.1",
+       eventPrefix: 'drop',
+       defaults: {
+               accept: '*',
+               activeClass: false,
+               addClasses: true,
+               greedy: false,
+               hoverClass: false,
+               scope: 'default',
+               tolerance: 'intersect'
+       }
+});
+
+$.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].options.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
+
+                       m[i].offset = m[i].element.offset();
+                       m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
+
+                       if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
+
+               }
+
+       },
+       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);
+
+                       if (!this.options.disabled && this.visible && this.options.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
+                               this.isout = 1; this.isover = 0;
+                               this._deactivate.call(this, event);
+                       }
+
+               });
+               return dropped;
+
+       },
+       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) {
+                               var parent = this.element.parents(':data(droppable):eq(0)');
+                               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);
+                       }
+               });
+
+       }
+};
+
+})(jQuery);
+/*
+ * jQuery UI Resizable 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Resizables
+ *
+ * Depends:
+ *     ui.core.js
+ */
+(function($) {
+
+$.widget("ui.resizable", $.extend({}, $.ui.mouse, {
+
+       _init: 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)) {
+
+                       //Opera fix for relative positioning
+                       if (/relative/.test(this.element.css('position')) && $.browser.opera)
+                               this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
+
+                       //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>');
+
+                               // increase zIndex of sw, se, ne, nw axis
+                               //TODO : this modifies original option
+                               if(/sw|se|ne|nw/.test(handle)) 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() {
+                                       $(this).removeClass("ui-resizable-autohide");
+                                       self._handles.show();
+                               },
+                               function(){
+                                       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.parent().append(
+                               this.originalElement.css({
+                                       position: wrapper.css('position'),
+                                       width: wrapper.outerWidth(),
+                                       height: wrapper.outerHeight(),
+                                       top: wrapper.css('top'),
+                                       left: wrapper.css('left')
+                               })
+                       ).end().remove();
+               }
+
+               this.originalElement.css('resize', this.originalResizeStyle);
+               _destroy(this.originalElement);
+
+       },
+
+       _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 });
+               }
+
+               //Opera fixing relative position
+               if ($.browser.opera && (/relative/).test(el.css('position')))
+                       el.css({ position: 'relative', top: 'auto', left: 'auto' });
+
+               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;
+
+               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.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;
+
+                       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;
+
+       },
+
+       _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 (data.height) data.width = (csize.height * this.aspectRatio);
+               else if (data.width) data.height = (csize.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.options, 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.7.1",
+       eventPrefix: "resize",
+       defaults: {
+               alsoResize: false,
+               animate: false,
+               animateDuration: "slow",
+               animateEasing: "swing",
+               aspectRatio: false,
+               autoHide: false,
+               cancel: ":input,option",
+               containment: false,
+               delay: 0,
+               distance: 1,
+               ghost: false,
+               grid: false,
+               handles: "e,s,se",
+               helper: false,
+               maxHeight: null,
+               maxWidth: null,
+               minHeight: 10,
+               minWidth: 10,
+               zIndex: 1000
+       }
+});
+
+/*
+ * Resizable Extensions
+ */
+
+$.ui.plugin.add("resizable", "alsoResize", {
+
+       start: function(event, ui) {
+
+               var self = $(this).data("resizable"), o = self.options;
+
+               _store = function(exp) {
+                       $(exp).each(function() {
+                               $(this).data("resizable-alsoresize", {
+                                       width: parseInt($(this).width(), 10), height: parseInt($(this).height(), 10),
+                                       left: parseInt($(this).css('left'), 10), top: parseInt($(this).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, c) { _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 : ['width', 'height', 'top', 'left'];
+
+                               $.each(css || ['width', 'height', 'top', 'left'], function(i, prop) {
+                                       var sum = (start[prop]||0) + (delta[prop]||0);
+                                       if (sum && sum >= 0)
+                                               style[prop] = sum || null;
+                               });
+
+                               //Opera fixing relative position
+                               if (/relative/.test(el.css('position')) && $.browser.opera) {
+                                       self._revertToRelativePosition = true;
+                                       el.css({ position: 'absolute', top: 'auto', left: 'auto' });
+                               }
+
+                               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){
+               var self = $(this).data("resizable");
+
+               //Opera fixing relative position
+               if (self._revertToRelativePosition && $.browser.opera) {
+                       self._revertToRelativePosition = false;
+                       el.css({ position: 'relative' });
+               }
+
+               $(this).removeData("resizable-alsoresize-start");
+       }
+});
+
+$.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 / o.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 * o.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);
+/*
+ * jQuery UI Selectable 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Selectables
+ *
+ * Depends:
+ *     ui.core.js
+ */
+(function($) {
+
+$.widget("ui.selectable", $.extend({}, $.ui.mouse, {
+
+       _init: 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.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 = $(document.createElement('div'))
+                       .css({border:'1px dotted black'})
+                       .addClass("ui-selectable-helper");
+       },
+
+       destroy: function() {
+               this.element
+                       .removeClass("ui-selectable ui-selectable-disabled")
+                       .removeData("selectable")
+                       .unbind(".selectable");
+               this._mouseDestroy();
+       },
+
+       _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({
+                       "z-index": 100,
+                       "position": "absolute",
+                       "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) {
+                               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) {
+                               selectee.$element.removeClass("ui-unselecting").addClass('ui-selecting');
+                               selectee.unselecting = false;
+                               selectee.selecting = true;
+                               selectee.selected = true;
+                               // selectable SELECTING callback
+                               self._trigger("selecting", event, {
+                                       selecting: 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 && 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 && !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.7.1",
+       defaults: {
+               appendTo: 'body',
+               autoRefresh: true,
+               cancel: ":input,option",
+               delay: 0,
+               distance: 0,
+               filter: '*',
+               tolerance: 'touch'
+       }
+});
+
+})(jQuery);
+/*
+ * jQuery UI Sortable 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Sortables
+ *
+ * Depends:
+ *     ui.core.js
+ */
+(function($) {
+
+$.widget("ui.sortable", $.extend({}, $.ui.mouse, {
+       _init: function() {
+
+               var o = this.options;
+               this.containerCache = {};
+               this.element.addClass("ui-sortable");
+
+               //Get the items
+               this.refresh();
+
+               //Let's determine if the items are floating
+               this.floating = this.items.length ? (/left|right/).test(this.items[0].item.css('float')) : false;
+
+               //Let's determine the parent's offset
+               this.offset = this.element.offset();
+
+               //Initialize mouse events for interaction
+               this._mouseInit();
+
+       },
+
+       destroy: function() {
+               this.element
+                       .removeClass("ui-sortable ui-sortable-disabled")
+                       .removeData("sortable")
+                       .unbind(".sortable");
+               this._mouseDestroy();
+
+               for ( var i = this.items.length - 1; i >= 0; i-- )
+                       this.items[i].item.removeData("sortable-item");
+       },
+
+       _mouseCapture: function(event, overrideHandle) {
+
+               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, 'sortable-item') == self) {
+                               currentItem = $(this);
+                               return false;
+                       }
+               });
+               if($.data(event.target, 'sortable-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
+               };
+
+               // 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");
+
+               $.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._generatePosition(event);
+               this.originalPageX = event.pageX;
+               this.originalPageY = event.pageY;
+
+               //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
+               if(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;
+
+                       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)
+                       ) {
+
+                               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();
+
+                       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;
+                               }
+                       }
+
+               }
+
+               //$(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 true;
+
+       },
+
+       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]));
+               });
+
+               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 = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
+                       isOverElementWidth = $.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();
+       },
+
+       _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], 'sortable');
+                                       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"), 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"), 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(sortable-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) {
+                       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], 'sortable');
+                                       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('sortable-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();
+                       };
+               }
+
+       },
+
+       _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) {
+               for (var i = this.containers.length - 1; i >= 0; i--){
+
+                       if(this._intersectsWith(this.containers[i].containerCache)) {
+                               if(!this.containers[i].containerCache.over) {
+
+                                       if(this.currentContainer != this.containers[i]) {
+
+                                               //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[i].floating ? 'left' : 'top'];
+                                               for (var j = this.items.length - 1; j >= 0; j--) {
+                                                       if(!$.ui.contains(this.containers[i].element[0], this.items[j].item[0])) continue;
+                                                       var cur = this.items[j][this.containers[i].floating ? 'left' : 'top'];
+                                                       if(Math.abs(cur - base) < dist) {
+                                                               dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
+                                                       }
+                                               }
+
+                                               if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled
+                                                       continue;
+
+                                               this.currentContainer = this.containers[i];
+                                               itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[i].element, true);
+                                               this._trigger("change", event, this._uiHash());
+                                               this.containers[i]._trigger("change", event, this._uiHash(this));
+
+                                               //Update the placeholder
+                                               this.options.placeholder.update(this.currentContainer, this.placeholder);
+
+                                       }
+
+                                       this.containers[i]._trigger("over", event, this._uiHash(this));
+                                       this.containers[i].containerCache.over = 1;
+                               }
+                       } else {
+                               if(this.containers[i].containerCache.over) {
+                                       this.containers[i]._trigger("out", event, this._uiHash(this));
+                                       this.containers[i].containerCache.over = 0;
+                               }
+                       }
+
+               };
+       },
+
+       _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(obj.left != undefined) this.offset.click.left = obj.left + this.margins.left;
+               if(obj.right != undefined) this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
+               if(obj.top != undefined) this.offset.click.top = obj.top + this.margins.top;
+               if(obj.bottom != undefined) 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[0].parentNode) 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
+               if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
+                       if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
+                       for (var i = this.containers.length - 1; i >= 0; i--){
+                               if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
+                                       delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
+                                       delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.containers[i]));
+                               }
+                       };
+               };
+
+               //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 cursor
+               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());
+                       }
+                       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,
+                       absolutePosition: self.positionAbs, //deprecated
+                       offset: self.positionAbs,
+                       item: self.currentItem,
+                       sender: inst ? inst.element : null
+               };
+       }
+
+}));
+
+$.extend($.ui.sortable, {
+       getter: "serialize toArray",
+       version: "1.7.1",
+       eventPrefix: "sort",
+       defaults: {
+               appendTo: "parent",
+               axis: false,
+               cancel: ":input,option",
+               connectWith: false,
+               containment: false,
+               cursor: 'auto',
+               cursorAt: false,
+               delay: 0,
+               distance: 1,
+               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
+       }
+});
+
+})(jQuery);
+/*
+ * jQuery UI Accordion 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Accordion
+ *
+ * Depends:
+ *     ui.core.js
+ */
+(function($) {
+
+$.widget("ui.accordion", {
+
+       _init: function() {
+
+               var o = this.options, self = this;
+               this.running = 0;
+
+               // if the user set the alwaysOpen option on init
+               // then we need to set the collapsible option
+               // if they set both on init, collapsible will take priority
+               if (o.collapsible == $.ui.accordion.defaults.collapsible &&
+                       o.alwaysOpen != $.ui.accordion.defaults.alwaysOpen) {
+                       o.collapsible = !o.alwaysOpen;
+               }
+
+               if ( o.navigation ) {
+                       var current = this.element.find("a").filter(o.navigationFilter);
+                       if ( current.length ) {
+                               if ( current.filter(o.header).length ) {
+                                       this.active = current;
+                               } else {
+                                       this.active = current.parent().parent().prev();
+                                       current.addClass("ui-accordion-content-active");
+                               }
+                       }
+               }
+
+               this.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
+               if (this.element[0].nodeName == "UL") {
+                       this.element.children("li").addClass("ui-accordion-li-fix");
+               }
+
+               this.headers = this.element.find(o.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all")
+                       .bind("mouseenter.accordion", function(){ $(this).addClass('ui-state-hover'); })
+                       .bind("mouseleave.accordion", function(){ $(this).removeClass('ui-state-hover'); })
+                       .bind("focus.accordion", function(){ $(this).addClass('ui-state-focus'); })
+                       .bind("blur.accordion", function(){ $(this).removeClass('ui-state-focus'); });
+
+               this.headers
+                       .next()
+                               .addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom");
+
+               this.active = this._findActive(this.active || o.active).toggleClass("ui-state-default").toggleClass("ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top");
+               this.active.next().addClass('ui-accordion-content-active');
+
+               //Append icon elements
+               $("<span/>").addClass("ui-icon " + o.icons.header).prependTo(this.headers);
+               this.active.find(".ui-icon").toggleClass(o.icons.header).toggleClass(o.icons.headerSelected);
+
+               // IE7-/Win - Extra vertical space in lists fixed
+               if ($.browser.msie) {
+                       this.element.find('a').css('zoom', '1');
+               }
+
+               this.resize();
+
+               //ARIA
+               this.element.attr('role','tablist');
+
+               this.headers
+                       .attr('role','tab')
+                       .bind('keydown', function(event) { return self._keydown(event); })
+                       .next()
+                       .attr('role','tabpanel');
+
+               this.headers
+                       .not(this.active || "")
+                       .attr('aria-expanded','false')
+                       .attr("tabIndex", "-1")
+                       .next()
+                       .hide();
+
+               // make sure at least one header is in the tab order
+               if (!this.active.length) {
+                       this.headers.eq(0).attr('tabIndex','0');
+               } else {
+                       this.active
+                               .attr('aria-expanded','true')
+                               .attr('tabIndex', '0');
+               }
+
+               // only need links in taborder for Safari
+               if (!$.browser.safari)
+                       this.headers.find('a').attr('tabIndex','-1');
+
+               if (o.event) {
+                       this.headers.bind((o.event) + ".accordion", function(event) { return self._clickHandler.call(self, event, this); });
+               }
+
+       },
+
+       destroy: function() {
+               var o = this.options;
+
+               this.element
+                       .removeClass("ui-accordion ui-widget ui-helper-reset")
+                       .removeAttr("role")
+                       .unbind('.accordion')
+                       .removeData('accordion');
+
+               this.headers
+                       .unbind(".accordion")
+                       .removeClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-corner-top")
+                       .removeAttr("role").removeAttr("aria-expanded").removeAttr("tabindex");
+
+               this.headers.find("a").removeAttr("tabindex");
+               this.headers.children(".ui-icon").remove();
+               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");
+               if (o.autoHeight || o.fillHeight) {
+                       contents.css("height", "");
+               }
+       },
+       
+       _setData: function(key, value) {
+               if(key == 'alwaysOpen') { key = 'collapsible'; value = !value; }
+               $.widget.prototype._setData.apply(this, arguments);     
+       },
+
+       _keydown: function(event) {
+
+               var o = this.options, keyCode = $.ui.keyCode;
+
+               if (o.disabled || event.altKey || event.ctrlKey)
+                       return;
+
+               var length = this.headers.length;
+               var currentIndex = this.headers.index(event.target);
+               var 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:
+                               return this._clickHandler({ target: event.target }, event.target);
+               }
+
+               if (toFocus) {
+                       $(event.target).attr('tabIndex','-1');
+                       $(toFocus).attr('tabIndex','0');
+                       toFocus.focus();
+                       return false;
+               }
+
+               return true;
+
+       },
+
+       resize: function() {
+
+               var o = this.options, maxHeight;
+
+               if (o.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();
+                       });
+
+                       var maxPadding = 0;
+                       this.headers.next().each(function() {
+                               maxPadding = Math.max(maxPadding, $(this).innerHeight() - $(this).height());
+                       }).height(Math.max(0, maxHeight - maxPadding))
+                       .css('overflow', 'auto');
+
+               } else if ( o.autoHeight ) {
+                       maxHeight = 0;
+                       this.headers.next().each(function() {
+                               maxHeight = Math.max(maxHeight, $(this).outerHeight());
+                       }).height(maxHeight);
+               }
+
+       },
+
+       activate: function(index) {
+               // call clickHandler with custom event
+               var active = this._findActive(index)[0];
+               this._clickHandler({ target: active }, active);
+       },
+
+       _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)");
+       },
+
+       _clickHandler: function(event, target) {
+
+               var o = this.options;
+               if (o.disabled) return false;
+
+               // called only when using activate(false) to close all parts programmatically
+               if (!event.target && o.collapsible) {
+                       this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all")
+                               .find(".ui-icon").removeClass(o.icons.headerSelected).addClass(o.icons.header);
+                       this.active.next().addClass('ui-accordion-content-active');
+                       var toHide = this.active.next(),
+                               data = {
+                                       options: o,
+                                       newHeader: $([]),
+                                       oldHeader: o.active,
+                                       newContent: $([]),
+                                       oldContent: toHide
+                               },
+                               toShow = (this.active = $([]));
+                       this._toggle(toShow, toHide, data);
+                       return false;
+               }
+
+               // get the click target
+               var clicked = $(event.currentTarget || target);
+               var clickedIsActive = clicked[0] == this.active[0];
+
+               // if animations are still active, or the active header is the target, ignore click
+               if (this.running || (!o.collapsible && clickedIsActive)) {
+                       return false;
+               }
+
+               // switch classes
+               this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all")
+                       .find(".ui-icon").removeClass(o.icons.headerSelected).addClass(o.icons.header);
+               this.active.next().addClass('ui-accordion-content-active');
+               if (!clickedIsActive) {
+                       clicked.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top")
+                               .find(".ui-icon").removeClass(o.icons.header).addClass(o.icons.headerSelected);
+                       clicked.next().addClass('ui-accordion-content-active');
+               }
+
+               // find elements to show and hide
+               var toShow = clicked.next(),
+                       toHide = this.active.next(),
+                       data = {
+                               options: o,
+                               newHeader: clickedIsActive && o.collapsible ? $([]) : clicked,
+                               oldHeader: this.active,
+                               newContent: clickedIsActive && o.collapsible ? $([]) : toShow.find('> *'),
+                               oldContent: toHide.find('> *')
+                       },
+                       down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
+
+               this.active = clickedIsActive ? $([]) : clicked;
+               this._toggle(toShow, toHide, data, clickedIsActive, down);
+
+               return false;
+
+       },
+
+       _toggle: function(toShow, toHide, data, clickedIsActive, down) {
+
+               var o = this.options, self = this;
+
+               this.toShow = toShow;
+               this.toHide = toHide;
+               this.data = data;
+
+               var complete = function() { if(!self) return; return self._completed.apply(self, arguments); };
+
+               // trigger changestart event
+               this._trigger("changestart", null, this.data);
+
+               // count elements to animate
+               this.running = toHide.size() === 0 ? toShow.size() : toHide.size();
+
+               if (o.animated) {
+
+                       var animOptions = {};
+
+                       if ( o.collapsible && clickedIsActive ) {
+                               animOptions = {
+                                       toShow: $([]),
+                                       toHide: toHide,
+                                       complete: complete,
+                                       down: down,
+                                       autoHeight: o.autoHeight || o.fillSpace
+                               };
+                       } else {
+                               animOptions = {
+                                       toShow: toShow,
+                                       toHide: toHide,
+                                       complete: complete,
+                                       down: down,
+                                       autoHeight: o.autoHeight || o.fillSpace
+                               };
+                       }
+
+                       if (!o.proxied) {
+                               o.proxied = o.animated;
+                       }
+
+                       if (!o.proxiedDuration) {
+                               o.proxiedDuration = o.duration;
+                       }
+
+                       o.animated = $.isFunction(o.proxied) ?
+                               o.proxied(animOptions) : o.proxied;
+
+                       o.duration = $.isFunction(o.proxiedDuration) ?
+                               o.proxiedDuration(animOptions) : o.proxiedDuration;
+
+                       var animations = $.ui.accordion.animations,
+                               duration = o.duration,
+                               easing = o.animated;
+
+                       if (!animations[easing]) {
+                               animations[easing] = function(options) {
+                                       this.slide(options, {
+                                               easing: easing,
+                                               duration: duration || 700
+                                       });
+                               };
+                       }
+
+                       animations[easing](animOptions);
+
+               } else {
+
+                       if (o.collapsible && clickedIsActive) {
+                               toShow.toggle();
+                       } else {
+                               toHide.hide();
+                               toShow.show();
+                       }
+
+                       complete(true);
+
+               }
+
+               toHide.prev().attr('aria-expanded','false').attr("tabIndex", "-1").blur();
+               toShow.prev().attr('aria-expanded','true').attr("tabIndex", "0").focus();
+
+       },
+
+       _completed: function(cancel) {
+
+               var o = this.options;
+
+               this.running = cancel ? 0 : --this.running;
+               if (this.running) return;
+
+               if (o.clearStyle) {
+                       this.toShow.add(this.toHide).css({
+                               height: "",
+                               overflow: ""
+                       });
+               }
+
+               this._trigger('change', null, this.data);
+       }
+
+});
+
+
+$.extend($.ui.accordion, {
+       version: "1.7.1",
+       defaults: {
+               active: null,
+               alwaysOpen: true, //deprecated, use collapsible
+               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();
+               }
+       },
+       animations: {
+               slide: function(options, additions) {
+                       options = $.extend({
+                               easing: "swing",
+                               duration: 300
+                       }, options, additions);
+                       if ( !options.toHide.size() ) {
+                               options.toShow.animate({height: "show"}, options);
+                               return;
+                       }
+                       if ( !options.toShow.size() ) {
+                               options.toHide.animate({height: "hide"}, options);
+                               return;
+                       }
+                       var overflow = options.toShow.css('overflow'),
+                               percentDone,
+                               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( parseInt(s.parent().width(),10) - parseInt(s.css("paddingLeft"),10) - parseInt(s.css("paddingRight"),10) - (parseInt(s.css("borderLeftWidth"),10) || 0) - (parseInt(s.css("borderRightWidth"),10) || 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.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);
+                                       options.toShow.css({overflow: overflow});
+                                       options.complete();
+                               }
+                       });
+               },
+               bounceslide: function(options) {
+                       this.slide(options, {
+                               easing: options.down ? "easeOutBounce" : "swing",
+                               duration: options.down ? 1000 : 200
+                       });
+               },
+               easeslide: function(options) {
+                       this.slide(options, {
+                               easing: "easeinout",
+                               duration: 700
+                       });
+               }
+       }
+});
+
+})(jQuery);
+/*
+ * jQuery UI Dialog 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Dialog
+ *
+ * Depends:
+ *     ui.core.js
+ *     ui.draggable.js
+ *     ui.resizable.js
+ */
+(function($) {
+
+var setDataSwitch = {
+               dragStart: "start.draggable",
+               drag: "drag.draggable",
+               dragStop: "stop.draggable",
+               maxHeight: "maxHeight.resizable",
+               minHeight: "minHeight.resizable",
+               maxWidth: "maxWidth.resizable",
+               minWidth: "minWidth.resizable",
+               resizeStart: "start.resizable",
+               resize: "drag.resizable",
+               resizeStop: "stop.resizable"
+       },
+       
+       uiDialogClasses =
+               'ui-dialog ' +
+               'ui-widget ' +
+               'ui-widget-content ' +
+               'ui-corner-all ';
+
+$.widget("ui.dialog", {
+
+       _init: function() {
+               this.originalTitle = this.element.attr('title');
+
+               var self = this,
+                       options = this.options,
+
+                       title = options.title || this.originalTitle || '&nbsp;',
+                       titleId = $.ui.dialog.getTitleId(this.element),
+
+                       uiDialog = (this.uiDialog = $('<div/>'))
+                               .appendTo(document.body)
+                               .hide()
+                               .addClass(uiDialogClasses + options.dialogClass)
+                               .css({
+                                       position: 'absolute',
+                                       overflow: 'hidden',
+                                       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) {
+                                       (options.closeOnEscape && event.keyCode
+                                               && event.keyCode == $.ui.keyCode.ESCAPE && self.close(event));
+                               })
+                               .attr({
+                                       role: 'dialog',
+                                       'aria-labelledby': titleId
+                               })
+                               .mousedown(function(event) {
+                                       self.moveToTop(false, event);
+                               }),
+
+                       uiDialogContent = this.element
+                               .show()
+                               .removeAttr('title')
+                               .addClass(
+                                       'ui-dialog-content ' +
+                                       'ui-widget-content')
+                               .appendTo(uiDialog),
+
+                       uiDialogTitlebar = (this.uiDialogTitlebar = $('<div></div>'))
+                               .addClass(
+                                       'ui-dialog-titlebar ' +
+                                       'ui-widget-header ' +
+                                       'ui-corner-all ' +
+                                       'ui-helper-clearfix'
+                               )
+                               .prependTo(uiDialog),
+
+                       uiDialogTitlebarClose = $('<a href="#"/>')
+                               .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');
+                               })
+                               .mousedown(function(ev) {
+                                       ev.stopPropagation();
+                               })
+                               .click(function(event) {
+                                       self.close(event);
+                                       return false;
+                               })
+                               .appendTo(uiDialogTitlebar),
+
+                       uiDialogTitlebarCloseText = (this.uiDialogTitlebarCloseText = $('<span/>'))
+                               .addClass(
+                                       'ui-icon ' +
+                                       'ui-icon-closethick'
+                               )
+                               .text(options.closeText)
+                               .appendTo(uiDialogTitlebarClose),
+
+                       uiDialogTitle = $('<span/>')
+                               .addClass('ui-dialog-title')
+                               .attr('id', titleId)
+                               .html(title)
+                               .prependTo(uiDialogTitlebar);
+
+               uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
+
+               (options.draggable && $.fn.draggable && this._makeDraggable());
+               (options.resizable && $.fn.resizable && this._makeResizable());
+
+               this._createButtons(options.buttons);
+               this._isOpen = false;
+
+               (options.bgiframe && $.fn.bgiframe && uiDialog.bgiframe());
+               (options.autoOpen && this.open());
+               
+       },
+
+       destroy: function() {
+               (this.overlay && this.overlay.destroy());
+               this.uiDialog.hide();
+               this.element
+                       .unbind('.dialog')
+                       .removeData('dialog')
+                       .removeClass('ui-dialog-content ui-widget-content')
+                       .hide().appendTo('body');
+               this.uiDialog.remove();
+
+               (this.originalTitle && this.element.attr('title', this.originalTitle));
+       },
+
+       close: function(event) {
+               var self = this;
+               
+               if (false === self._trigger('beforeclose', event)) {
+                       return;
+               }
+
+               (self.overlay && self.overlay.destroy());
+               self.uiDialog.unbind('keypress.ui-dialog');
+
+               (self.options.hide
+                       ? self.uiDialog.hide(self.options.hide, function() {
+                               self._trigger('close', event);
+                       })
+                       : self.uiDialog.hide() && self._trigger('close', event));
+
+               $.ui.dialog.overlay.resize();
+
+               self._isOpen = false;
+       },
+
+       isOpen: function() {
+               return this._isOpen;
+       },
+
+       // the force parameter allows us to move modal dialogs to their correct
+       // position on open
+       moveToTop: function(force, event) {
+
+               if ((this.options.modal && !force)
+                       || (!this.options.stack && !this.options.modal)) {
+                       return this._trigger('focus', event);
+               }
+               
+               if (this.options.zIndex > $.ui.dialog.maxZ) {
+                       $.ui.dialog.maxZ = this.options.zIndex;
+               }
+               (this.overlay && this.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
+               var saveScroll = { scrollTop: this.element.attr('scrollTop'), scrollLeft: this.element.attr('scrollLeft') };
+               this.uiDialog.css('z-index', ++$.ui.dialog.maxZ);
+               this.element.attr(saveScroll);
+               this._trigger('focus', event);
+       },
+
+       open: function() {
+               if (this._isOpen) { return; }
+
+               var options = this.options,
+                       uiDialog = this.uiDialog;
+
+               this.overlay = options.modal ? new $.ui.dialog.overlay(this) : null;
+               (uiDialog.next().length && uiDialog.appendTo('body'));
+               this._size();
+               this._position(options.position);
+               uiDialog.show(options.show);
+               this.moveToTop(true);
+
+               // prevent tabbing out of modal dialogs
+               (options.modal && uiDialog.bind('keypress.ui-dialog', function(event) {
+                       if (event.keyCode != $.ui.keyCode.TAB) {
+                               return;
+                       }
+
+                       var tabbables = $(':tabbable', this),
+                               first = tabbables.filter(':first')[0],
+                               last  = tabbables.filter(':last')[0];
+
+                       if (event.target == last && !event.shiftKey) {
+                               setTimeout(function() {
+                                       first.focus();
+                               }, 1);
+                       } else if (event.target == first && event.shiftKey) {
+                               setTimeout(function() {
+                                       last.focus();
+                               }, 1);
+                       }
+               }));
+
+               // 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
+               $([])
+                       .add(uiDialog.find('.ui-dialog-content :tabbable:first'))
+                       .add(uiDialog.find('.ui-dialog-buttonpane :tabbable:first'))
+                       .add(uiDialog)
+                       .filter(':first')
+                       .focus();
+
+               this._trigger('open');
+               this._isOpen = true;
+       },
+
+       _createButtons: function(buttons) {
+               var self = this,
+                       hasButtons = false,
+                       uiDialogButtonPane = $('<div></div>')
+                               .addClass(
+                                       'ui-dialog-buttonpane ' +
+                                       'ui-widget-content ' +
+                                       'ui-helper-clearfix'
+                               );
+
+               // if we already have a button pane, remove it
+               this.uiDialog.find('.ui-dialog-buttonpane').remove();
+
+               (typeof buttons == 'object' && buttons !== null &&
+                       $.each(buttons, function() { return !(hasButtons = true); }));
+               if (hasButtons) {
+                       $.each(buttons, function(name, fn) {
+                               $('<button type="button"></button>')
+                                       .addClass(
+                                               'ui-state-default ' +
+                                               'ui-corner-all'
+                                       )
+                                       .text(name)
+                                       .click(function() { fn.apply(self.element[0], arguments); })
+                                       .hover(
+                                               function() {
+                                                       $(this).addClass('ui-state-hover');
+                                               },
+                                               function() {
+                                                       $(this).removeClass('ui-state-hover');
+                                               }
+                                       )
+                                       .focus(function() {
+                                               $(this).addClass('ui-state-focus');
+                                       })
+                                       .blur(function() {
+                                               $(this).removeClass('ui-state-focus');
+                                       })
+                                       .appendTo(uiDialogButtonPane);
+                       });
+                       uiDialogButtonPane.appendTo(this.uiDialog);
+               }
+       },
+
+       _makeDraggable: function() {
+               var self = this,
+                       options = this.options,
+                       heightBeforeDrag;
+
+               this.uiDialog.draggable({
+                       cancel: '.ui-dialog-content',
+                       handle: '.ui-dialog-titlebar',
+                       containment: 'document',
+                       start: function() {
+                               heightBeforeDrag = options.height;
+                               $(this).height($(this).height()).addClass("ui-dialog-dragging");
+                               (options.dragStart && options.dragStart.apply(self.element[0], arguments));
+                       },
+                       drag: function() {
+                               (options.drag && options.drag.apply(self.element[0], arguments));
+                       },
+                       stop: function() {
+                               $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
+                               (options.dragStop && options.dragStop.apply(self.element[0], arguments));
+                               $.ui.dialog.overlay.resize();
+                       }
+               });
+       },
+
+       _makeResizable: function(handles) {
+               handles = (handles === undefined ? this.options.resizable : handles);
+               var self = this,
+                       options = this.options,
+                       resizeHandles = typeof handles == 'string'
+                               ? handles
+                               : 'n,e,s,w,se,sw,ne,nw';
+
+               this.uiDialog.resizable({
+                       cancel: '.ui-dialog-content',
+                       alsoResize: this.element,
+                       maxWidth: options.maxWidth,
+                       maxHeight: options.maxHeight,
+                       minWidth: options.minWidth,
+                       minHeight: options.minHeight,
+                       start: function() {
+                               $(this).addClass("ui-dialog-resizing");
+                               (options.resizeStart && options.resizeStart.apply(self.element[0], arguments));
+                       },
+                       resize: function() {
+                               (options.resize && options.resize.apply(self.element[0], arguments));
+                       },
+                       handles: resizeHandles,
+                       stop: function() {
+                               $(this).removeClass("ui-dialog-resizing");
+                               options.height = $(this).height();
+                               options.width = $(this).width();
+                               (options.resizeStop && options.resizeStop.apply(self.element[0], arguments));
+                               $.ui.dialog.overlay.resize();
+                       }
+               })
+               .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
+       },
+
+       _position: function(pos) {
+               var wnd = $(window), doc = $(document),
+                       pTop = doc.scrollTop(), pLeft = doc.scrollLeft(),
+                       minTop = pTop;
+
+               if ($.inArray(pos, ['center','top','right','bottom','left']) >= 0) {
+                       pos = [
+                               pos == 'right' || pos == 'left' ? pos : 'center',
+                               pos == 'top' || pos == 'bottom' ? pos : 'middle'
+                       ];
+               }
+               if (pos.constructor != Array) {
+                       pos = ['center', 'middle'];
+               }
+               if (pos[0].constructor == Number) {
+                       pLeft += pos[0];
+               } else {
+                       switch (pos[0]) {
+                               case 'left':
+                                       pLeft += 0;
+                                       break;
+                               case 'right':
+                                       pLeft += wnd.width() - this.uiDialog.outerWidth();
+                                       break;
+                               default:
+                               case 'center':
+                                       pLeft += (wnd.width() - this.uiDialog.outerWidth()) / 2;
+                       }
+               }
+               if (pos[1].constructor == Number) {
+                       pTop += pos[1];
+               } else {
+                       switch (pos[1]) {
+                               case 'top':
+                                       pTop += 0;
+                                       break;
+                               case 'bottom':
+                                       pTop += wnd.height() - this.uiDialog.outerHeight();
+                                       break;
+                               default:
+                               case 'middle':
+                                       pTop += (wnd.height() - this.uiDialog.outerHeight()) / 2;
+                       }
+               }
+
+               // prevent the dialog from being too high (make sure the titlebar
+               // is accessible)
+               pTop = Math.max(pTop, minTop);
+               this.uiDialog.css({top: pTop, left: pLeft});
+       },
+
+       _setData: function(key, value){
+               (setDataSwitch[key] && this.uiDialog.data(setDataSwitch[key], value));
+               switch (key) {
+                       case "buttons":
+                               this._createButtons(value);
+                               break;
+                       case "closeText":
+                               this.uiDialogTitlebarCloseText.text(value);
+                               break;
+                       case "dialogClass":
+                               this.uiDialog
+                                       .removeClass(this.options.dialogClass)
+                                       .addClass(uiDialogClasses + value);
+                               break;
+                       case "draggable":
+                               (value
+                                       ? this._makeDraggable()
+                                       : this.uiDialog.draggable('destroy'));
+                               break;
+                       case "height":
+                               this.uiDialog.height(value);
+                               break;
+                       case "position":
+                               this._position(value);
+                               break;
+                       case "resizable":
+                               var uiDialog = this.uiDialog,
+                                       isResizable = this.uiDialog.is(':data(resizable)');
+
+                               // currently resizable, becoming non-resizable
+                               (isResizable && !value && uiDialog.resizable('destroy'));
+
+                               // currently resizable, changing handles
+                               (isResizable && typeof value == 'string' &&
+                                       uiDialog.resizable('option', 'handles', value));
+
+                               // currently non-resizable, becoming resizable
+                               (isResizable || this._makeResizable(value));
+                               break;
+                       case "title":
+                               $(".ui-dialog-title", this.uiDialogTitlebar).html(value || '&nbsp;');
+                               break;
+                       case "width":
+                               this.uiDialog.width(value);
+                               break;
+               }
+
+               $.widget.prototype._setData.apply(this, 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;
+
+               // reset content sizing
+               this.element.css({
+                       height: 0,
+                       minHeight: 0,
+                       width: 'auto'
+               });
+
+               // reset wrapper sizing
+               // determine the height of all the non-content elements
+               var nonContentHeight = this.uiDialog.css({
+                               height: 'auto',
+                               width: options.width
+                       })
+                       .height();
+
+               this.element
+                       .css({
+                               minHeight: Math.max(options.minHeight - nonContentHeight, 0),
+                               height: options.height == 'auto'
+                                       ? 'auto'
+                                       : Math.max(options.height - nonContentHeight, 0)
+                       });
+       }
+});
+
+$.extend($.ui.dialog, {
+       version: "1.7.1",
+       defaults: {
+               autoOpen: true,
+               bgiframe: false,
+               buttons: {},
+               closeOnEscape: true,
+               closeText: 'close',
+               dialogClass: '',
+               draggable: true,
+               hide: null,
+               height: 'auto',
+               maxHeight: false,
+               maxWidth: false,
+               minHeight: 150,
+               minWidth: 150,
+               modal: false,
+               position: 'center',
+               resizable: true,
+               show: null,
+               stack: true,
+               title: '',
+               width: 300,
+               zIndex: 1000
+       },
+
+       getter: 'isOpen',
+
+       uuid: 0,
+       maxZ: 0,
+
+       getTitleId: function($el) {
+               return 'ui-dialog-title-' + ($el.attr('id') || ++this.uuid);
+       },
+
+       overlay: function(dialog) {
+               this.$el = $.ui.dialog.overlay.create(dialog);
+       }
+});
+
+$.extend($.ui.dialog.overlay, {
+       instances: [],
+       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() {
+                               $(document).bind($.ui.dialog.overlay.events, function(event) {
+                                       var dialogZ = $(event.target).parents('.ui-dialog').css('zIndex') || 0;
+                                       return (dialogZ > $.ui.dialog.overlay.maxZ);
+                               });
+                       }, 1);
+
+                       // allow closing by pressing the escape key
+                       $(document).bind('keydown.dialog-overlay', function(event) {
+                               (dialog.options.closeOnEscape && event.keyCode
+                                               && event.keyCode == $.ui.keyCode.ESCAPE && dialog.close(event));
+                       });
+
+                       // handle window resize
+                       $(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
+               }
+
+               var $el = $('<div></div>').appendTo(document.body)
+                       .addClass('ui-widget-overlay').css({
+                               width: this.width(),
+                               height: this.height()
+                       });
+
+               (dialog.options.bgiframe && $.fn.bgiframe && $el.bgiframe());
+
+               this.instances.push($el);
+               return $el;
+       },
+
+       destroy: function($el) {
+               this.instances.splice($.inArray(this.instances, $el), 1);
+
+               if (this.instances.length === 0) {
+                       $([document, window]).unbind('.dialog-overlay');
+               }
+
+               $el.remove();
+       },
+
+       height: function() {
+               // handle IE 6
+               if ($.browser.msie && $.browser.version < 7) {
+                       var scrollHeight = Math.max(
+                               document.documentElement.scrollHeight,
+                               document.body.scrollHeight
+                       );
+                       var 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() {
+               // handle IE 6
+               if ($.browser.msie && $.browser.version < 7) {
+                       var scrollWidth = Math.max(
+                               document.documentElement.scrollWidth,
+                               document.body.scrollWidth
+                       );
+                       var 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);
+/*
+ * jQuery UI Slider 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Slider
+ *
+ * Depends:
+ *     ui.core.js
+ */
+
+(function($) {
+
+$.widget("ui.slider", $.extend({}, $.ui.mouse, {
+
+       _init: function() {
+
+               var self = this, o = this.options;
+               this._keySliding = false;
+               this._handleIndex = null;
+               this._detectOrientation();
+               this._mouseInit();
+
+               this.element
+                       .addClass("ui-slider"
+                               + " ui-slider-" + this.orientation
+                               + " ui-widget"
+                               + " ui-widget-content"
+                               + " ui-corner-all");
+
+               this.range = $([]);
+
+               if (o.range) {
+
+                       if (o.range === true) {
+                               this.range = $('<div></div>');
+                               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]];
+                               }
+                       } else {
+                               this.range = $('<div></div>');
+                       }
+
+                       this.range
+                               .appendTo(this.element)
+                               .addClass("ui-slider-range");
+
+                       if (o.range == "min" || o.range == "max") {
+                               this.range.addClass("ui-slider-range-" + o.range);
+                       }
+
+                       // note: this isn't the most fittingly semantic framework class for this element,
+                       // but worked best visually with a variety of themes
+                       this.range.addClass("ui-widget-header");
+
+               }
+
+               if ($(".ui-slider-handle", this.element).length == 0)
+                       $('<a href="#"></a>')
+                               .appendTo(this.element)
+                               .addClass("ui-slider-handle");
+
+               if (o.values && o.values.length) {
+                       while ($(".ui-slider-handle", this.element).length < o.values.length)
+                               $('<a href="#"></a>')
+                                       .appendTo(this.element)
+                                       .addClass("ui-slider-handle");
+               }
+
+               this.handles = $(".ui-slider-handle", this.element)
+                       .addClass("ui-state-default"
+                               + " ui-corner-all");
+
+               this.handle = this.handles.eq(0);
+
+               this.handles.add(this.range).filter("a")
+                       .click(function(event) { event.preventDefault(); })
+                       .hover(function() { $(this).addClass('ui-state-hover'); }, function() { $(this).removeClass('ui-state-hover'); })
+                       .focus(function() { $(".ui-slider .ui-state-focus").removeClass('ui-state-focus'); $(this).addClass('ui-state-focus'); })
+                       .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 ret = true;
+
+                       var index = $(this).data("index.ui-slider-handle");
+
+                       if (self.options.disabled)
+                               return;
+
+                       switch (event.keyCode) {
+                               case $.ui.keyCode.HOME:
+                               case $.ui.keyCode.END:
+                               case $.ui.keyCode.UP:
+                               case $.ui.keyCode.RIGHT:
+                               case $.ui.keyCode.DOWN:
+                               case $.ui.keyCode.LEFT:
+                                       ret = false;
+                                       if (!self._keySliding) {
+                                               self._keySliding = true;
+                                               $(this).addClass("ui-state-active");
+                                               self._start(event, index);
+                                       }
+                                       break;
+                       }
+
+                       var curVal, newVal, step = self._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.UP:
+                               case $.ui.keyCode.RIGHT:
+                                       if(curVal == self._valueMax()) return;
+                                       newVal = curVal + step;
+                                       break;
+                               case $.ui.keyCode.DOWN:
+                               case $.ui.keyCode.LEFT:
+                                       if(curVal == self._valueMin()) return;
+                                       newVal = curVal - step;
+                                       break;
+                       }
+
+                       self._slide(event, index, newVal);
+
+                       return ret;
+
+               }).keyup(function(event) {
+
+                       var index = $(this).data("index.ui-slider-handle");
+
+                       if (self._keySliding) {
+                               self._stop(event, index);
+                               self._change(event, index);
+                               self._keySliding = false;
+                               $(this).removeClass("ui-state-active");
+                       }
+
+               });
+
+               this._refreshValue();
+
+       },
+
+       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();
+
+       },
+
+       _mouseCapture: function(event) {
+
+               var o = this.options;
+
+               if (o.disabled)
+                       return false;
+
+               this.elementSize = {
+                       width: this.element.outerWidth(),
+                       height: this.element.outerHeight()
+               };
+               this.elementOffset = this.element.offset();
+
+               var position = { x: event.pageX, y: event.pageY };
+               var normValue = this._normValueFromMouse(position);
+
+               var distance = this._valueMax() - this._valueMin() + 1, closestHandle;
+               var self = this, index;
+               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) {
+                       closestHandle = $(this.handles[++index]);
+               }
+
+               this._start(event, index);
+
+               self._handleIndex = index;
+
+               closestHandle
+                       .addClass("ui-state-active")
+                       .focus();
+               
+               var offset = closestHandle.offset();
+               var 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)
+               };
+
+               normValue = this._normValueFromMouse(position);
+               this._slide(event, index, normValue);
+               return true;
+
+       },
+
+       _mouseStart: function(event) {
+               return true;
+       },
+
+       _mouseDrag: function(event) {
+
+               var position = { x: event.pageX, y: event.pageY };
+               var normValue = this._normValueFromMouse(position);
+               
+               this._slide(event, this._handleIndex, normValue);
+
+               return false;
+
+       },
+
+       _mouseStop: function(event) {
+
+               this.handles.removeClass("ui-state-active");
+               this._stop(event, this._handleIndex);
+               this._change(event, this._handleIndex);
+               this._handleIndex = null;
+               this._clickOffset = null;
+
+               return false;
+
+       },
+       
+       _detectOrientation: function() {
+               this.orientation = this.options.orientation == 'vertical' ? 'vertical' : 'horizontal';
+       },
+
+       _normValueFromMouse: function(position) {
+
+               var pixelTotal, pixelMouse;
+               if ('horizontal' == this.orientation) {
+                       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);
+               }
+
+               var percentMouse = (pixelMouse / pixelTotal);
+               if (percentMouse > 1) percentMouse = 1;
+               if (percentMouse < 0) percentMouse = 0;
+               if ('vertical' == this.orientation)
+                       percentMouse = 1 - percentMouse;
+
+               var valueTotal = this._valueMax() - this._valueMin(),
+                       valueMouse = percentMouse * valueTotal,
+                       valueMouseModStep = valueMouse % this.options.step,
+                       normValue = this._valueMin() + valueMouse - valueMouseModStep;
+
+               if (valueMouseModStep > (this.options.step / 2))
+                       normValue += this.options.step;
+
+               // Since JavaScript has problems with large floats, round
+               // the final value to 5 digits after the decimal point (see #4124)
+               return parseFloat(normValue.toFixed(5));
+
+       },
+
+       _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()
+               }
+               this._trigger("start", event, uiHash);
+       },
+
+       _slide: function(event, index, newVal) {
+
+               var handle = this.handles[index];
+
+               if (this.options.values && this.options.values.length) {
+
+                       var otherVal = this.values(index ? 0 : 1);
+
+                       if ((index == 0 && newVal >= otherVal) || (index == 1 && newVal <= otherVal))
+                               newVal = otherVal;
+
+                       if (newVal != this.values(index)) {
+                               var newValues = this.values();
+                               newValues[index] = newVal;
+                               // A slide can be canceled by returning false from the slide callback
+                               var allowed = this._trigger("slide", event, {
+                                       handle: this.handles[index],
+                                       value: newVal,
+                                       values: newValues
+                               });
+                               var otherVal = this.values(index ? 0 : 1);
+                               if (allowed !== false) {
+                                       this.values(index, newVal, ( event.type == 'mousedown' && this.options.animate ), true);
+                               }
+                       }
+
+               } else {
+
+                       if (newVal != this.value()) {
+                               // A slide can be canceled by returning false from the slide callback
+                               var allowed = this._trigger("slide", event, {
+                                       handle: this.handles[index],
+                                       value: newVal
+                               });
+                               if (allowed !== false) {
+                                       this._setData('value', newVal, ( event.type == 'mousedown' && this.options.animate ));
+                               }
+                                       
+                       }
+
+               }
+
+       },
+
+       _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) {
+               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._setData("value", newValue);
+                       this._change(null, 0);
+               }
+
+               return this._value();
+
+       },
+
+       values: function(index, newValue, animated, noPropagation) {
+
+               if (arguments.length > 1) {
+                       this.options.values[index] = newValue;
+                       this._refreshValue(animated);
+                       if(!noPropagation) this._change(null, index);
+               }
+
+               if (arguments.length) {
+                       if (this.options.values && this.options.values.length) {
+                               return this._values(index);
+                       } else {
+                               return this.value();
+                       }
+               } else {
+                       return this._values();
+               }
+
+       },
+
+       _setData: function(key, value, animated) {
+
+               $.widget.prototype._setData.apply(this, arguments);
+
+               switch (key) {
+                       case 'orientation':
+
+                               this._detectOrientation();
+                               
+                               this.element
+                                       .removeClass("ui-slider-horizontal ui-slider-vertical")
+                                       .addClass("ui-slider-" + this.orientation);
+                               this._refreshValue(animated);
+                               break;
+                       case 'value':
+                               this._refreshValue(animated);
+                               break;
+               }
+
+       },
+
+       _step: function() {
+               var step = this.options.step;
+               return step;
+       },
+
+       _value: function() {
+
+               var val = this.options.value;
+               if (val < this._valueMin()) val = this._valueMin();
+               if (val > this._valueMax()) val = this._valueMax();
+
+               return val;
+
+       },
+
+       _values: function(index) {
+
+               if (arguments.length) {
+                       var val = this.options.values[index];
+                       if (val < this._valueMin()) val = this._valueMin();
+                       if (val > this._valueMax()) val = this._valueMax();
+
+                       return val;
+               } else {
+                       return this.options.values;
+               }
+
+       },
+
+       _valueMin: function() {
+               var valueMin = this.options.min;
+               return valueMin;
+       },
+
+       _valueMax: function() {
+               var valueMax = this.options.max;
+               return valueMax;
+       },
+
+       _refreshValue: function(animate) {
+
+               var oRange = this.options.range, o = this.options, self = this;
+
+               if (this.options.values && this.options.values.length) {
+                       var vp0, vp1;
+                       this.handles.each(function(i, j) {
+                               var valPercent = (self.values(i) - self._valueMin()) / (self._valueMax() - self._valueMin()) * 100;
+                               var _set = {}; _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') {
+                                               (i == 0) && self.range.stop(1,1)[animate ? 'animate' : 'css']({ left: valPercent + '%' }, o.animate);
+                                               (i == 1) && self.range[animate ? 'animate' : 'css']({ width: (valPercent - lastValPercent) + '%' }, { queue: false, duration: o.animate });
+                                       } else {
+                                               (i == 0) && self.range.stop(1,1)[animate ? 'animate' : 'css']({ bottom: (valPercent) + '%' }, o.animate);
+                                               (i == 1) && self.range[animate ? 'animate' : 'css']({ height: (valPercent - lastValPercent) + '%' }, { queue: false, duration: o.animate });
+                                       }
+                               }
+                               lastValPercent = valPercent;
+                       });
+               } else {
+                       var value = this.value(),
+                               valueMin = this._valueMin(),
+                               valueMax = this._valueMax(),
+                               valPercent = valueMax != valueMin
+                                       ? (value - valueMin) / (valueMax - valueMin) * 100
+                                       : 0;
+                       var _set = {}; _set[self.orientation == 'horizontal' ? 'left' : 'bottom'] = valPercent + '%';
+                       this.handle.stop(1,1)[animate ? 'animate' : 'css'](_set, o.animate);
+
+                       (oRange == "min") && (this.orientation == "horizontal") && this.range.stop(1,1)[animate ? 'animate' : 'css']({ width: valPercent + '%' }, o.animate);
+                       (oRange == "max") && (this.orientation == "horizontal") && this.range[animate ? 'animate' : 'css']({ width: (100 - valPercent) + '%' }, { queue: false, duration: o.animate });
+                       (oRange == "min") && (this.orientation == "vertical") && this.range.stop(1,1)[animate ? 'animate' : 'css']({ height: valPercent + '%' }, o.animate);
+                       (oRange == "max") && (this.orientation == "vertical") && this.range[animate ? 'animate' : 'css']({ height: (100 - valPercent) + '%' }, { queue: false, duration: o.animate });
+               }
+
+       }
+       
+}));
+
+$.extend($.ui.slider, {
+       getter: "value values",
+       version: "1.7.1",
+       eventPrefix: "slide",
+       defaults: {
+               animate: false,
+               delay: 0,
+               distance: 0,
+               max: 100,
+               min: 0,
+               orientation: 'horizontal',
+               range: false,
+               step: 1,
+               value: 0,
+               values: null
+       }
+});
+
+})(jQuery);
+/*
+ * jQuery UI Tabs 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Tabs
+ *
+ * Depends:
+ *     ui.core.js
+ */
+(function($) {
+
+$.widget("ui.tabs", {
+
+       _init: function() {
+               if (this.options.deselectable !== undefined) {
+                       this.options.collapsible = this.options.deselectable;
+               }
+               this._tabify(true);
+       },
+
+       _setData: function(key, value) {
+               if (key == 'selected') {
+                       if (this.options.collapsible && value == this.options.selected) {
+                               return;
+                       }
+                       this.select(value);
+               }
+               else {
+                       this.options[key] = value;
+                       if (key == 'deselectable') {
+                               this.options.collapsible = value;
+                       }
+                       this._tabify();
+               }
+       },
+
+       _tabId: function(a) {
+               return a.title && a.title.replace(/\s/g, '_').replace(/[^A-Za-z0-9\-_:\.]/g, '') ||
+                       this.options.idPrefix + $.data(a);
+       },
+
+       _sanitizeSelector: function(hash) {
+               return hash.replace(/:/g, '\\:'); // we need this because an id may contain a ":"
+       },
+
+       _cookie: function() {
+               var cookie = this.cookie || (this.cookie = this.options.cookie.name || 'ui-tabs-' + $.data(this.list[0]));
+               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) {
+
+               this.list = this.element.children('ul:first');
+               this.lis = $('li:has(a[href])', this.list);
+               this.anchors = this.lis.map(function() { return $('a', this)[0]; });
+               this.panels = $([]);
+
+               var self = this, o = this.options;
+
+               var fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
+               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._sanitizeSelector(href));
+                       }
+
+                       // remote tab
+                       else if (href != '#') { // prevent loading the page itself if href is just "#"
+                               $.data(a, 'href.tabs', href); // required for restore on destroy
+
+                               // TODO until #3808 is fixed strip fragment identifier from url
+                               // (IE fails to load from such url)
+                               $.data(a, 'load.tabs', href.replace(/#.*$/, '')); // mutable data
+
+                               var id = self._tabId(a);
+                               a.href = '#' + id;
+                               var $panel = $('#' + 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; // break
+                                               }
+                                       });
+                               }
+                               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 || 0;
+                       }
+                       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');
+                       if (o.selected >= 0 && this.anchors.length) { // check for length avoids error when initializing empty list
+                               this.panels.eq(o.selected).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.panels[o.selected]));
+                               });
+                               
+                               this.load(o.selected);
+                       }
+
+                       // clean up to avoid memory leaks in certain versions of IE 6
+                       $(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
+               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 &&
+                               !$(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 ($.browser.msie && fx.opacity) {
+                               $el[0].style.removeAttribute('filter');
+                       }
+               }
+
+               // Show a tab...
+               var showTab = showFx ?
+                       function(clicked, $show) {
+                               $(clicked).closest('li').removeClass('ui-state-default').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').removeClass('ui-state-default').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').addClass('ui-state-default');
+                                       $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').addClass('ui-state-default');
+                               $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 = $(this).closest('li'), $hide = self.panels.filter(':not(.ui-tabs-hide)'),
+                                       $show = $(self._sanitizeSelector(this.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._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);
+                                       });
+
+                                       self.load(self.anchors.index(this)); // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
+                                       
+                                       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;});
+
+       },
+
+       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);
+               }
+       },
+
+       add: function(url, label, index) {
+               if (index === undefined) {
+                       index = this.anchors.length; // append by default
+               }
+
+               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 = $('#' + 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) { // after tabify
+                       $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);
+               }
+
+               // callback
+               this._trigger('add', null, this._ui(this.anchors[index], this.panels[index]));
+       },
+
+       remove: function(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();
+
+               // callback
+               this._trigger('remove', null, this._ui($li.find('a')[0], $panel[0]));
+       },
+
+       enable: function(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; });
+
+               // callback
+               this._trigger('enable', null, this._ui(this.anchors[index], this.panels[index]));
+       },
+
+       disable: function(index) {
+               var self = this, o = this.options;
+               if (index != o.selected) { // cannot disable already selected tab
+                       this.lis.eq(index).addClass('ui-state-disabled');
+
+                       o.disabled.push(index);
+                       o.disabled.sort();
+
+                       // callback
+                       this._trigger('disable', null, this._ui(this.anchors[index], this.panels[index]));
+               }
+       },
+
+       select: function(index) {
+               if (typeof index == 'string') {
+                       index = this.anchors.index(this.anchors.filter('[href$=' + index + ']'));
+               }
+               else if (index === null) { // usage of null is deprecated, TODO remove in next release
+                       index = -1;
+               }
+               if (index == -1 && this.options.collapsible) {
+                       index = this.options.selected;
+               }
+
+               this.anchors.eq(index).trigger(this.options.event + '.tabs');
+       },
+
+       load: function(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._sanitizeSelector(a.hash)).html(r);
+
+                               // take care of tab labels
+                               self._cleanup();
+
+                               if (o.cache) {
+                                       $.data(a, 'cache.tabs', true); // if loaded once do not load them again
+                               }
+
+                               // callbacks
+                               self._trigger('load', null, self._ui(self.anchors[index], self.panels[index]));
+                               try {
+                                       o.ajaxOptions.success(r, s);
+                               }
+                               catch (e) {}
+
+                               // last, so that load event is fired before show...
+                               self.element.dequeue("tabs");
+                       }
+               }));
+       },
+
+       abort: function() {
+               // stop possibly running animations
+               this.element.queue([]);
+               this.panels.stop(false, true);
+
+               // terminate pending requests from other tabs
+               if (this.xhr) {
+                       this.xhr.abort();
+                       delete this.xhr;
+               }
+
+               // take care of tab labels
+               this._cleanup();
+
+       },
+
+       url: function(index, url) {
+               this.anchors.eq(index).removeData('cache.tabs').data('load.tabs', url);
+       },
+
+       length: function() {
+               return this.anchors.length;
+       }
+
+});
+
+$.extend($.ui.tabs, {
+       version: '1.7.1',
+       getter: 'length',
+       defaults: {
+               ajaxOptions: null,
+               cache: false,
+               cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
+               collapsible: false,
+               disabled: [],
+               event: 'click',
+               fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
+               idPrefix: 'ui-tabs-',
+               panelTemplate: '<div></div>',
+               spinner: '<em>Loading&#8230;</em>',
+               tabTemplate: '<li><a href="#{href}"><span>#{label}</span></a></li>'
+       }
+});
+
+/*
+ * 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) {
+                               t = o.selected;
+                               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;
+               }
+       }
+});
+
+})(jQuery);
+/*
+ * jQuery UI Datepicker 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Datepicker
+ *
+ * Depends:
+ *     ui.core.js
+ */
+
+(function($) { // hide the namespace
+
+$.extend($.ui, { datepicker: { version: "1.7.1" } });
+
+var PROP_NAME = 'datepicker';
+
+/* 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
+               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
+       };
+       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: 'show', // 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
+               showMonthAfterYear: false, // True if the year select precedes month, false for month then year
+               yearRange: '-10:+10', // Range of years to display in drop-down,
+                       // either relative to current year (-nn:+nn) or absolute (nnnn:nnnn)
+               showOtherMonths: false, // True to show dates in other months, false to leave blank
+               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: 'normal', // 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
+       };
+       $.extend(this._defaults, this.regional['']);
+       this.dpDiv = $('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>');
+}
+
+$.extend(Datepicker.prototype, {
+       /* Class name added to elements to indicate already configured with a date picker. */
+       markerClassName: 'hasDatepicker',
+
+       /* Debug logging (if enabled). */
+       log: function () {
+               if (this.debug)
+                       console.log.apply('', arguments);
+       },
+
+       /* 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)
+                       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(/([:\[\]\.])/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
+                       $('<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.trigger = $([]);
+               if (input.hasClass(this.markerClassName))
+                       return;
+               var appendText = this._get(inst, 'appendText');
+               var isRTL = this._get(inst, 'isRTL');
+               if (appendText)
+                       input[isRTL ? 'before' : 'after']('<span class="' + this._appendClass + '">' + appendText + '</span>');
+               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 == target)
+                                       $.datepicker._hideDatepicker();
+                               else
+                                       $.datepicker._showDatepicker(target);
+                               return false;
+                       });
+               }
+               input.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).
+                       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);
+       },
+
+       /* 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));
+               this._updateDatepicker(inst);
+               this._updateAlternate(inst);
+       },
+
+       /* Pop-up the date picker in a "dialog" box.
+          @param  input     element - ignored
+          @param  dateText  string - the initial date to display (in the current format)
+          @param  onSelect  function - the function(dateText) 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, dateText, onSelect, settings, pos) {
+               var inst = this._dialogInst; // internal instance
+               if (!inst) {
+                       var id = 'dp' + (++this.uuid);
+                       this._dialogInput = $('<input type="text" id="' + id +
+                               '" size="1" style="position: absolute; top: -100px;"/>');
+                       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 || {});
+               this._dialogInput.val(dateText);
+
+               this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
+               if (!this._pos) {
+                       var browserWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
+                       var browserHeight = window.innerHeight || document.documentElement.clientHeight || document.body.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] + '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.trigger.remove();
+                       $target.siblings('.' + this._appendClass).remove().end().
+                               removeClass(this.markerClassName).
+                               unbind('focus', this._showDatepicker).
+                               unbind('keydown', this._doKeyDown).
+                               unbind('keypress', this._doKeyPress);
+               } 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');
+               }
+               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');
+               }
+               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 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
+          @param  value   any - the new value for the setting (omit if above is an object) */
+       _optionDatepicker: function(target, name, value) {
+               var settings = name || {};
+               if (typeof name == 'string') {
+                       settings = {};
+                       settings[name] = value;
+               }
+               var inst = this._getInst(target);
+               if (inst) {
+                       if (this._curInst == inst) {
+                               this._hideDatepicker(null);
+                       }
+                       extendRemove(inst.settings, settings);
+                       var date = new Date();
+                       extendRemove(inst, {rangeStart: null, // start of range
+                               endDay: null, endMonth: null, endYear: null, // end of range
+                               selectedDay: date.getDate(), selectedMonth: date.getMonth(),
+                               selectedYear: date.getFullYear(), // starting point
+                               currentDay: date.getDate(), currentMonth: date.getMonth(),
+                               currentYear: date.getFullYear(), // current selection
+                               drawMonth: date.getMonth(), drawYear: date.getFullYear()}); // month being drawn
+                       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
+          @param  endDate  Date - the new end date for a range (optional) */
+       _setDateDatepicker: function(target, date, endDate) {
+               var inst = this._getInst(target);
+               if (inst) {
+                       this._setDate(inst, date, endDate);
+                       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
+          @return Date - the current date or
+                  Date[2] - the current dates for a range */
+       _getDateDatepicker: function(target) {
+               var inst = this._getInst(target);
+               if (inst && !inst.inline)
+                       this._setDateFromField(inst);
+               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(null, '');
+                                               break; // hide on tab out
+                               case 13: var sel = $('td.' + $.datepicker._dayOverClass +
+                                                       ', td.' + $.datepicker._currentClass, inst.dpDiv);
+                                               if (sel[0])
+                                                       $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
+                                               else
+                                                       $.datepicker._hideDatepicker(null, $.datepicker._get(inst, 'duration'));
+                                               return false; // don't submit the form
+                                               break; // select the value on enter
+                               case 27: $.datepicker._hideDatepicker(null, $.datepicker._get(inst, 'duration'));
+                                               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 || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
+               }
+       },
+
+       /* Pop-up the date picker for a given input field.
+          @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);
+               var beforeShow = $.datepicker._get(inst, 'beforeShow');
+               extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
+               $.datepicker._hideDatepicker(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;
+               inst.rangeStart = null;
+               // 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') || 'show';
+                       var duration = $.datepicker._get(inst, 'duration');
+                       var postProcess = function() {
+                               $.datepicker._datepickerShowing = true;
+                               if ($.browser.msie && parseInt($.browser.version,10) < 7) // fix IE < 7 select problems
+                                       $('iframe.ui-datepicker-cover').css({width: inst.dpDiv.width() + 4,
+                                               height: inst.dpDiv.height() + 4});
+                       };
+                       if ($.effects && $.effects[showAnim])
+                               inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
+                       else
+                               inst.dpDiv[showAnim](duration, postProcess);
+                       if (duration == '')
+                               postProcess();
+                       if (inst.input[0].type != 'hidden')
+                               inst.input[0].focus();
+                       $.datepicker._curInst = inst;
+               }
+       },
+
+       /* Generate the date picker content. */
+       _updateDatepicker: function(inst) {
+               var dims = {width: inst.dpDiv.width() + 4,
+                       height: inst.dpDiv.height() + 4};
+               var self = this;
+               inst.dpDiv.empty().append(this._generateHTML(inst))
+                       .find('iframe.ui-datepicker-cover').
+                               css({width: dims.width, height: dims.height})
+                       .end()
+                       .find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')
+                               .bind('mouseout', function(){
+                                       $(this).removeClass('ui-state-hover');
+                                       if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
+                                       if(this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
+                               })
+                               .bind('mouseover', function(){
+                                       if (!self._isDisabledDatepicker( inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) {
+                                               $(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
+                                               $(this).addClass('ui-state-hover');
+                                               if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
+                                               if(this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
+                                       }
+                               })
+                       .end()
+                       .find('.' + this._dayOverClass + ' a')
+                               .trigger('mouseover')
+                       .end();
+               var numMonths = this._getNumberOfMonths(inst);
+               var cols = numMonths[1];
+               var width = 17;
+               if (cols > 1) {
+                       inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
+               } else {
+                       inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
+               }
+               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.input && inst.input[0].type != 'hidden' && inst == $.datepicker._curInst)
+                       $(inst.input[0]).focus();
+       },
+
+       /* 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 = (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) + $(document).scrollLeft();
+               var viewHeight = (window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight) + $(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 -= (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? Math.abs(offset.left + dpWidth - viewWidth) : 0;
+               offset.top -= (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? Math.abs(offset.top + dpHeight + inputHeight*2 - viewHeight) : 0;
+
+               return offset;
+       },
+
+       /* Find an object's position on the screen. */
+       _findPos: function(obj) {
+        while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
+            obj = obj.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
+          @param  duration  string - the duration over which to close the date picker */
+       _hideDatepicker: function(input, duration) {
+               var inst = this._curInst;
+               if (!inst || (input && inst != $.data(input, PROP_NAME)))
+                       return;
+               if (inst.stayOpen)
+                       this._selectDate('#' + inst.id, this._formatDate(inst,
+                               inst.currentDay, inst.currentMonth, inst.currentYear));
+               inst.stayOpen = false;
+               if (this._datepickerShowing) {
+                       duration = (duration != null ? duration : this._get(inst, 'duration'));
+                       var showAnim = this._get(inst, 'showAnim');
+                       var postProcess = function() {
+                               $.datepicker._tidyDialog(inst);
+                       };
+                       if (duration != '' && $.effects && $.effects[showAnim])
+                               inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'),
+                                       duration, postProcess);
+                       else
+                               inst.dpDiv[(duration == '' ? 'hide' : (showAnim == 'slideDown' ? 'slideUp' :
+                                       (showAnim == 'fadeIn' ? 'fadeOut' : 'hide')))](duration, postProcess);
+                       if (duration == '')
+                               this._tidyDialog(inst);
+                       var onClose = this._get(inst, 'onClose');
+                       if (onClose)
+                               onClose.apply((inst.input ? inst.input[0] : null),
+                                       [(inst.input ? inst.input.val() : ''), inst]);  // trigger custom callback
+                       this._datepickerShowing = false;
+                       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;
+               }
+               this._curInst = null;
+       },
+
+       /* 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);
+               if (($target.parents('#' + $.datepicker._mainDivId).length == 0) &&
+                               !$target.hasClass($.datepicker.markerClassName) &&
+                               !$target.hasClass($.datepicker._triggerClass) &&
+                               $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
+                       $.datepicker._hideDatepicker(null, '');
+       },
+
+       /* 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._selectingMonthYear = false;
+               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);
+       },
+
+       /* Restore input focus after not changing month/year. */
+       _clickMonthYear: function(id) {
+               var target = $(id);
+               var inst = this._getInst(target[0]);
+               if (inst.input && inst._selectingMonthYear && !$.browser.msie)
+                       inst.input[0].focus();
+               inst._selectingMonthYear = !inst._selectingMonthYear;
+       },
+
+       /* 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;
+               if (inst.stayOpen) {
+                       inst.endDay = inst.endMonth = inst.endYear = null;
+               }
+               this._selectDate(id, this._formatDate(inst,
+                       inst.currentDay, inst.currentMonth, inst.currentYear));
+               if (inst.stayOpen) {
+                       inst.rangeStart = this._daylightSavingAdjust(
+                               new Date(inst.currentYear, inst.currentMonth, inst.currentDay));
+                       this._updateDatepicker(inst);
+               }
+       },
+
+       /* Erase the input field and hide the date picker. */
+       _clearDate: function(id) {
+               var target = $(id);
+               var inst = this._getInst(target[0]);
+               inst.stayOpen = false;
+               inst.endDay = inst.endMonth = inst.endYear = inst.rangeStart = null;
+               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 if (!inst.stayOpen) {
+                       this._hideDatepicker(null, this._get(inst, 'duration'));
+                       this._lastInput = inst.input[0];
+                       if (typeof(inst.input[0]) != 'object')
+                               inst.input[0].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);
+                       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.getFullYear(), date.getMonth(), date.getDate());
+               var firstMon = new Date(checkDate.getFullYear(), 1 - 1, 4); // First week always contains 4 Jan
+               var firstDay = firstMon.getDay() || 7; // Day of week: Mon = 1, ..., Sun = 7
+               firstMon.setDate(firstMon.getDate() + 1 - firstDay); // Preceding Monday
+               if (firstDay < 4 && checkDate < firstMon) { // Adjust first three days in year if necessary
+                       checkDate.setDate(checkDate.getDate() - 3); // Generate for previous year
+                       return $.datepicker.iso8601Week(checkDate);
+               } else if (checkDate > new Date(checkDate.getFullYear(), 12 - 1, 28)) { // Check last three days in year
+                       firstDay = new Date(checkDate.getFullYear() + 1, 1 - 1, 4).getDay() || 7;
+                       if (firstDay > 4 && (checkDate.getDay() || 7) < firstDay - 3) { // Adjust if necessary
+                               return 1;
+                       }
+               }
+               return Math.floor(((checkDate - firstMon) / 86400000) / 7) + 1; // Weeks to given date
+       },
+
+       /* 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;
+               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) {
+                       lookAhead(match);
+                       var origSize = (match == '@' ? 14 : (match == 'y' ? 4 : (match == 'o' ? 3 : 2)));
+                       var size = origSize;
+                       var num = 0;
+                       while (size > 0 && iValue < value.length &&
+                                       value.charAt(iValue) >= '0' && value.charAt(iValue) <= '9') {
+                               num = num * 10 + parseInt(value.charAt(iValue++),10);
+                               size--;
+                       }
+                       if (size == origSize)
+                               throw 'Missing number at position ' + iValue;
+                       return num;
+               };
+               // Extract a name from the string value and convert to an index
+               var getName = function(match, shortNames, longNames) {
+                       var names = (lookAhead(match) ? longNames : shortNames);
+                       var size = 0;
+                       for (var j = 0; j < names.length; j++)
+                               size = Math.max(size, names[j].length);
+                       var name = '';
+                       var iInit = iValue;
+                       while (size > 0 && iValue < value.length) {
+                               name += value.charAt(iValue++);
+                               for (var i = 0; i < names.length; i++)
+                                       if (name == names[i])
+                                               return i + 1;
+                               size--;
+                       }
+                       throw 'Unknown name at position ' + iInit;
+               };
+               // 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 "'":
+                                               if (lookAhead("'"))
+                                                       checkLiteral();
+                                               else
+                                                       literal = true;
+                                               break;
+                                       default:
+                                               checkLiteral();
+                               }
+               }
+               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/*
+               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
+       TIMESTAMP: '@',
+       W3C: 'yy-mm-dd', // ISO 8601
+
+       /* 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)
+          '...' - 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':
+                                                       var doy = date.getDate();
+                                                       for (var m = date.getMonth() - 1; m >= 0; m--)
+                                                               doy += this._getDaysInMonth(date.getFullYear(), m);
+                                                       output += formatNumber('o', doy, 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 "'":
+                                                       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;
+               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) {
+               var dateFormat = this._get(inst, 'dateFormat');
+               var dates = inst.input ? inst.input.val() : null;
+               inst.endDay = inst.endMonth = inst.endYear = null;
+               var date = defaultDate = this._getDefaultDate(inst);
+               var settings = this._getFormatConfig(inst);
+               try {
+                       date = this.parseDate(dateFormat, dates, settings) || defaultDate;
+               } catch (event) {
+                       this.log(event);
+                       date = defaultDate;
+               }
+               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) {
+               var date = this._determineDate(this._get(inst, 'defaultDate'), new Date());
+               var minDate = this._getMinMaxDate(inst, 'min', true);
+               var maxDate = this._getMinMaxDate(inst, 'max');
+               date = (minDate && date < minDate ? minDate : date);
+               date = (maxDate && date > maxDate ? maxDate : date);
+               return date;
+       },
+
+       /* A date may be specified as an exact value or a relative one. */
+       _determineDate: function(date, defaultDate) {
+               var offsetNumeric = function(offset) {
+                       var date = new Date();
+                       date.setDate(date.getDate() + offset);
+                       return date;
+               };
+               var offsetString = function(offset, getDaysInMonth) {
+                       var date = 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, getDaysInMonth(year, month));
+                                               break;
+                                       case 'y': case 'Y' :
+                                               year += parseInt(matches[1],10);
+                                               day = Math.min(day, getDaysInMonth(year, month));
+                                               break;
+                               }
+                               matches = pattern.exec(offset);
+                       }
+                       return new Date(year, month, day);
+               };
+               date = (date == null ? defaultDate :
+                       (typeof date == 'string' ? offsetString(date, this._getDaysInMonth) :
+                       (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : date)));
+               date = (date && date.toString() == 'Invalid Date' ? defaultDate : date);
+               if (date) {
+                       date.setHours(0);
+                       date.setMinutes(0);
+                       date.setSeconds(0);
+                       date.setMilliseconds(0);
+               }
+               return this._daylightSavingAdjust(date);
+       },
+
+       /* 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, endDate) {
+               var clear = !(date);
+               var origMonth = inst.selectedMonth;
+               var origYear = inst.selectedYear;
+               date = this._determineDate(date, new Date());
+               inst.selectedDay = inst.currentDay = date.getDate();
+               inst.drawMonth = inst.selectedMonth = inst.currentMonth = date.getMonth();
+               inst.drawYear = inst.selectedYear = inst.currentYear = date.getFullYear();
+               if (origMonth != inst.selectedMonth || origYear != inst.selectedYear)
+                       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;
+       },
+
+       /* 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 stepBigMonths = this._get(inst, 'stepBigMonths');
+               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', true);
+               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[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" onclick="DP_jQuery.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
+                       ' 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" onclick="DP_jQuery.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
+                       ' 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" onclick="DP_jQuery.datepicker._hideDatepicker();">' + 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" onclick="DP_jQuery.datepicker._gotoToday(\'#' + inst.id + '\');"' +
+                       '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
+               var firstDay = parseInt(this._get(inst, 'firstDay'),10);
+               firstDay = (isNaN(firstDay) ? 0 : firstDay);
+               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 calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
+               var endDate = inst.endDay ? this._daylightSavingAdjust(
+                       new Date(inst.endYear, inst.endMonth, inst.endDay)) : currentDate;
+               var defaultDate = this._getDefaultDate(inst);
+               var html = '';
+               for (var row = 0; row < numMonths[0]; row++) {
+                       var group = '';
+                       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 ui-datepicker-group-';
+                                       switch (col) {
+                                               case 0: calender += 'first'; cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
+                                               case numMonths[1]-1: calender += 'last'; cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
+                                               default: calender += '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,
+                                       selectedDate, row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
+                                       '</div><table class="ui-datepicker-calendar"><thead>' +
+                                       '<tr>';
+                               var thead = '';
+                               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 numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
+                               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 = '';
+                                       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 || !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() && printDate.getTime() <= endDate.getTime() ? // in current range
+                                                       ' ' + 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 ? '' : ' onclick="DP_jQuery.datepicker._selectDay(\'#' +
+                                                       inst.id + '\',' + drawMonth + ',' + drawYear + ', this);return false;"') + '>' + // actions
+                                                       (otherMonth ? (showOtherMonths ? printDate.getDate() : '&#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() && printDate.getTime() <= endDate.getTime() ? // in current range
+                                                       ' ui-state-active' : '') + // highlight selected day
+                                                       '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display for this month
+                                               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,
+                       selectedDate, secondary, monthNames, monthNamesShort) {
+               minDate = (inst.rangeStart && minDate && selectedDate < minDate ? selectedDate : minDate);
+               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" ' +
+                               'onchange="DP_jQuery.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
+                               'onclick="DP_jQuery.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
+                               '>';
+                       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) && (!(changeMonth && changeYear)) ? '&#xa0;' : '');
+               // year selection
+               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 year = 0;
+                       var endYear = 0;
+                       if (years.length != 2) {
+                               year = drawYear - 10;
+                               endYear = drawYear + 10;
+                       } else if (years[0].charAt(0) == '+' || years[0].charAt(0) == '-') {
+                               year = drawYear + parseInt(years[0], 10);
+                               endYear = drawYear + parseInt(years[1], 10);
+                       } else {
+                               year = parseInt(years[0], 10);
+                               endYear = parseInt(years[1], 10);
+                       }
+                       year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
+                       endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
+                       html += '<select class="ui-datepicker-year" ' +
+                               'onchange="DP_jQuery.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
+                               'onclick="DP_jQuery.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
+                               '>';
+                       for (; year <= endYear; year++) {
+                               html += '<option value="' + year + '"' +
+                                       (year == drawYear ? ' selected="selected"' : '') +
+                                       '>' + year + '</option>';
+                       }
+                       html += '</select>';
+               }
+               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._daylightSavingAdjust(new Date(year, month, day));
+               // ensure it is within the bounds set
+               var minDate = this._getMinMaxDate(inst, 'min', true);
+               var maxDate = this._getMinMaxDate(inst, 'max');
+               date = (minDate && date < minDate ? minDate : date);
+               date = (maxDate && date > maxDate ? maxDate : date);
+               inst.selectedDay = date.getDate();
+               inst.drawMonth = inst.selectedMonth = date.getMonth();
+               inst.drawYear = inst.selectedYear = date.getFullYear();
+               if (period == 'M' || period == 'Y')
+                       this._notifyChange(inst);
+       },
+
+       /* 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 - may be overridden for a range. */
+       _getMinMaxDate: function(inst, minMax, checkRange) {
+               var date = this._determineDate(this._get(inst, minMax + 'Date'), null);
+               return (!checkRange || !inst.rangeStart ? date :
+                       (!date || inst.rangeStart > date ? inst.rangeStart : date));
+       },
+
+       /* Find the number of days in a given month. */
+       _getDaysInMonth: function(year, month) {
+               return 32 - 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[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) {
+               // during range selection, use minimum of selected date and range start
+               var newMinDate = (!inst.rangeStart ? null : this._daylightSavingAdjust(
+                       new Date(inst.selectedYear, inst.selectedMonth, inst.selectedDay)));
+               newMinDate = (newMinDate && inst.rangeStart < newMinDate ? inst.rangeStart : newMinDate);
+               var minDate = newMinDate || this._getMinMaxDate(inst, 'min');
+               var maxDate = this._getMinMaxDate(inst, 'max');
+               return ((!minDate || date >= minDate) && (!maxDate || date <= maxDate));
+       },
+
+       /* 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));
+       }
+});
+
+/* 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){
+
+       /* 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'))
+               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.7.1";
+
+// Workaround for #4055
+// Add another global to avoid noConflict issues with inline event handlers
+window.DP_jQuery = $;
+
+})(jQuery);
+/*
+ * jQuery UI Progressbar 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Progressbar
+ *
+ * Depends:
+ *   ui.core.js
+ */
+(function($) {
+
+$.widget("ui.progressbar", {
+
+       _init: function() {
+
+               this.element
+                       .addClass("ui-progressbar"
+                               + " ui-widget"
+                               + " ui-widget-content"
+                               + " ui-corner-all")
+                       .attr({
+                               role: "progressbar",
+                               "aria-valuemin": this._valueMin(),
+                               "aria-valuemax": this._valueMax(),
+                               "aria-valuenow": this._value()
+                       });
+
+               this.valueDiv = $('<div class="ui-progressbar-value ui-widget-header ui-corner-left"></div>').appendTo(this.element);
+
+               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")
+                       .removeData("progressbar")
+                       .unbind(".progressbar");
+
+               this.valueDiv.remove();
+
+               $.widget.prototype.destroy.apply(this, arguments);
+
+       },
+
+       value: function(newValue) {
+               arguments.length && this._setData("value", newValue);
+               return this._value();
+       },
+
+       _setData: function(key, value) {
+
+               switch (key) {
+                       case 'value':
+                               this.options.value = value;
+                               this._refreshValue();
+                               this._trigger('change', null, {});
+                               break;
+               }
+
+               $.widget.prototype._setData.apply(this, arguments);
+
+       },
+
+       _value: function() {
+
+               var val = this.options.value;
+               if (val < this._valueMin()) val = this._valueMin();
+               if (val > this._valueMax()) val = this._valueMax();
+
+               return val;
+
+       },
+
+       _valueMin: function() {
+               var valueMin = 0;
+               return valueMin;
+       },
+
+       _valueMax: function() {
+               var valueMax = 100;
+               return valueMax;
+       },
+
+       _refreshValue: function() {
+               var value = this.value();
+               this.valueDiv[value == this._valueMax() ? 'addClass' : 'removeClass']("ui-corner-right");
+               this.valueDiv.width(value + '%');
+               this.element.attr("aria-valuenow", value);
+       }
+
+});
+
+$.extend($.ui.progressbar, {
+       version: "1.7.1",
+       defaults: {
+               value: 0
+       }
+});
+
+})(jQuery);
+/*
+ * jQuery UI Effects 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/
+ */
+;jQuery.effects || (function($) {
+
+$.effects = {
+       version: "1.7.1",
+
+       // 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();
+
+               //Cache width,height and float properties of the element, and create a wrapper around it
+               var props = { width: element.outerWidth(true), height: element.outerHeight(true), 'float': element.css('float') };
+               element.wrap('<div class="ui-effects-wrapper" style="font-size:100%;background:transparent;border:none;margin:0;padding:0"></div>');
+               var wrapper = element.parent();
+
+               //Transfer the positioning of the element to the wrapper
+               if (element.css('position') == 'static') {
+                       wrapper.css({ position: 'relative' });
+                       element.css({ position: 'relative'} );
+               } else {
+                       var top = element.css('top'); if(isNaN(parseInt(top,10))) top = 'auto';
+                       var left = element.css('left'); if(isNaN(parseInt(left,10))) left = 'auto';
+                       wrapper.css({ position: element.css('position'), top: top, left: left, zIndex: element.css('z-index') }).show();
+                       element.css({position: 'relative', top: 0, left: 0 });
+               }
+
+               wrapper.css(props);
+               return wrapper;
+       },
+
+       removeWrapper: function(element) {
+               if (element.parent().is('.ui-effects-wrapper'))
+                       return element.parent().replaceWith(element);
+               return element;
+       },
+
+       setTransition: function(element, list, factor, value) {
+               value = value || {};
+               $.each(list, function(i, x){
+                       unit = element.cssUnit(x);
+                       if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];
+               });
+               return value;
+       },
+
+       //Base function to animate from one class to another in a seamless transition
+       animateClass: function(value, duration, easing, callback) {
+
+               var cb = (typeof easing == "function" ? easing : (callback ? callback : null));
+               var ea = (typeof easing == "string" ? easing : null);
+
+               return this.each(function() {
+
+                       var offset = {}; var that = $(this); var oldStyleAttr = that.attr("style") || '';
+                       if(typeof oldStyleAttr == 'object') oldStyleAttr = oldStyleAttr["cssText"]; /* Stupidly in IE, style is a object.. */
+                       if(value.toggle) { that.hasClass(value.toggle) ? value.remove = value.toggle : value.add = value.toggle; }
+
+                       //Let's get a style offset
+                       var oldStyle = $.extend({}, (document.defaultView ? document.defaultView.getComputedStyle(this,null) : this.currentStyle));
+                       if(value.add) that.addClass(value.add); if(value.remove) that.removeClass(value.remove);
+                       var newStyle = $.extend({}, (document.defaultView ? document.defaultView.getComputedStyle(this,null) : this.currentStyle));
+                       if(value.add) that.removeClass(value.add); if(value.remove) that.addClass(value.remove);
+
+                       // The main function to form the object for animation
+                       for(var n in newStyle) {
+                               if( typeof newStyle[n] != "function" && newStyle[n] /* No functions and null properties */
+                               && n.indexOf("Moz") == -1 && n.indexOf("length") == -1 /* No mozilla spezific render properties. */
+                               && newStyle[n] != oldStyle[n] /* Only values that have changed are used for the animation */
+                               && (n.match(/color/i) || (!n.match(/color/i) && !isNaN(parseInt(newStyle[n],10)))) /* Only things that can be parsed to integers or colors */
+                               && (oldStyle.position != "static" || (oldStyle.position == "static" && !n.match(/left|top|bottom|right/))) /* No need for positions when dealing with static positions */
+                               ) offset[n] = newStyle[n];
+                       }
+
+                       that.animate(offset, duration, ea, function() { // Animate the newly constructed offset object
+                               // Change style attribute back to original. For stupid IE, we need to clear the damn object.
+                               if(typeof $(this).attr("style") == 'object') { $(this).attr("style")["cssText"] = ""; $(this).attr("style")["cssText"] = oldStyleAttr; } else $(this).attr("style", oldStyleAttr);
+                               if(value.add) $(this).addClass(value.add); if(value.remove) $(this).removeClass(value.remove);
+                               if(cb) cb.apply(this, arguments);
+                       });
+
+               });
+       }
+};
+
+
+function _normalizeArguments(a, m) {
+
+       var o = a[1] && a[1].constructor == Object ? a[1] : {}; if(m) o.mode = m;
+       var speed = a[1] && a[1].constructor != Object ? a[1] : (o.duration ? o.duration : a[2]); //either comes from options.duration or the secon/third argument
+               speed = $.fx.off ? 0 : typeof speed === "number" ? speed : $.fx.speeds[speed] || $.fx.speeds._default;
+       var callback = o.callback || ( $.isFunction(a[1]) && a[1] ) || ( $.isFunction(a[2]) && a[2] ) || ( $.isFunction(a[3]) && a[3] );
+
+       return [a[0], o, speed, callback];
+       
+}
+
+//Extend the methods of jQuery
+$.fn.extend({
+
+       //Save old methods
+       _show: $.fn.show,
+       _hide: $.fn.hide,
+       __toggle: $.fn.toggle,
+       _addClass: $.fn.addClass,
+       _removeClass: $.fn.removeClass,
+       _toggleClass: $.fn.toggleClass,
+
+       // New effect methods
+       effect: function(fx, options, speed, callback) {
+               return $.effects[fx] ? $.effects[fx].call(this, {method: fx, options: options || {}, duration: speed, callback: callback }) : null;
+       },
+
+       show: function() {
+               if(!arguments[0] || (arguments[0].constructor == Number || (/(slow|normal|fast)/).test(arguments[0])))
+                       return this._show.apply(this, arguments);
+               else {
+                       return this.effect.apply(this, _normalizeArguments(arguments, 'show'));
+               }
+       },
+
+       hide: function() {
+               if(!arguments[0] || (arguments[0].constructor == Number || (/(slow|normal|fast)/).test(arguments[0])))
+                       return this._hide.apply(this, arguments);
+               else {
+                       return this.effect.apply(this, _normalizeArguments(arguments, 'hide'));
+               }
+       },
+
+       toggle: function(){
+               if(!arguments[0] || (arguments[0].constructor == Number || (/(slow|normal|fast)/).test(arguments[0])) || (arguments[0].constructor == Function))
+                       return this.__toggle.apply(this, arguments);
+               else {
+                       return this.effect.apply(this, _normalizeArguments(arguments, 'toggle'));
+               }
+       },
+
+       addClass: function(classNames, speed, easing, callback) {
+               return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);
+       },
+       removeClass: function(classNames,speed,easing,callback) {
+               return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);
+       },
+       toggleClass: function(classNames,speed,easing,callback) {
+               return ( (typeof speed !== "boolean") && speed ) ? $.effects.animateClass.apply(this, [{ toggle: classNames },speed,easing,callback]) : this._toggleClass(classNames, speed);
+       },
+       morph: function(remove,add,speed,easing,callback) {
+               return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
+       },
+       switchClass: function() {
+               return this.morph.apply(this, arguments);
+       },
+
+       // 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;
+       }
+});
+
+/*
+ * jQuery Color Animations
+ * Copyright 2007 John Resig
+ * Released under the MIT and GPL licenses.
+ */
+
+// 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.state == 0 ) {
+                                               fx.start = getColor( fx.elem, attr );
+                                               fx.end = getRGB( fx.end );
+                               }
+
+                               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(",") + ")";
+                       };
+});
+
+// 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 {
+                               color = $.curCSS(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]
+};
+
+/*
+ * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
+ *
+ * Uses the built in easing capabilities added In jQuery 1.1
+ * to offer multiple easing options
+ *
+ * TERMS OF USE - jQuery Easing
+ *
+ * Open source under the BSD License.
+ *
+ * Copyright 2008 George McGinley Smith
+ * 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 the author nor the names of 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 OWNER 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.
+ *
+*/
+
+// t: current time, b: begInnIng value, c: change In value, d: duration
+$.easing.jswing = $.easing.swing;
+
+$.extend($.easing,
+{
+       def: 'easeOutQuad',
+       swing: function (x, t, b, c, d) {
+               //alert($.easing.default);
+               return $.easing[$.easing.def](x, t, b, c, d);
+       },
+       easeInQuad: function (x, t, b, c, d) {
+               return c*(t/=d)*t + b;
+       },
+       easeOutQuad: function (x, t, b, c, d) {
+               return -c *(t/=d)*(t-2) + b;
+       },
+       easeInOutQuad: function (x, t, b, c, d) {
+               if ((t/=d/2) < 1) return c/2*t*t + b;
+               return -c/2 * ((--t)*(t-2) - 1) + b;
+       },
+       easeInCubic: function (x, t, b, c, d) {
+               return c*(t/=d)*t*t + b;
+       },
+       easeOutCubic: function (x, t, b, c, d) {
+               return c*((t=t/d-1)*t*t + 1) + b;
+       },
+       easeInOutCubic: function (x, t, b, c, d) {
+               if ((t/=d/2) < 1) return c/2*t*t*t + b;
+               return c/2*((t-=2)*t*t + 2) + b;
+       },
+       easeInQuart: function (x, t, b, c, d) {
+               return c*(t/=d)*t*t*t + b;
+       },
+       easeOutQuart: function (x, t, b, c, d) {
+               return -c * ((t=t/d-1)*t*t*t - 1) + b;
+       },
+       easeInOutQuart: function (x, t, b, c, d) {
+               if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
+               return -c/2 * ((t-=2)*t*t*t - 2) + b;
+       },
+       easeInQuint: function (x, t, b, c, d) {
+               return c*(t/=d)*t*t*t*t + b;
+       },
+       easeOutQuint: function (x, t, b, c, d) {
+               return c*((t=t/d-1)*t*t*t*t + 1) + b;
+       },
+       easeInOutQuint: function (x, t, b, c, d) {
+               if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
+               return c/2*((t-=2)*t*t*t*t + 2) + b;
+       },
+       easeInSine: function (x, t, b, c, d) {
+               return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
+       },
+       easeOutSine: function (x, t, b, c, d) {
+               return c * Math.sin(t/d * (Math.PI/2)) + b;
+       },
+       easeInOutSine: function (x, t, b, c, d) {
+               return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
+       },
+       easeInExpo: function (x, t, b, c, d) {
+               return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
+       },
+       easeOutExpo: function (x, t, b, c, d) {
+               return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
+       },
+       easeInOutExpo: function (x, t, b, c, d) {
+               if (t==0) return b;
+               if (t==d) return b+c;
+               if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
+               return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
+       },
+       easeInCirc: function (x, t, b, c, d) {
+               return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
+       },
+       easeOutCirc: function (x, t, b, c, d) {
+               return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
+       },
+       easeInOutCirc: function (x, t, b, c, d) {
+               if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
+               return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
+       },
+       easeInElastic: function (x, t, b, c, d) {
+               var s=1.70158;var p=0;var a=c;
+               if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
+               if (a < Math.abs(c)) { a=c; var s=p/4; }
+               else var s = p/(2*Math.PI) * Math.asin (c/a);
+               return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
+       },
+       easeOutElastic: function (x, t, b, c, d) {
+               var s=1.70158;var p=0;var a=c;
+               if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
+               if (a < Math.abs(c)) { a=c; var s=p/4; }
+               else var s = p/(2*Math.PI) * Math.asin (c/a);
+               return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
+       },
+       easeInOutElastic: function (x, t, b, c, d) {
+               var s=1.70158;var p=0;var a=c;
+               if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
+               if (a < Math.abs(c)) { a=c; var s=p/4; }
+               else var s = p/(2*Math.PI) * Math.asin (c/a);
+               if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
+               return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
+       },
+       easeInBack: function (x, t, b, c, d, s) {
+               if (s == undefined) s = 1.70158;
+               return c*(t/=d)*t*((s+1)*t - s) + b;
+       },
+       easeOutBack: function (x, t, b, c, d, s) {
+               if (s == undefined) s = 1.70158;
+               return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
+       },
+       easeInOutBack: function (x, t, b, c, d, s) {
+               if (s == undefined) s = 1.70158;
+               if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
+               return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
+       },
+       easeInBounce: function (x, t, b, c, d) {
+               return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b;
+       },
+       easeOutBounce: function (x, t, b, c, d) {
+               if ((t/=d) < (1/2.75)) {
+                       return c*(7.5625*t*t) + b;
+               } else if (t < (2/2.75)) {
+                       return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
+               } else if (t < (2.5/2.75)) {
+                       return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
+               } else {
+                       return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
+               }
+       },
+       easeInOutBounce: function (x, t, b, c, d) {
+               if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
+               return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
+       }
+});
+
+/*
+ *
+ * TERMS OF USE - EASING EQUATIONS
+ *
+ * Open source under the BSD License.
+ *
+ * Copyright 2001 Robert Penner
+ * 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 the author nor the names of 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 OWNER 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.
+ *
+ */
+
+})(jQuery);
+/*
+ * jQuery UI Effects Blind 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Blind
+ *
+ * Depends:
+ *     effects.core.js
+ */
+(function($) {
+
+$.effects.blind = function(o) {
+
+       return this.queue(function() {
+
+               // Create element
+               var el = $(this), props = ['position','top','left'];
+
+               // 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);
+/*
+ * jQuery UI Effects Bounce 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Bounce
+ *
+ * Depends:
+ *     effects.core.js
+ */
+(function($) {
+
+$.effects.bounce = function(o) {
+
+       return this.queue(function() {
+
+               // Create element
+               var el = $(this), props = ['position','top','left'];
+
+               // 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({margin:true}) / 3 : el.outerWidth({margin: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);
+/*
+ * jQuery UI Effects Clip 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Clip
+ *
+ * Depends:
+ *     effects.core.js
+ */
+(function($) {
+
+$.effects.clip = function(o) {
+
+       return this.queue(function() {
+
+               // Create element
+               var el = $(this), props = ['position','top','left','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);
+/*
+ * jQuery UI Effects Drop 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Drop
+ *
+ * Depends:
+ *     effects.core.js
+ */
+(function($) {
+
+$.effects.drop = function(o) {
+
+       return this.queue(function() {
+
+               // Create element
+               var el = $(this), props = ['position','top','left','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({margin:true}) / 2 : el.outerWidth({margin: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);
+/*
+ * jQuery UI Effects Explode 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Explode
+ *
+ * Depends:
+ *     effects.core.js
+ */
+(function($) {
+
+$.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);
+/*
+ * jQuery UI Effects Fold 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Fold
+ *
+ * Depends:
+ *     effects.core.js
+ */
+(function($) {
+
+$.effects.fold = function(o) {
+
+       return this.queue(function() {
+
+               // Create element
+               var el = $(this), props = ['position','top','left'];
+
+               // 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);
+/*
+ * jQuery UI Effects Highlight 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Highlight
+ *
+ * Depends:
+ *     effects.core.js
+ */
+(function($) {
+
+$.effects.highlight = function(o) {
+
+       return this.queue(function() {
+
+               // Create element
+               var el = $(this), props = ['backgroundImage','backgroundColor','opacity'];
+
+               // Set options
+               var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
+               var color = o.options.color || "#ffff99"; // Default highlight color
+               var oldColor = el.css("backgroundColor");
+
+               // Adjust
+               $.effects.save(el, props); el.show(); // Save & Show
+               el.css({backgroundImage: 'none', backgroundColor: color}); // Shift
+
+               // Animation
+               var animation = {backgroundColor: oldColor };
+               if (mode == "hide") animation['opacity'] = 0;
+
+               // Animate
+               el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
+                       if(mode == "hide") el.hide();
+                       $.effects.restore(el, props);
+               if (mode == "show" && $.browser.msie) this.style.removeAttribute('filter');
+                       if(o.callback) o.callback.apply(this, arguments);
+                       el.dequeue();
+               }});
+
+       });
+
+};
+
+})(jQuery);
+/*
+ * jQuery UI Effects Pulsate 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Pulsate
+ *
+ * Depends:
+ *     effects.core.js
+ */
+(function($) {
+
+$.effects.pulsate = function(o) {
+
+       return this.queue(function() {
+
+               // Create element
+               var el = $(this);
+
+               // Set options
+               var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
+               var times = o.options.times || 5; // Default # of times
+               var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2;
+
+               // Adjust
+               if (mode == 'hide') times--;
+               if (el.is(':hidden')) { // Show fadeIn
+                       el.css('opacity', 0);
+                       el.show(); // Show
+                       el.animate({opacity: 1}, duration, o.options.easing);
+                       times = times-2;
+               }
+
+               // Animate
+               for (var i = 0; i < times; i++) { // Pulsate
+                       el.animate({opacity: 0}, duration, o.options.easing).animate({opacity: 1}, duration, o.options.easing);
+               };
+               if (mode == 'hide') { // Last Pulse
+                       el.animate({opacity: 0}, duration, o.options.easing, function(){
+                               el.hide(); // Hide
+                               if(o.callback) o.callback.apply(this, arguments); // Callback
+                       });
+               } else {
+                       el.animate({opacity: 0}, duration, o.options.easing).animate({opacity: 1}, duration, o.options.easing, function(){
+                               if(o.callback) o.callback.apply(this, arguments); // Callback
+                       });
+               };
+               el.queue('fx', function() { el.dequeue(); });
+               el.dequeue();
+       });
+
+};
+
+})(jQuery);
+/*
+ * jQuery UI Effects Scale 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Scale
+ *
+ * Depends:
+ *     effects.core.js
+ */
+(function($) {
+
+$.effects.puff = 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 || 'hide'); // Set Mode
+               var percent = parseInt(o.options.percent,10) || 150; // Set default puff percent
+               options.fade = true; // It's not a puff if it doesn't fade! :)
+               var original = {height: el.height(), width: el.width()}; // Save original
+
+               // Adjust
+               var factor = percent / 100;
+               el.from = (mode == 'hide') ? original : {height: original.height * factor, width: original.width * factor};
+
+               // Animation
+               options.from = el.from;
+               options.percent = (mode == 'hide') ? percent : 100;
+               options.mode = mode;
+
+               // Animate
+               el.effect('scale', options, o.duration, o.callback);
+               el.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','left','width','height','overflow','opacity'];
+               var props1 = ['position','top','left','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(){
+                               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(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);
+/*
+ * jQuery UI Effects Shake 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Shake
+ *
+ * Depends:
+ *     effects.core.js
+ */
+(function($) {
+
+$.effects.shake = function(o) {
+
+       return this.queue(function() {
+
+               // Create element
+               var el = $(this), props = ['position','top','left'];
+
+               // 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);
+/*
+ * jQuery UI Effects Slide 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Slide
+ *
+ * Depends:
+ *     effects.core.js
+ */
+(function($) {
+
+$.effects.slide = function(o) {
+
+       return this.queue(function() {
+
+               // Create element
+               var el = $(this), props = ['position','top','left'];
+
+               // 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({margin:true}) : el.outerWidth({margin:true}));
+               if (mode == 'show') el.css(ref, motion == 'pos' ? -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);
+/*
+ * jQuery UI Effects Transfer 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Transfer
+ *
+ * Depends:
+ *     effects.core.js
+ */
+(function($) {
+
+$.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/js2/mwEmbed/jquery/jquery.ui/ui/ui.accordion.js b/js2/mwEmbed/jquery/jquery.ui/ui/ui.accordion.js
new file mode 100644 (file)
index 0000000..0e94df1
--- /dev/null
@@ -0,0 +1,477 @@
+/*
+ * jQuery UI Accordion 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Accordion
+ *
+ * Depends:
+ *     ui.core.js
+ */
+(function($) {
+
+$.widget("ui.accordion", {
+
+       _init: function() {
+
+               var o = this.options, self = this;
+               this.running = 0;
+
+               // if the user set the alwaysOpen option on init
+               // then we need to set the collapsible option
+               // if they set both on init, collapsible will take priority
+               if (o.collapsible == $.ui.accordion.defaults.collapsible &&
+                       o.alwaysOpen != $.ui.accordion.defaults.alwaysOpen) {
+                       o.collapsible = !o.alwaysOpen;
+               }
+
+               if ( o.navigation ) {
+                       var current = this.element.find("a").filter(o.navigationFilter);
+                       if ( current.length ) {
+                               if ( current.filter(o.header).length ) {
+                                       this.active = current;
+                               } else {
+                                       this.active = current.parent().parent().prev();
+                                       current.addClass("ui-accordion-content-active");
+                               }
+                       }
+               }
+
+               this.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
+               if (this.element[0].nodeName == "UL") {
+                       this.element.children("li").addClass("ui-accordion-li-fix");
+               }
+
+               this.headers = this.element.find(o.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all")
+                       .bind("mouseenter.accordion", function(){ $(this).addClass('ui-state-hover'); })
+                       .bind("mouseleave.accordion", function(){ $(this).removeClass('ui-state-hover'); })
+                       .bind("focus.accordion", function(){ $(this).addClass('ui-state-focus'); })
+                       .bind("blur.accordion", function(){ $(this).removeClass('ui-state-focus'); });
+
+               this.headers
+                       .next()
+                               .addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom");
+
+               this.active = this._findActive(this.active || o.active).toggleClass("ui-state-default").toggleClass("ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top");
+               this.active.next().addClass('ui-accordion-content-active');
+
+               //Append icon elements
+               $("<span/>").addClass("ui-icon " + o.icons.header).prependTo(this.headers);
+               this.active.find(".ui-icon").toggleClass(o.icons.header).toggleClass(o.icons.headerSelected);
+
+               // IE7-/Win - Extra vertical space in lists fixed
+               if ($.browser.msie) {
+                       this.element.find('a').css('zoom', '1');
+               }
+
+               this.resize();
+
+               //ARIA
+               this.element.attr('role','tablist');
+
+               this.headers
+                       .attr('role','tab')
+                       .bind('keydown', function(event) { return self._keydown(event); })
+                       .next()
+                       .attr('role','tabpanel');
+
+               this.headers
+                       .not(this.active || "")
+                       .attr('aria-expanded','false')
+                       .attr("tabIndex", "-1")
+                       .next()
+                       .hide();
+
+               // make sure at least one header is in the tab order
+               if (!this.active.length) {
+                       this.headers.eq(0).attr('tabIndex','0');
+               } else {
+                       this.active
+                               .attr('aria-expanded','true')
+                               .attr('tabIndex', '0');
+               }
+
+               // only need links in taborder for Safari
+               if (!$.browser.safari)
+                       this.headers.find('a').attr('tabIndex','-1');
+
+               if (o.event) {
+                       this.headers.bind((o.event) + ".accordion", function(event) { return self._clickHandler.call(self, event, this); });
+               }
+
+       },
+
+       destroy: function() {
+               var o = this.options;
+
+               this.element
+                       .removeClass("ui-accordion ui-widget ui-helper-reset")
+                       .removeAttr("role")
+                       .unbind('.accordion')
+                       .removeData('accordion');
+
+               this.headers
+                       .unbind(".accordion")
+                       .removeClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-corner-top")
+                       .removeAttr("role").removeAttr("aria-expanded").removeAttr("tabindex");
+
+               this.headers.find("a").removeAttr("tabindex");
+               this.headers.children(".ui-icon").remove();
+               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");
+               if (o.autoHeight || o.fillHeight) {
+                       contents.css("height", "");
+               }
+       },
+       
+       _setData: function(key, value) {
+               if(key == 'alwaysOpen') { key = 'collapsible'; value = !value; }
+               $.widget.prototype._setData.apply(this, arguments);     
+       },
+
+       _keydown: function(event) {
+
+               var o = this.options, keyCode = $.ui.keyCode;
+
+               if (o.disabled || event.altKey || event.ctrlKey)
+                       return;
+
+               var length = this.headers.length;
+               var currentIndex = this.headers.index(event.target);
+               var 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:
+                               return this._clickHandler({ target: event.target }, event.target);
+               }
+
+               if (toFocus) {
+                       $(event.target).attr('tabIndex','-1');
+                       $(toFocus).attr('tabIndex','0');
+                       toFocus.focus();
+                       return false;
+               }
+
+               return true;
+
+       },
+
+       resize: function() {
+
+               var o = this.options, maxHeight;
+
+               if (o.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();
+                       });
+
+                       var maxPadding = 0;
+                       this.headers.next().each(function() {
+                               maxPadding = Math.max(maxPadding, $(this).innerHeight() - $(this).height());
+                       }).height(Math.max(0, maxHeight - maxPadding))
+                       .css('overflow', 'auto');
+
+               } else if ( o.autoHeight ) {
+                       maxHeight = 0;
+                       this.headers.next().each(function() {
+                               maxHeight = Math.max(maxHeight, $(this).outerHeight());
+                       }).height(maxHeight);
+               }
+
+       },
+
+       activate: function(index) {
+               // call clickHandler with custom event
+               var active = this._findActive(index)[0];
+               this._clickHandler({ target: active }, active);
+       },
+
+       _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)");
+       },
+
+       _clickHandler: function(event, target) {
+
+               var o = this.options;
+               if (o.disabled) return false;
+
+               // called only when using activate(false) to close all parts programmatically
+               if (!event.target && o.collapsible) {
+                       this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all")
+                               .find(".ui-icon").removeClass(o.icons.headerSelected).addClass(o.icons.header);
+                       this.active.next().addClass('ui-accordion-content-active');
+                       var toHide = this.active.next(),
+                               data = {
+                                       options: o,
+                                       newHeader: $([]),
+                                       oldHeader: o.active,
+                                       newContent: $([]),
+                                       oldContent: toHide
+                               },
+                               toShow = (this.active = $([]));
+                       this._toggle(toShow, toHide, data);
+                       return false;
+               }
+
+               // get the click target
+               var clicked = $(event.currentTarget || target);
+               var clickedIsActive = clicked[0] == this.active[0];
+
+               // if animations are still active, or the active header is the target, ignore click
+               if (this.running || (!o.collapsible && clickedIsActive)) {
+                       return false;
+               }
+
+               // switch classes
+               this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all")
+                       .find(".ui-icon").removeClass(o.icons.headerSelected).addClass(o.icons.header);
+               this.active.next().addClass('ui-accordion-content-active');
+               if (!clickedIsActive) {
+                       clicked.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top")
+                               .find(".ui-icon").removeClass(o.icons.header).addClass(o.icons.headerSelected);
+                       clicked.next().addClass('ui-accordion-content-active');
+               }
+
+               // find elements to show and hide
+               var toShow = clicked.next(),
+                       toHide = this.active.next(),
+                       data = {
+                               options: o,
+                               newHeader: clickedIsActive && o.collapsible ? $([]) : clicked,
+                               oldHeader: this.active,
+                               newContent: clickedIsActive && o.collapsible ? $([]) : toShow.find('> *'),
+                               oldContent: toHide.find('> *')
+                       },
+                       down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
+
+               this.active = clickedIsActive ? $([]) : clicked;
+               this._toggle(toShow, toHide, data, clickedIsActive, down);
+
+               return false;
+
+       },
+
+       _toggle: function(toShow, toHide, data, clickedIsActive, down) {
+
+               var o = this.options, self = this;
+
+               this.toShow = toShow;
+               this.toHide = toHide;
+               this.data = data;
+
+               var complete = function() { if(!self) return; return self._completed.apply(self, arguments); };
+
+               // trigger changestart event
+               this._trigger("changestart", null, this.data);
+
+               // count elements to animate
+               this.running = toHide.size() === 0 ? toShow.size() : toHide.size();
+
+               if (o.animated) {
+
+                       var animOptions = {};
+
+                       if ( o.collapsible && clickedIsActive ) {
+                               animOptions = {
+                                       toShow: $([]),
+                                       toHide: toHide,
+                                       complete: complete,
+                                       down: down,
+                                       autoHeight: o.autoHeight || o.fillSpace
+                               };
+                       } else {
+                               animOptions = {
+                                       toShow: toShow,
+                                       toHide: toHide,
+                                       complete: complete,
+                                       down: down,
+                                       autoHeight: o.autoHeight || o.fillSpace
+                               };
+                       }
+
+                       if (!o.proxied) {
+                               o.proxied = o.animated;
+                       }
+
+                       if (!o.proxiedDuration) {
+                               o.proxiedDuration = o.duration;
+                       }
+
+                       o.animated = $.isFunction(o.proxied) ?
+                               o.proxied(animOptions) : o.proxied;
+
+                       o.duration = $.isFunction(o.proxiedDuration) ?
+                               o.proxiedDuration(animOptions) : o.proxiedDuration;
+
+                       var animations = $.ui.accordion.animations,
+                               duration = o.duration,
+                               easing = o.animated;
+
+                       if (!animations[easing]) {
+                               animations[easing] = function(options) {
+                                       this.slide(options, {
+                                               easing: easing,
+                                               duration: duration || 700
+                                       });
+                               };
+                       }
+
+                       animations[easing](animOptions);
+
+               } else {
+
+                       if (o.collapsible && clickedIsActive) {
+                               toShow.toggle();
+                       } else {
+                               toHide.hide();
+                               toShow.show();
+                       }
+
+                       complete(true);
+
+               }
+
+               toHide.prev().attr('aria-expanded','false').attr("tabIndex", "-1").blur();
+               toShow.prev().attr('aria-expanded','true').attr("tabIndex", "0").focus();
+
+       },
+
+       _completed: function(cancel) {
+
+               var o = this.options;
+
+               this.running = cancel ? 0 : --this.running;
+               if (this.running) return;
+
+               if (o.clearStyle) {
+                       this.toShow.add(this.toHide).css({
+                               height: "",
+                               overflow: ""
+                       });
+               }
+
+               this._trigger('change', null, this.data);
+       }
+
+});
+
+
+$.extend($.ui.accordion, {
+       version: "1.7.1",
+       defaults: {
+               active: null,
+               alwaysOpen: true, //deprecated, use collapsible
+               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();
+               }
+       },
+       animations: {
+               slide: function(options, additions) {
+                       options = $.extend({
+                               easing: "swing",
+                               duration: 300
+                       }, options, additions);
+                       if ( !options.toHide.size() ) {
+                               options.toShow.animate({height: "show"}, options);
+                               return;
+                       }
+                       if ( !options.toShow.size() ) {
+                               options.toHide.animate({height: "hide"}, options);
+                               return;
+                       }
+                       var overflow = options.toShow.css('overflow'),
+                               percentDone,
+                               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( parseInt(s.parent().width(),10) - parseInt(s.css("paddingLeft"),10) - parseInt(s.css("paddingRight"),10) - (parseInt(s.css("borderLeftWidth"),10) || 0) - (parseInt(s.css("borderRightWidth"),10) || 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.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);
+                                       options.toShow.css({overflow: overflow});
+                                       options.complete();
+                               }
+                       });
+               },
+               bounceslide: function(options) {
+                       this.slide(options, {
+                               easing: options.down ? "easeOutBounce" : "swing",
+                               duration: options.down ? 1000 : 200
+                       });
+               },
+               easeslide: function(options) {
+                       this.slide(options, {
+                               easing: "easeinout",
+                               duration: 700
+                       });
+               }
+       }
+});
+
+})(jQuery);
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/ui.core.js b/js2/mwEmbed/jquery/jquery.ui/ui/ui.core.js
new file mode 100644 (file)
index 0000000..601d0a8
--- /dev/null
@@ -0,0 +1,519 @@
+/*
+ * jQuery UI 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI
+ */
+;jQuery.ui || (function($) {
+
+var _remove = $.fn.remove,
+       isFF2 = $.browser.mozilla && (parseFloat($.browser.version) < 1.9);
+
+//Helper functions and ui object
+$.ui = {
+       version: "1.7.1",
+
+       // $.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);
+                               }
+                       }
+               }
+       },
+
+       contains: function(a, b) {
+               return document.compareDocumentPosition
+                       ? a.compareDocumentPosition(b) & 16
+                       : a !== b && a.contains(b);
+       },
+
+       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;
+       },
+
+       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);
+       },
+
+       keyCode: {
+               BACKSPACE: 8,
+               CAPS_LOCK: 20,
+               COMMA: 188,
+               CONTROL: 17,
+               DELETE: 46,
+               DOWN: 40,
+               END: 35,
+               ENTER: 13,
+               ESCAPE: 27,
+               HOME: 36,
+               INSERT: 45,
+               LEFT: 37,
+               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
+       }
+};
+
+// WAI-ARIA normalization
+if (isFF2) {
+       var attr = $.attr,
+               removeAttr = $.fn.removeAttr,
+               ariaNS = "http://www.w3.org/2005/07/aaa",
+               ariaState = /^aria-/,
+               ariaRole = /^wairole:/;
+
+       $.attr = function(elem, name, value) {
+               var set = value !== undefined;
+
+               return (name == 'role'
+                       ? (set
+                               ? attr.call(this, elem, name, "wairole:" + value)
+                               : (attr.apply(this, arguments) || "").replace(ariaRole, ""))
+                       : (ariaState.test(name)
+                               ? (set
+                                       ? elem.setAttributeNS(ariaNS,
+                                               name.replace(ariaState, "aaa:"), value)
+                                       : attr.call(this, elem, name.replace(ariaState, "aaa:")))
+                               : attr.apply(this, arguments)));
+       };
+
+       $.fn.removeAttr = function(name) {
+               return (ariaState.test(name)
+                       ? this.each(function() {
+                               this.removeAttributeNS(ariaNS, name.replace(ariaState, ""));
+                       }) : removeAttr.call(this, name));
+       };
+}
+
+//jQuery plugins
+$.fn.extend({
+       remove: function() {
+               // Safari has a native remove event which actually removes DOM elements,
+               // so we have to use triggerHandler instead of trigger (#3037).
+               $("*", this).add(this).each(function() {
+                       $(this).triggerHandler("remove");
+               });
+               return _remove.apply(this, arguments );
+       },
+
+       enableSelection: function() {
+               return this
+                       .attr('unselectable', 'off')
+                       .css('MozUserSelect', '')
+                       .unbind('selectstart.ui');
+       },
+
+       disableSelection: function() {
+               return this
+                       .attr('unselectable', 'on')
+                       .css('MozUserSelect', 'none')
+                       .bind('selectstart.ui', function() { return false; });
+       },
+
+       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;
+       }
+});
+
+
+//Additional selectors
+$.extend($.expr[':'], {
+       data: function(elem, i, match) {
+               return !!$.data(elem, match[3]);
+       },
+
+       focusable: function(element) {
+               var nodeName = element.nodeName.toLowerCase(),
+                       tabIndex = $.attr(element, 'tabindex');
+               return (/input|select|textarea|button|object/.test(nodeName)
+                       ? !element.disabled
+                       : 'a' == nodeName || 'area' == nodeName
+                               ? element.href || !isNaN(tabIndex)
+                               : !isNaN(tabIndex))
+                       // the element and all of its ancestors must be visible
+                       // the browser may report that the area is hidden
+                       && !$(element)['area' == nodeName ? 'parents' : 'closest'](':hidden').length;
+       },
+
+       tabbable: function(element) {
+               var tabIndex = $.attr(element, 'tabindex');
+               return (isNaN(tabIndex) || tabIndex >= 0) && $(element).is(':focusable');
+       }
+});
+
+
+// $.widget is a factory to create jQuery plugins
+// taking some boilerplate code out of the plugin code
+function getter(namespace, plugin, method, args) {
+       function getMethods(type) {
+               var methods = $[namespace][plugin][type] || [];
+               return (typeof methods == 'string' ? methods.split(/,?\s+/) : methods);
+       }
+
+       var methods = getMethods('getter');
+       if (args.length == 1 && typeof args[0] == 'string') {
+               methods = methods.concat(getMethods('getterSetter'));
+       }
+       return ($.inArray(method, methods) != -1);
+}
+
+$.widget = function(name, prototype) {
+       var namespace = name.split(".")[0];
+       name = name.split(".")[1];
+
+       // create plugin method
+       $.fn[name] = function(options) {
+               var isMethodCall = (typeof options == 'string'),
+                       args = Array.prototype.slice.call(arguments, 1);
+
+               // prevent calls to internal methods
+               if (isMethodCall && options.substring(0, 1) == '_') {
+                       return this;
+               }
+
+               // handle getter methods
+               if (isMethodCall && getter(namespace, name, options, args)) {
+                       var instance = $.data(this[0], name);
+                       return (instance ? instance[options].apply(instance, args)
+                               : undefined);
+               }
+
+               // handle initialization and non-getter methods
+               return this.each(function() {
+                       var instance = $.data(this, name);
+
+                       // constructor
+                       (!instance && !isMethodCall &&
+                               $.data(this, name, new $[namespace][name](this, options))._init());
+
+                       // method call
+                       (instance && isMethodCall && $.isFunction(instance[options]) &&
+                               instance[options].apply(instance, args));
+               });
+       };
+
+       // create widget constructor
+       $[namespace] = $[namespace] || {};
+       $[namespace][name] = function(element, options) {
+               var self = this;
+
+               this.namespace = namespace;
+               this.widgetName = name;
+               this.widgetEventPrefix = $[namespace][name].eventPrefix || name;
+               this.widgetBaseClass = namespace + '-' + name;
+
+               this.options = $.extend({},
+                       $.widget.defaults,
+                       $[namespace][name].defaults,
+                       $.metadata && $.metadata.get(element)[name],
+                       options);
+
+               this.element = $(element)
+                       .bind('setData.' + name, function(event, key, value) {
+                               if (event.target == element) {
+                                       return self._setData(key, value);
+                               }
+                       })
+                       .bind('getData.' + name, function(event, key) {
+                               if (event.target == element) {
+                                       return self._getData(key);
+                               }
+                       })
+                       .bind('remove', function() {
+                               return self.destroy();
+                       });
+       };
+
+       // add widget prototype
+       $[namespace][name].prototype = $.extend({}, $.widget.prototype, prototype);
+
+       // TODO: merge getter and getterSetter properties from widget prototype
+       // and plugin prototype
+       $[namespace][name].getterSetter = 'option';
+};
+
+$.widget.prototype = {
+       _init: function() {},
+       destroy: function() {
+               this.element.removeData(this.widgetName)
+                       .removeClass(this.widgetBaseClass + '-disabled' + ' ' + this.namespace + '-state-disabled')
+                       .removeAttr('aria-disabled');
+       },
+
+       option: function(key, value) {
+               var options = key,
+                       self = this;
+
+               if (typeof key == "string") {
+                       if (value === undefined) {
+                               return this._getData(key);
+                       }
+                       options = {};
+                       options[key] = value;
+               }
+
+               $.each(options, function(key, value) {
+                       self._setData(key, value);
+               });
+       },
+       _getData: function(key) {
+               return this.options[key];
+       },
+       _setData: function(key, value) {
+               this.options[key] = value;
+
+               if (key == 'disabled') {
+                       this.element
+                               [value ? 'addClass' : 'removeClass'](
+                                       this.widgetBaseClass + '-disabled' + ' ' +
+                                       this.namespace + '-state-disabled')
+                               .attr("aria-disabled", value);
+               }
+       },
+
+       enable: function() {
+               this._setData('disabled', false);
+       },
+       disable: function() {
+               this._setData('disabled', true);
+       },
+
+       _trigger: function(type, event, data) {
+               var callback = this.options[type],
+                       eventName = (type == this.widgetEventPrefix
+                               ? type : this.widgetEventPrefix + type);
+
+               event = $.Event(event);
+               event.type = eventName;
+
+               // copy original event properties over to the new event
+               // this would happen if we could call $.event.fix instead of $.Event
+               // but we don't have a way to force an event to be fixed multiple times
+               if (event.originalEvent) {
+                       for (var i = $.event.props.length, prop; i;) {
+                               prop = $.event.props[--i];
+                               event[prop] = event.originalEvent[prop];
+                       }
+               }
+
+               this.element.trigger(event, data);
+
+               return !($.isFunction(callback) && callback.call(this.element[0], event, data) === false
+                       || event.isDefaultPrevented());
+       }
+};
+
+$.widget.defaults = {
+       disabled: false
+};
+
+
+/** Mouse Interaction Plugin **/
+
+$.ui.mouse = {
+       _mouseInit: function() {
+               var self = this;
+
+               this.element
+                       .bind('mousedown.'+this.widgetName, function(event) {
+                               return self._mouseDown(event);
+                       })
+                       .bind('click.'+this.widgetName, function(event) {
+                               if(self._preventClickEvent) {
+                                       self._preventClickEvent = false;
+                                       event.stopImmediatePropagation();
+                                       return false;
+                               }
+                       });
+
+               // Prevent text selection in IE
+               if ($.browser.msie) {
+                       this._mouseUnselectable = this.element.attr('unselectable');
+                       this.element.attr('unselectable', 'on');
+               }
+
+               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);
+
+               // Restore text selection in IE
+               ($.browser.msie
+                       && this.element.attr('unselectable', this._mouseUnselectable));
+       },
+
+       _mouseDown: function(event) {
+               // don't let more than one widget handle mouseStart
+               // TODO: figure out why we have to use originalEvent
+               event.originalEvent = event.originalEvent || {};
+               if (event.originalEvent.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),
+                       elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(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;
+                       }
+               }
+
+               // 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);
+
+               // preventDefault() is used to prevent the selection of text here -
+               // however, in Safari, this causes select boxes not to be selectable
+               // anymore, so this fix is needed
+               ($.browser.safari || event.preventDefault());
+
+               event.originalEvent.mouseHandled = true;
+               return true;
+       },
+
+       _mouseMove: function(event) {
+               // IE mouseup check - mouseup happened when mouse was out of window
+               if ($.browser.msie && !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;
+                       this._preventClickEvent = (event.target == this._mouseDownEvent.target);
+                       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; }
+};
+
+$.ui.mouse.defaults = {
+       cancel: null,
+       distance: 1,
+       delay: 0
+};
+
+})(jQuery);
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/ui.datepicker.js b/js2/mwEmbed/jquery/jquery.ui/ui/ui.datepicker.js
new file mode 100644 (file)
index 0000000..d3aa5c2
--- /dev/null
@@ -0,0 +1,1630 @@
+/*
+ * jQuery UI Datepicker 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Datepicker
+ *
+ * Depends:
+ *     ui.core.js
+ */
+
+(function($) { // hide the namespace
+
+$.extend($.ui, { datepicker: { version: "1.7.1" } });
+
+var PROP_NAME = 'datepicker';
+
+/* 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
+               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
+       };
+       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: 'show', // 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
+               showMonthAfterYear: false, // True if the year select precedes month, false for month then year
+               yearRange: '-10:+10', // Range of years to display in drop-down,
+                       // either relative to current year (-nn:+nn) or absolute (nnnn:nnnn)
+               showOtherMonths: false, // True to show dates in other months, false to leave blank
+               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: 'normal', // 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
+       };
+       $.extend(this._defaults, this.regional['']);
+       this.dpDiv = $('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>');
+}
+
+$.extend(Datepicker.prototype, {
+       /* Class name added to elements to indicate already configured with a date picker. */
+       markerClassName: 'hasDatepicker',
+
+       /* Debug logging (if enabled). */
+       log: function () {
+               if (this.debug)
+                       console.log.apply('', arguments);
+       },
+
+       /* 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)
+                       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(/([:\[\]\.])/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
+                       $('<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.trigger = $([]);
+               if (input.hasClass(this.markerClassName))
+                       return;
+               var appendText = this._get(inst, 'appendText');
+               var isRTL = this._get(inst, 'isRTL');
+               if (appendText)
+                       input[isRTL ? 'before' : 'after']('<span class="' + this._appendClass + '">' + appendText + '</span>');
+               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 == target)
+                                       $.datepicker._hideDatepicker();
+                               else
+                                       $.datepicker._showDatepicker(target);
+                               return false;
+                       });
+               }
+               input.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).
+                       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);
+       },
+
+       /* 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));
+               this._updateDatepicker(inst);
+               this._updateAlternate(inst);
+       },
+
+       /* Pop-up the date picker in a "dialog" box.
+          @param  input     element - ignored
+          @param  dateText  string - the initial date to display (in the current format)
+          @param  onSelect  function - the function(dateText) 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, dateText, onSelect, settings, pos) {
+               var inst = this._dialogInst; // internal instance
+               if (!inst) {
+                       var id = 'dp' + (++this.uuid);
+                       this._dialogInput = $('<input type="text" id="' + id +
+                               '" size="1" style="position: absolute; top: -100px;"/>');
+                       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 || {});
+               this._dialogInput.val(dateText);
+
+               this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
+               if (!this._pos) {
+                       var browserWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
+                       var browserHeight = window.innerHeight || document.documentElement.clientHeight || document.body.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] + '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.trigger.remove();
+                       $target.siblings('.' + this._appendClass).remove().end().
+                               removeClass(this.markerClassName).
+                               unbind('focus', this._showDatepicker).
+                               unbind('keydown', this._doKeyDown).
+                               unbind('keypress', this._doKeyPress);
+               } 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');
+               }
+               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');
+               }
+               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 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
+          @param  value   any - the new value for the setting (omit if above is an object) */
+       _optionDatepicker: function(target, name, value) {
+               var settings = name || {};
+               if (typeof name == 'string') {
+                       settings = {};
+                       settings[name] = value;
+               }
+               var inst = this._getInst(target);
+               if (inst) {
+                       if (this._curInst == inst) {
+                               this._hideDatepicker(null);
+                       }
+                       extendRemove(inst.settings, settings);
+                       var date = new Date();
+                       extendRemove(inst, {rangeStart: null, // start of range
+                               endDay: null, endMonth: null, endYear: null, // end of range
+                               selectedDay: date.getDate(), selectedMonth: date.getMonth(),
+                               selectedYear: date.getFullYear(), // starting point
+                               currentDay: date.getDate(), currentMonth: date.getMonth(),
+                               currentYear: date.getFullYear(), // current selection
+                               drawMonth: date.getMonth(), drawYear: date.getFullYear()}); // month being drawn
+                       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
+          @param  endDate  Date - the new end date for a range (optional) */
+       _setDateDatepicker: function(target, date, endDate) {
+               var inst = this._getInst(target);
+               if (inst) {
+                       this._setDate(inst, date, endDate);
+                       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
+          @return Date - the current date or
+                  Date[2] - the current dates for a range */
+       _getDateDatepicker: function(target) {
+               var inst = this._getInst(target);
+               if (inst && !inst.inline)
+                       this._setDateFromField(inst);
+               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(null, '');
+                                               break; // hide on tab out
+                               case 13: var sel = $('td.' + $.datepicker._dayOverClass +
+                                                       ', td.' + $.datepicker._currentClass, inst.dpDiv);
+                                               if (sel[0])
+                                                       $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
+                                               else
+                                                       $.datepicker._hideDatepicker(null, $.datepicker._get(inst, 'duration'));
+                                               return false; // don't submit the form
+                                               break; // select the value on enter
+                               case 27: $.datepicker._hideDatepicker(null, $.datepicker._get(inst, 'duration'));
+                                               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 || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
+               }
+       },
+
+       /* Pop-up the date picker for a given input field.
+          @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);
+               var beforeShow = $.datepicker._get(inst, 'beforeShow');
+               extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
+               $.datepicker._hideDatepicker(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;
+               inst.rangeStart = null;
+               // 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') || 'show';
+                       var duration = $.datepicker._get(inst, 'duration');
+                       var postProcess = function() {
+                               $.datepicker._datepickerShowing = true;
+                               if ($.browser.msie && parseInt($.browser.version,10) < 7) // fix IE < 7 select problems
+                                       $('iframe.ui-datepicker-cover').css({width: inst.dpDiv.width() + 4,
+                                               height: inst.dpDiv.height() + 4});
+                       };
+                       if ($.effects && $.effects[showAnim])
+                               inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
+                       else
+                               inst.dpDiv[showAnim](duration, postProcess);
+                       if (duration == '')
+                               postProcess();
+                       if (inst.input[0].type != 'hidden')
+                               inst.input[0].focus();
+                       $.datepicker._curInst = inst;
+               }
+       },
+
+       /* Generate the date picker content. */
+       _updateDatepicker: function(inst) {
+               var dims = {width: inst.dpDiv.width() + 4,
+                       height: inst.dpDiv.height() + 4};
+               var self = this;
+               inst.dpDiv.empty().append(this._generateHTML(inst))
+                       .find('iframe.ui-datepicker-cover').
+                               css({width: dims.width, height: dims.height})
+                       .end()
+                       .find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')
+                               .bind('mouseout', function(){
+                                       $(this).removeClass('ui-state-hover');
+                                       if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
+                                       if(this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
+                               })
+                               .bind('mouseover', function(){
+                                       if (!self._isDisabledDatepicker( inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) {
+                                               $(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
+                                               $(this).addClass('ui-state-hover');
+                                               if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
+                                               if(this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
+                                       }
+                               })
+                       .end()
+                       .find('.' + this._dayOverClass + ' a')
+                               .trigger('mouseover')
+                       .end();
+               var numMonths = this._getNumberOfMonths(inst);
+               var cols = numMonths[1];
+               var width = 17;
+               if (cols > 1) {
+                       inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
+               } else {
+                       inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
+               }
+               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.input && inst.input[0].type != 'hidden' && inst == $.datepicker._curInst)
+                       $(inst.input[0]).focus();
+       },
+
+       /* 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 = (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) + $(document).scrollLeft();
+               var viewHeight = (window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight) + $(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 -= (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? Math.abs(offset.left + dpWidth - viewWidth) : 0;
+               offset.top -= (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? Math.abs(offset.top + dpHeight + inputHeight*2 - viewHeight) : 0;
+
+               return offset;
+       },
+
+       /* Find an object's position on the screen. */
+       _findPos: function(obj) {
+        while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
+            obj = obj.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
+          @param  duration  string - the duration over which to close the date picker */
+       _hideDatepicker: function(input, duration) {
+               var inst = this._curInst;
+               if (!inst || (input && inst != $.data(input, PROP_NAME)))
+                       return;
+               if (inst.stayOpen)
+                       this._selectDate('#' + inst.id, this._formatDate(inst,
+                               inst.currentDay, inst.currentMonth, inst.currentYear));
+               inst.stayOpen = false;
+               if (this._datepickerShowing) {
+                       duration = (duration != null ? duration : this._get(inst, 'duration'));
+                       var showAnim = this._get(inst, 'showAnim');
+                       var postProcess = function() {
+                               $.datepicker._tidyDialog(inst);
+                       };
+                       if (duration != '' && $.effects && $.effects[showAnim])
+                               inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'),
+                                       duration, postProcess);
+                       else
+                               inst.dpDiv[(duration == '' ? 'hide' : (showAnim == 'slideDown' ? 'slideUp' :
+                                       (showAnim == 'fadeIn' ? 'fadeOut' : 'hide')))](duration, postProcess);
+                       if (duration == '')
+                               this._tidyDialog(inst);
+                       var onClose = this._get(inst, 'onClose');
+                       if (onClose)
+                               onClose.apply((inst.input ? inst.input[0] : null),
+                                       [(inst.input ? inst.input.val() : ''), inst]);  // trigger custom callback
+                       this._datepickerShowing = false;
+                       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;
+               }
+               this._curInst = null;
+       },
+
+       /* 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);
+               if (($target.parents('#' + $.datepicker._mainDivId).length == 0) &&
+                               !$target.hasClass($.datepicker.markerClassName) &&
+                               !$target.hasClass($.datepicker._triggerClass) &&
+                               $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
+                       $.datepicker._hideDatepicker(null, '');
+       },
+
+       /* 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._selectingMonthYear = false;
+               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);
+       },
+
+       /* Restore input focus after not changing month/year. */
+       _clickMonthYear: function(id) {
+               var target = $(id);
+               var inst = this._getInst(target[0]);
+               if (inst.input && inst._selectingMonthYear && !$.browser.msie)
+                       inst.input[0].focus();
+               inst._selectingMonthYear = !inst._selectingMonthYear;
+       },
+
+       /* 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;
+               if (inst.stayOpen) {
+                       inst.endDay = inst.endMonth = inst.endYear = null;
+               }
+               this._selectDate(id, this._formatDate(inst,
+                       inst.currentDay, inst.currentMonth, inst.currentYear));
+               if (inst.stayOpen) {
+                       inst.rangeStart = this._daylightSavingAdjust(
+                               new Date(inst.currentYear, inst.currentMonth, inst.currentDay));
+                       this._updateDatepicker(inst);
+               }
+       },
+
+       /* Erase the input field and hide the date picker. */
+       _clearDate: function(id) {
+               var target = $(id);
+               var inst = this._getInst(target[0]);
+               inst.stayOpen = false;
+               inst.endDay = inst.endMonth = inst.endYear = inst.rangeStart = null;
+               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 if (!inst.stayOpen) {
+                       this._hideDatepicker(null, this._get(inst, 'duration'));
+                       this._lastInput = inst.input[0];
+                       if (typeof(inst.input[0]) != 'object')
+                               inst.input[0].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);
+                       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.getFullYear(), date.getMonth(), date.getDate());
+               var firstMon = new Date(checkDate.getFullYear(), 1 - 1, 4); // First week always contains 4 Jan
+               var firstDay = firstMon.getDay() || 7; // Day of week: Mon = 1, ..., Sun = 7
+               firstMon.setDate(firstMon.getDate() + 1 - firstDay); // Preceding Monday
+               if (firstDay < 4 && checkDate < firstMon) { // Adjust first three days in year if necessary
+                       checkDate.setDate(checkDate.getDate() - 3); // Generate for previous year
+                       return $.datepicker.iso8601Week(checkDate);
+               } else if (checkDate > new Date(checkDate.getFullYear(), 12 - 1, 28)) { // Check last three days in year
+                       firstDay = new Date(checkDate.getFullYear() + 1, 1 - 1, 4).getDay() || 7;
+                       if (firstDay > 4 && (checkDate.getDay() || 7) < firstDay - 3) { // Adjust if necessary
+                               return 1;
+                       }
+               }
+               return Math.floor(((checkDate - firstMon) / 86400000) / 7) + 1; // Weeks to given date
+       },
+
+       /* 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;
+               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) {
+                       lookAhead(match);
+                       var origSize = (match == '@' ? 14 : (match == 'y' ? 4 : (match == 'o' ? 3 : 2)));
+                       var size = origSize;
+                       var num = 0;
+                       while (size > 0 && iValue < value.length &&
+                                       value.charAt(iValue) >= '0' && value.charAt(iValue) <= '9') {
+                               num = num * 10 + parseInt(value.charAt(iValue++),10);
+                               size--;
+                       }
+                       if (size == origSize)
+                               throw 'Missing number at position ' + iValue;
+                       return num;
+               };
+               // Extract a name from the string value and convert to an index
+               var getName = function(match, shortNames, longNames) {
+                       var names = (lookAhead(match) ? longNames : shortNames);
+                       var size = 0;
+                       for (var j = 0; j < names.length; j++)
+                               size = Math.max(size, names[j].length);
+                       var name = '';
+                       var iInit = iValue;
+                       while (size > 0 && iValue < value.length) {
+                               name += value.charAt(iValue++);
+                               for (var i = 0; i < names.length; i++)
+                                       if (name == names[i])
+                                               return i + 1;
+                               size--;
+                       }
+                       throw 'Unknown name at position ' + iInit;
+               };
+               // 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 "'":
+                                               if (lookAhead("'"))
+                                                       checkLiteral();
+                                               else
+                                                       literal = true;
+                                               break;
+                                       default:
+                                               checkLiteral();
+                               }
+               }
+               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/*
+               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
+       TIMESTAMP: '@',
+       W3C: 'yy-mm-dd', // ISO 8601
+
+       /* 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)
+          '...' - 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':
+                                                       var doy = date.getDate();
+                                                       for (var m = date.getMonth() - 1; m >= 0; m--)
+                                                               doy += this._getDaysInMonth(date.getFullYear(), m);
+                                                       output += formatNumber('o', doy, 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 "'":
+                                                       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;
+               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) {
+               var dateFormat = this._get(inst, 'dateFormat');
+               var dates = inst.input ? inst.input.val() : null;
+               inst.endDay = inst.endMonth = inst.endYear = null;
+               var date = defaultDate = this._getDefaultDate(inst);
+               var settings = this._getFormatConfig(inst);
+               try {
+                       date = this.parseDate(dateFormat, dates, settings) || defaultDate;
+               } catch (event) {
+                       this.log(event);
+                       date = defaultDate;
+               }
+               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) {
+               var date = this._determineDate(this._get(inst, 'defaultDate'), new Date());
+               var minDate = this._getMinMaxDate(inst, 'min', true);
+               var maxDate = this._getMinMaxDate(inst, 'max');
+               date = (minDate && date < minDate ? minDate : date);
+               date = (maxDate && date > maxDate ? maxDate : date);
+               return date;
+       },
+
+       /* A date may be specified as an exact value or a relative one. */
+       _determineDate: function(date, defaultDate) {
+               var offsetNumeric = function(offset) {
+                       var date = new Date();
+                       date.setDate(date.getDate() + offset);
+                       return date;
+               };
+               var offsetString = function(offset, getDaysInMonth) {
+                       var date = 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, getDaysInMonth(year, month));
+                                               break;
+                                       case 'y': case 'Y' :
+                                               year += parseInt(matches[1],10);
+                                               day = Math.min(day, getDaysInMonth(year, month));
+                                               break;
+                               }
+                               matches = pattern.exec(offset);
+                       }
+                       return new Date(year, month, day);
+               };
+               date = (date == null ? defaultDate :
+                       (typeof date == 'string' ? offsetString(date, this._getDaysInMonth) :
+                       (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : date)));
+               date = (date && date.toString() == 'Invalid Date' ? defaultDate : date);
+               if (date) {
+                       date.setHours(0);
+                       date.setMinutes(0);
+                       date.setSeconds(0);
+                       date.setMilliseconds(0);
+               }
+               return this._daylightSavingAdjust(date);
+       },
+
+       /* 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, endDate) {
+               var clear = !(date);
+               var origMonth = inst.selectedMonth;
+               var origYear = inst.selectedYear;
+               date = this._determineDate(date, new Date());
+               inst.selectedDay = inst.currentDay = date.getDate();
+               inst.drawMonth = inst.selectedMonth = inst.currentMonth = date.getMonth();
+               inst.drawYear = inst.selectedYear = inst.currentYear = date.getFullYear();
+               if (origMonth != inst.selectedMonth || origYear != inst.selectedYear)
+                       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;
+       },
+
+       /* 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 stepBigMonths = this._get(inst, 'stepBigMonths');
+               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', true);
+               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[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" onclick="DP_jQuery.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
+                       ' 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" onclick="DP_jQuery.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
+                       ' 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" onclick="DP_jQuery.datepicker._hideDatepicker();">' + 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" onclick="DP_jQuery.datepicker._gotoToday(\'#' + inst.id + '\');"' +
+                       '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
+               var firstDay = parseInt(this._get(inst, 'firstDay'),10);
+               firstDay = (isNaN(firstDay) ? 0 : firstDay);
+               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 calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
+               var endDate = inst.endDay ? this._daylightSavingAdjust(
+                       new Date(inst.endYear, inst.endMonth, inst.endDay)) : currentDate;
+               var defaultDate = this._getDefaultDate(inst);
+               var html = '';
+               for (var row = 0; row < numMonths[0]; row++) {
+                       var group = '';
+                       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 ui-datepicker-group-';
+                                       switch (col) {
+                                               case 0: calender += 'first'; cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
+                                               case numMonths[1]-1: calender += 'last'; cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
+                                               default: calender += '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,
+                                       selectedDate, row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
+                                       '</div><table class="ui-datepicker-calendar"><thead>' +
+                                       '<tr>';
+                               var thead = '';
+                               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 numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
+                               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 = '';
+                                       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 || !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() && printDate.getTime() <= endDate.getTime() ? // in current range
+                                                       ' ' + 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 ? '' : ' onclick="DP_jQuery.datepicker._selectDay(\'#' +
+                                                       inst.id + '\',' + drawMonth + ',' + drawYear + ', this);return false;"') + '>' + // actions
+                                                       (otherMonth ? (showOtherMonths ? printDate.getDate() : '&#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() && printDate.getTime() <= endDate.getTime() ? // in current range
+                                                       ' ui-state-active' : '') + // highlight selected day
+                                                       '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display for this month
+                                               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,
+                       selectedDate, secondary, monthNames, monthNamesShort) {
+               minDate = (inst.rangeStart && minDate && selectedDate < minDate ? selectedDate : minDate);
+               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" ' +
+                               'onchange="DP_jQuery.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
+                               'onclick="DP_jQuery.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
+                               '>';
+                       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) && (!(changeMonth && changeYear)) ? '&#xa0;' : '');
+               // year selection
+               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 year = 0;
+                       var endYear = 0;
+                       if (years.length != 2) {
+                               year = drawYear - 10;
+                               endYear = drawYear + 10;
+                       } else if (years[0].charAt(0) == '+' || years[0].charAt(0) == '-') {
+                               year = drawYear + parseInt(years[0], 10);
+                               endYear = drawYear + parseInt(years[1], 10);
+                       } else {
+                               year = parseInt(years[0], 10);
+                               endYear = parseInt(years[1], 10);
+                       }
+                       year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
+                       endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
+                       html += '<select class="ui-datepicker-year" ' +
+                               'onchange="DP_jQuery.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
+                               'onclick="DP_jQuery.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
+                               '>';
+                       for (; year <= endYear; year++) {
+                               html += '<option value="' + year + '"' +
+                                       (year == drawYear ? ' selected="selected"' : '') +
+                                       '>' + year + '</option>';
+                       }
+                       html += '</select>';
+               }
+               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._daylightSavingAdjust(new Date(year, month, day));
+               // ensure it is within the bounds set
+               var minDate = this._getMinMaxDate(inst, 'min', true);
+               var maxDate = this._getMinMaxDate(inst, 'max');
+               date = (minDate && date < minDate ? minDate : date);
+               date = (maxDate && date > maxDate ? maxDate : date);
+               inst.selectedDay = date.getDate();
+               inst.drawMonth = inst.selectedMonth = date.getMonth();
+               inst.drawYear = inst.selectedYear = date.getFullYear();
+               if (period == 'M' || period == 'Y')
+                       this._notifyChange(inst);
+       },
+
+       /* 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 - may be overridden for a range. */
+       _getMinMaxDate: function(inst, minMax, checkRange) {
+               var date = this._determineDate(this._get(inst, minMax + 'Date'), null);
+               return (!checkRange || !inst.rangeStart ? date :
+                       (!date || inst.rangeStart > date ? inst.rangeStart : date));
+       },
+
+       /* Find the number of days in a given month. */
+       _getDaysInMonth: function(year, month) {
+               return 32 - 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[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) {
+               // during range selection, use minimum of selected date and range start
+               var newMinDate = (!inst.rangeStart ? null : this._daylightSavingAdjust(
+                       new Date(inst.selectedYear, inst.selectedMonth, inst.selectedDay)));
+               newMinDate = (newMinDate && inst.rangeStart < newMinDate ? inst.rangeStart : newMinDate);
+               var minDate = newMinDate || this._getMinMaxDate(inst, 'min');
+               var maxDate = this._getMinMaxDate(inst, 'max');
+               return ((!minDate || date >= minDate) && (!maxDate || date <= maxDate));
+       },
+
+       /* 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));
+       }
+});
+
+/* 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){
+
+       /* 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'))
+               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.7.1";
+
+// Workaround for #4055
+// Add another global to avoid noConflict issues with inline event handlers
+window.DP_jQuery = $;
+
+})(jQuery);
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/ui.dialog.js b/js2/mwEmbed/jquery/jquery.ui/ui/ui.dialog.js
new file mode 100644 (file)
index 0000000..9f4f5e5
--- /dev/null
@@ -0,0 +1,650 @@
+/*
+ * jQuery UI Dialog 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Dialog
+ *
+ * Depends:
+ *     ui.core.js
+ *     ui.draggable.js
+ *     ui.resizable.js
+ */
+(function($) {
+
+var setDataSwitch = {
+               dragStart       : "start.draggable",
+               drag            : "drag.draggable",
+               dragStop        : "stop.draggable",
+               maxHeight       : "maxHeight.resizable",
+               minHeight       : "minHeight.resizable",
+               maxWidth        : "maxWidth.resizable",
+               minWidth        : "minWidth.resizable",
+               resizeStart     : "start.resizable",
+               resize          : "drag.resizable",
+               resizeStop      : "stop.resizable"
+       },
+       
+       uiDialogClasses =
+               'ui-dialog ' +
+               'ui-widget ' +
+               'ui-widget-content ' +
+               'ui-corner-all ';
+
+$.widget("ui.dialog", {
+
+       _init: function() {
+               this.originalTitle = this.element.attr('title');
+
+               var self = this,
+                       options = this.options,
+
+                       title = options.title || this.originalTitle || '&nbsp;',
+                       titleId = $.ui.dialog.getTitleId(this.element),
+
+                       uiDialog = (this.uiDialog = $('<div/>'))
+                               .appendTo(document.body)
+                               .hide()
+                               .addClass(uiDialogClasses + options.dialogClass)
+                               .css({
+                                       position: 'absolute',
+                                       overflow: 'hidden',
+                                       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) {
+                                       (options.closeOnEscape && event.keyCode
+                                               && event.keyCode == $.ui.keyCode.ESCAPE && self.close(event));
+                               })
+                               .attr({
+                                       role: 'dialog',
+                                       'aria-labelledby': titleId
+                               })
+                               .mousedown(function(event) {
+                                       self.moveToTop(false, event);
+                               }),
+
+                       uiDialogContent = this.element
+                               .show()
+                               .removeAttr('title')
+                               .addClass(
+                                       'ui-dialog-content ' +
+                                       'ui-widget-content')
+                               .appendTo(uiDialog),
+
+                       uiDialogTitlebar = (this.uiDialogTitlebar = $('<div></div>'))
+                               .addClass(
+                                       'ui-dialog-titlebar ' +
+                                       'ui-widget-header ' +
+                                       'ui-corner-all ' +
+                                       'ui-helper-clearfix'
+                               )
+                               .prependTo(uiDialog),
+
+                       uiDialogTitlebarClose = $('<a href="#"/>')
+                               .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');
+                               })
+                               .mousedown(function(ev) {
+                                       ev.stopPropagation();
+                               })
+                               .click(function(event) {
+                                       self.close(event);
+                                       return false;
+                               })
+                               .appendTo(uiDialogTitlebar),
+
+                       uiDialogTitlebarCloseText = (this.uiDialogTitlebarCloseText = $('<span/>'))
+                               .addClass(
+                                       'ui-icon ' +
+                                       'ui-icon-closethick'
+                               )
+                               .text(options.closeText)
+                               .appendTo(uiDialogTitlebarClose),
+
+                       uiDialogTitle = $('<span/>')
+                               .addClass('ui-dialog-title')
+                               .attr('id', titleId)
+                               .html(title)
+                               .prependTo(uiDialogTitlebar);
+
+               uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
+
+               (options.draggable && $.fn.draggable && this._makeDraggable());
+               (options.resizable && $.fn.resizable && this._makeResizable());
+
+               this._createButtons(options.buttons);
+               this._isOpen = false;
+
+               (options.bgiframe && $.fn.bgiframe && uiDialog.bgiframe());
+               (options.autoOpen && this.open());
+               
+       },
+
+       destroy: function() {
+               (this.overlay && this.overlay.destroy());
+               this.uiDialog.hide();
+               this.element
+                       .unbind('.dialog')
+                       .removeData('dialog')
+                       .removeClass('ui-dialog-content ui-widget-content')
+                       .hide().appendTo('body');
+               this.uiDialog.remove();
+
+               (this.originalTitle && this.element.attr('title', this.originalTitle));
+       },
+
+       close: function(event) {
+               var self = this;
+               
+               if (false === self._trigger('beforeclose', event)) {
+                       return;
+               }
+
+               (self.overlay && self.overlay.destroy());
+               self.uiDialog.unbind('keypress.ui-dialog');
+
+               (self.options.hide
+                       ? self.uiDialog.hide(self.options.hide, function() {
+                               self._trigger('close', event);
+                       })
+                       : self.uiDialog.hide() && self._trigger('close', event));
+
+               $.ui.dialog.overlay.resize();
+
+               self._isOpen = false;
+       },
+
+       isOpen: function() {
+               return this._isOpen;
+       },
+
+       // the force parameter allows us to move modal dialogs to their correct
+       // position on open
+       moveToTop: function(force, event) {
+
+               if ((this.options.modal && !force)
+                       || (!this.options.stack && !this.options.modal)) {
+                       return this._trigger('focus', event);
+               }
+               
+               if (this.options.zIndex > $.ui.dialog.maxZ) {
+                       $.ui.dialog.maxZ = this.options.zIndex;
+               }
+               (this.overlay && this.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
+               var saveScroll = { scrollTop: this.element.attr('scrollTop'), scrollLeft: this.element.attr('scrollLeft') };
+               this.uiDialog.css('z-index', ++$.ui.dialog.maxZ);
+               this.element.attr(saveScroll);
+               this._trigger('focus', event);
+       },
+
+       open: function() {
+               if (this._isOpen) { return; }
+
+               var options = this.options,
+                       uiDialog = this.uiDialog;
+
+               this.overlay = options.modal ? new $.ui.dialog.overlay(this) : null;
+               (uiDialog.next().length && uiDialog.appendTo('body'));
+               this._size();
+               this._position(options.position);
+               uiDialog.show(options.show);
+               this.moveToTop(true);
+
+               // prevent tabbing out of modal dialogs
+               (options.modal && uiDialog.bind('keypress.ui-dialog', function(event) {
+                       if (event.keyCode != $.ui.keyCode.TAB) {
+                               return;
+                       }
+
+                       var tabbables = $(':tabbable', this),
+                               first = tabbables.filter(':first')[0],
+                               last  = tabbables.filter(':last')[0];
+
+                       if (event.target == last && !event.shiftKey) {
+                               setTimeout(function() {
+                                       first.focus();
+                               }, 1);
+                       } else if (event.target == first && event.shiftKey) {
+                               setTimeout(function() {
+                                       last.focus();
+                               }, 1);
+                       }
+               }));
+
+               // 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
+               $([])
+                       .add(uiDialog.find('.ui-dialog-content :tabbable:first'))
+                       .add(uiDialog.find('.ui-dialog-buttonpane :tabbable:first'))
+                       .add(uiDialog)
+                       .filter(':first')
+                       .focus();
+
+               this._trigger('open');
+               this._isOpen = true;
+       },
+
+       _createButtons: function(buttons) {
+               var self = this,
+                       hasButtons = false,
+                       uiDialogButtonPane = $('<div></div>')
+                               .addClass(
+                                       'ui-dialog-buttonpane ' +
+                                       'ui-widget-content ' +
+                                       'ui-helper-clearfix'
+                               );
+
+               // if we already have a button pane, remove it
+               this.uiDialog.find('.ui-dialog-buttonpane').remove();
+
+               (typeof buttons == 'object' && buttons !== null &&
+                       $.each(buttons, function() { return !(hasButtons = true); }));
+               if (hasButtons) {
+                       $.each(buttons, function(name, fn) {
+                               $('<button type="button"></button>')
+                                       .addClass(
+                                               'ui-state-default ' +
+                                               'ui-corner-all'
+                                       )
+                                       .text(name)
+                                       .click(function() { fn.apply(self.element[0], arguments); })
+                                       .hover(
+                                               function() {
+                                                       $(this).addClass('ui-state-hover');
+                                               },
+                                               function() {
+                                                       $(this).removeClass('ui-state-hover');
+                                               }
+                                       )
+                                       .focus(function() {
+                                               $(this).addClass('ui-state-focus');
+                                       })
+                                       .blur(function() {
+                                               $(this).removeClass('ui-state-focus');
+                                       })
+                                       .appendTo(uiDialogButtonPane);
+                       });
+                       uiDialogButtonPane.appendTo(this.uiDialog);
+               }
+       },
+
+       _makeDraggable: function() {
+               var self = this,
+                       options = this.options,
+                       heightBeforeDrag;
+
+               this.uiDialog.draggable({
+                       cancel: '.ui-dialog-content',
+                       handle: '.ui-dialog-titlebar',
+                       containment: 'document',
+                       start: function() {
+                               heightBeforeDrag = options.height;
+                               $(this).height($(this).height()).addClass("ui-dialog-dragging");
+                               (options.dragStart && options.dragStart.apply(self.element[0], arguments));
+                       },
+                       drag: function() {
+                               (options.drag && options.drag.apply(self.element[0], arguments));
+                       },
+                       stop: function() {
+                               $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
+                               (options.dragStop && options.dragStop.apply(self.element[0], arguments));
+                               $.ui.dialog.overlay.resize();
+                       }
+               });
+       },
+
+       _makeResizable: function(handles) {
+               handles = (handles === undefined ? this.options.resizable : handles);
+               var self = this,
+                       options = this.options,
+                       resizeHandles = typeof handles == 'string'
+                               ? handles
+                               : 'n,e,s,w,se,sw,ne,nw';
+
+               this.uiDialog.resizable({
+                       cancel: '.ui-dialog-content',
+                       alsoResize: this.element,
+                       maxWidth: options.maxWidth,
+                       maxHeight: options.maxHeight,
+                       minWidth: options.minWidth,
+                       minHeight: options.minHeight,
+                       start: function() {
+                               $(this).addClass("ui-dialog-resizing");
+                               (options.resizeStart && options.resizeStart.apply(self.element[0], arguments));
+                       },
+                       resize: function() {
+                               (options.resize && options.resize.apply(self.element[0], arguments));
+                       },
+                       handles: resizeHandles,
+                       stop: function() {
+                               $(this).removeClass("ui-dialog-resizing");
+                               options.height = $(this).height();
+                               options.width = $(this).width();
+                               (options.resizeStop && options.resizeStop.apply(self.element[0], arguments));
+                               $.ui.dialog.overlay.resize();
+                       }
+               })
+               .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
+       },
+
+       _position: function(pos) {
+               var wnd = $(window), doc = $(document),
+                       pTop = doc.scrollTop(), pLeft = doc.scrollLeft(),
+                       minTop = pTop;
+
+               if ($.inArray(pos, ['center','top','right','bottom','left']) >= 0) {
+                       pos = [
+                               pos == 'right' || pos == 'left' ? pos : 'center',
+                               pos == 'top' || pos == 'bottom' ? pos : 'middle'
+                       ];
+               }
+               if (pos.constructor != Array) {
+                       pos = ['center', 'middle'];
+               }
+               if (pos[0].constructor == Number) {
+                       pLeft += pos[0];
+               } else {
+                       switch (pos[0]) {
+                               case 'left':
+                                       pLeft += 0;
+                                       break;
+                               case 'right':
+                                       pLeft += wnd.width() - this.uiDialog.outerWidth();
+                                       break;
+                               default:
+                               case 'center':
+                                       pLeft += (wnd.width() - this.uiDialog.outerWidth()) / 2;
+                       }
+               }
+               if (pos[1].constructor == Number) {
+                       pTop += pos[1];
+               } else {
+                       switch (pos[1]) {
+                               case 'top':
+                                       pTop += 0;
+                                       break;
+                               case 'bottom':
+                                       pTop += wnd.height() - this.uiDialog.outerHeight();
+                                       break;
+                               default:
+                               case 'middle':
+                                       pTop += (wnd.height() - this.uiDialog.outerHeight()) / 2;
+                       }
+               }
+
+               // prevent the dialog from being too high (make sure the titlebar
+               // is accessible)
+               pTop = Math.max(pTop, minTop);
+               this.uiDialog.css({top: pTop, left: pLeft});
+       },
+
+       _setData: function(key, value){
+               (setDataSwitch[key] && this.uiDialog.data(setDataSwitch[key], value));
+               switch (key) {
+                       case "buttons":
+                               this._createButtons(value);
+                               break;
+                       case "closeText":
+                               this.uiDialogTitlebarCloseText.text(value);
+                               break;
+                       case "dialogClass":
+                               this.uiDialog
+                                       .removeClass(this.options.dialogClass)
+                                       .addClass(uiDialogClasses + value);
+                               break;
+                       case "draggable":
+                               (value
+                                       ? this._makeDraggable()
+                                       : this.uiDialog.draggable('destroy'));
+                               break;
+                       case "height":
+                               this.uiDialog.height(value);
+                               break;
+                       case "position":
+                               this._position(value);
+                               break;
+                       case "resizable":
+                               var uiDialog = this.uiDialog,
+                                       isResizable = this.uiDialog.is(':data(resizable)');
+
+                               // currently resizable, becoming non-resizable
+                               (isResizable && !value && uiDialog.resizable('destroy'));
+
+                               // currently resizable, changing handles
+                               (isResizable && typeof value == 'string' &&
+                                       uiDialog.resizable('option', 'handles', value));
+
+                               // currently non-resizable, becoming resizable
+                               (isResizable || this._makeResizable(value));
+                               break;
+                       case "title":
+                               $(".ui-dialog-title", this.uiDialogTitlebar).html(value || '&nbsp;');
+                               break;
+                       case "width":
+                               this.uiDialog.width(value);
+                               break;
+               }
+
+               $.widget.prototype._setData.apply(this, 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;
+
+               // reset content sizing
+               this.element.css({
+                       height: 0,
+                       minHeight: 0,
+                       width: 'auto'
+               });
+
+               // reset wrapper sizing
+               // determine the height of all the non-content elements
+               var nonContentHeight = this.uiDialog.css({
+                               height: 'auto',
+                               width: options.width
+                       })
+                       .height();
+
+               this.element
+                       .css({
+                               minHeight: Math.max(options.minHeight - nonContentHeight, 0),
+                               height: options.height == 'auto'
+                                       ? 'auto'
+                                       : Math.max(options.height - nonContentHeight, 0)
+                       });
+       }
+});
+
+$.extend($.ui.dialog, {
+       version: "1.7.1",
+       defaults: {
+               autoOpen: true,
+               bgiframe: false,
+               buttons: {},
+               closeOnEscape: true,
+               closeText: 'close',
+               dialogClass: '',
+               draggable: true,
+               hide: null,
+               height: 'auto',
+               maxHeight: false,
+               maxWidth: false,
+               minHeight: 150,
+               minWidth: 150,
+               modal: false,
+               position: 'center',
+               resizable: true,
+               show: null,
+               stack: true,
+               title: '',
+               width: 300,
+               zIndex: 1000
+       },
+
+       getter: 'isOpen',
+
+       uuid: 0,
+       maxZ: 0,
+
+       getTitleId: function($el) {
+               return 'ui-dialog-title-' + ($el.attr('id') || ++this.uuid);
+       },
+
+       overlay: function(dialog) {
+               this.$el = $.ui.dialog.overlay.create(dialog);
+       }
+});
+
+$.extend($.ui.dialog.overlay, {
+       instances: [],
+       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() {
+                               $(document).bind($.ui.dialog.overlay.events, function(event) {
+                                       var dialogZ = $(event.target).parents('.ui-dialog').css('zIndex') || 0;
+                                       return (dialogZ > $.ui.dialog.overlay.maxZ);
+                               });
+                       }, 1);
+
+                       // allow closing by pressing the escape key
+                       $(document).bind('keydown.dialog-overlay', function(event) {
+                               (dialog.options.closeOnEscape && event.keyCode
+                                               && event.keyCode == $.ui.keyCode.ESCAPE && dialog.close(event));
+                       });
+
+                       // handle window resize
+                       $(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
+               }
+
+               var $el = $('<div></div>').appendTo(document.body)
+                       .addClass('ui-widget-overlay').css({
+                               width: this.width(),
+                               height: this.height()
+                       });
+
+               (dialog.options.bgiframe && $.fn.bgiframe && $el.bgiframe());
+
+               this.instances.push($el);
+               return $el;
+       },
+
+       destroy: function($el) {
+               this.instances.splice($.inArray(this.instances, $el), 1);
+
+               if (this.instances.length === 0) {
+                       $([document, window]).unbind('.dialog-overlay');
+               }
+
+               $el.remove();
+       },
+
+       height: function() {
+               // handle IE 6
+               if ($.browser.msie && $.browser.version < 7) {
+                       var scrollHeight = Math.max(
+                               document.documentElement.scrollHeight,
+                               document.body.scrollHeight
+                       );
+                       var 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() {
+               // handle IE 6
+               if ($.browser.msie && $.browser.version < 7) {
+                       var scrollWidth = Math.max(
+                               document.documentElement.scrollWidth,
+                               document.body.scrollWidth
+                       );
+                       var 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/js2/mwEmbed/jquery/jquery.ui/ui/ui.draggable.js b/js2/mwEmbed/jquery/jquery.ui/ui/ui.draggable.js
new file mode 100644 (file)
index 0000000..e07d1c8
--- /dev/null
@@ -0,0 +1,766 @@
+/*
+ * jQuery UI Draggable 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Draggables
+ *
+ * Depends:
+ *     ui.core.js
+ */
+(function($) {
+
+$.widget("ui.draggable", $.extend({}, $.ui.mouse, {
+
+       _init: 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();
+       },
+
+       _mouseCapture: function(event) {
+
+               var o = this.options;
+
+               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;
+
+               return true;
+
+       },
+
+       _mouseStart: function(event) {
+
+               var o = this.options;
+
+               //Create and append the visible helper
+               this.helper = this._createHelper(event);
+
+               //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.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._generatePosition(event);
+               this.originalPageX = event.pageX;
+               this.originalPageY = event.pageY;
+
+               //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
+               if(o.cursorAt)
+                       this._adjustOffsetFromHelper(o.cursorAt);
+
+               //Set a containment if given in the options
+               if(o.containment)
+                       this._setContainment();
+
+               //Call plugins and callbacks
+               this._trigger("start", event);
+
+               //Recache the helper size
+               this._cacheHelperProportions();
+
+               //Prepare the droppable offsets
+               if ($.ui.ddmanager && !o.dropBehaviour)
+                       $.ui.ddmanager.prepareOffsets(this, event);
+
+               this.helper.addClass("ui-draggable-dragging");
+               this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
+               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();
+                       this._trigger('drag', event, ui);
+                       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((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() {
+                               self._trigger("stop", event);
+                               self._clear();
+                       });
+               } else {
+                       this._trigger("stop", event);
+                       this._clear();
+               }
+
+               return false;
+       },
+
+       _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() : 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(obj.left != undefined) this.offset.click.left = obj.left + this.margins.left;
+               if(obj.right != undefined) this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
+               if(obj.top != undefined) this.offset.click.top = obj.top + this.margins.top;
+               if(obj.bottom != undefined) 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)
+               };
+       },
+
+       _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) && o.containment.constructor != Array) {
+                       var ce = $(o.containment)[0]; if(!ce) return;
+                       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
+                       ];
+               } 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 && 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() ))
+                       )
+               };
+
+       },
+
+       _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,
+                       absolutePosition: this.positionAbs, //deprecated
+                       offset: this.positionAbs
+               };
+       }
+
+}));
+
+$.extend($.ui.draggable, {
+       version: "1.7.1",
+       eventPrefix: "drag",
+       defaults: {
+               addClasses: true,
+               appendTo: "parent",
+               axis: false,
+               cancel: ":input,option",
+               connectToSortable: false,
+               containment: false,
+               cursor: "auto",
+               cursorAt: false,
+               delay: 0,
+               distance: 1,
+               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
+       }
+});
+
+$.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._refreshItems();       //Do a one-time refresh at start to refresh the containerCache
+                               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().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", "iframeFix", {
+       start: function(event, ui) {
+               var o = $(this).data('draggable').options;
+               $(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");
+               });
+       },
+       stop: function(event, ui) {
+               $("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers
+       }
+});
+
+$.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.group)).sort(function(a,b) {
+                       return (parseInt($(a).css("zIndex"),10) || o.stack.min) - (parseInt($(b).css("zIndex"),10) || o.stack.min);
+               });
+
+               $(group).each(function(i) {
+                       this.style.zIndex = o.stack.min + i;
+               });
+
+               this[0].style.zIndex = o.stack.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/js2/mwEmbed/jquery/jquery.ui/ui/ui.droppable.js b/js2/mwEmbed/jquery/jquery.ui/ui/ui.droppable.js
new file mode 100644 (file)
index 0000000..22fcbaf
--- /dev/null
@@ -0,0 +1,282 @@
+/*
+ * jQuery UI Droppable 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Droppables
+ *
+ * Depends:
+ *     ui.core.js
+ *     ui.draggable.js
+ */
+(function($) {
+
+$.widget("ui.droppable", {
+
+       _init: function() {
+
+               var o = this.options, accept = o.accept;
+               this.isover = 0; this.isout = 1;
+
+               this.options.accept = this.options.accept && $.isFunction(this.options.accept) ? this.options.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[this.options.scope] = $.ui.ddmanager.droppables[this.options.scope] || [];
+               $.ui.ddmanager.droppables[this.options.scope].push(this);
+
+               (this.options.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");
+       },
+
+       _setData: function(key, value) {
+
+               if(key == 'accept') {
+                       this.options.accept = value && $.isFunction(value) ? value : function(d) {
+                               return d.is(value);
+                       };
+               } else {
+                       $.widget.prototype._setData.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.options.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.options.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 && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)) {
+                               childrenIntersection = true; return false;
+                       }
+               });
+               if(childrenIntersection) return false;
+
+               if(this.options.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,
+                       absolutePosition: c.positionAbs, //deprecated
+                       offset: c.positionAbs
+               };
+       }
+
+});
+
+$.extend($.ui.droppable, {
+       version: "1.7.1",
+       eventPrefix: 'drop',
+       defaults: {
+               accept: '*',
+               activeClass: false,
+               addClasses: true,
+               greedy: false,
+               hoverClass: false,
+               scope: 'default',
+               tolerance: 'intersect'
+       }
+});
+
+$.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].options.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
+
+                       m[i].offset = m[i].element.offset();
+                       m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
+
+                       if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
+
+               }
+
+       },
+       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);
+
+                       if (!this.options.disabled && this.visible && this.options.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
+                               this.isout = 1; this.isover = 0;
+                               this._deactivate.call(this, event);
+                       }
+
+               });
+               return dropped;
+
+       },
+       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) {
+                               var parent = this.element.parents(':data(droppable):eq(0)');
+                               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);
+                       }
+               });
+
+       }
+};
+
+})(jQuery);
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/ui.progressbar.js b/js2/mwEmbed/jquery/jquery.ui/ui/ui.progressbar.js
new file mode 100644 (file)
index 0000000..e69b225
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * jQuery UI Progressbar 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Progressbar
+ *
+ * Depends:
+ *   ui.core.js
+ */
+(function($) {
+
+$.widget("ui.progressbar", {
+
+       _init: function() {
+
+               this.element
+                       .addClass("ui-progressbar"
+                               + " ui-widget"
+                               + " ui-widget-content"
+                               + " ui-corner-all")
+                       .attr({
+                               role: "progressbar",
+                               "aria-valuemin": this._valueMin(),
+                               "aria-valuemax": this._valueMax(),
+                               "aria-valuenow": this._value()
+                       });
+
+               this.valueDiv = $('<div class="ui-progressbar-value ui-widget-header ui-corner-left"></div>').appendTo(this.element);
+
+               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")
+                       .removeData("progressbar")
+                       .unbind(".progressbar");
+
+               this.valueDiv.remove();
+
+               $.widget.prototype.destroy.apply(this, arguments);
+
+       },
+
+       value: function(newValue) {
+               arguments.length && this._setData("value", newValue);
+               return this._value();
+       },
+
+       _setData: function(key, value) {
+
+               switch (key) {
+                       case 'value':
+                               this.options.value = value;
+                               this._refreshValue();
+                               this._trigger('change', null, {});
+                               break;
+               }
+
+               $.widget.prototype._setData.apply(this, arguments);
+
+       },
+
+       _value: function() {
+
+               var val = this.options.value;
+               if (val < this._valueMin()) val = this._valueMin();
+               if (val > this._valueMax()) val = this._valueMax();
+
+               return val;
+
+       },
+
+       _valueMin: function() {
+               var valueMin = 0;
+               return valueMin;
+       },
+
+       _valueMax: function() {
+               var valueMax = 100;
+               return valueMax;
+       },
+
+       _refreshValue: function() {
+               var value = this.value();
+               this.valueDiv[value == this._valueMax() ? 'addClass' : 'removeClass']("ui-corner-right");
+               this.valueDiv.width(value + '%');
+               this.element.attr("aria-valuenow", value);
+       }
+
+});
+
+$.extend($.ui.progressbar, {
+       version: "1.7.1",
+       defaults: {
+               value: 0
+       }
+});
+
+})(jQuery);
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/ui.resizable.js b/js2/mwEmbed/jquery/jquery.ui/ui/ui.resizable.js
new file mode 100644 (file)
index 0000000..618102f
--- /dev/null
@@ -0,0 +1,800 @@
+/*
+ * jQuery UI Resizable 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Resizables
+ *
+ * Depends:
+ *     ui.core.js
+ */
+(function($) {
+
+$.widget("ui.resizable", $.extend({}, $.ui.mouse, {
+
+       _init: 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)) {
+
+                       //Opera fix for relative positioning
+                       if (/relative/.test(this.element.css('position')) && $.browser.opera)
+                               this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
+
+                       //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>');
+
+                               // increase zIndex of sw, se, ne, nw axis
+                               //TODO : this modifies original option
+                               if(/sw|se|ne|nw/.test(handle)) 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() {
+                                       $(this).removeClass("ui-resizable-autohide");
+                                       self._handles.show();
+                               },
+                               function(){
+                                       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.parent().append(
+                               this.originalElement.css({
+                                       position: wrapper.css('position'),
+                                       width: wrapper.outerWidth(),
+                                       height: wrapper.outerHeight(),
+                                       top: wrapper.css('top'),
+                                       left: wrapper.css('left')
+                               })
+                       ).end().remove();
+               }
+
+               this.originalElement.css('resize', this.originalResizeStyle);
+               _destroy(this.originalElement);
+
+       },
+
+       _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 });
+               }
+
+               //Opera fixing relative position
+               if ($.browser.opera && (/relative/).test(el.css('position')))
+                       el.css({ position: 'relative', top: 'auto', left: 'auto' });
+
+               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;
+
+               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.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;
+
+                       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;
+
+       },
+
+       _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 (data.height) data.width = (csize.height * this.aspectRatio);
+               else if (data.width) data.height = (csize.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.options, 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.7.1",
+       eventPrefix: "resize",
+       defaults: {
+               alsoResize: false,
+               animate: false,
+               animateDuration: "slow",
+               animateEasing: "swing",
+               aspectRatio: false,
+               autoHide: false,
+               cancel: ":input,option",
+               containment: false,
+               delay: 0,
+               distance: 1,
+               ghost: false,
+               grid: false,
+               handles: "e,s,se",
+               helper: false,
+               maxHeight: null,
+               maxWidth: null,
+               minHeight: 10,
+               minWidth: 10,
+               zIndex: 1000
+       }
+});
+
+/*
+ * Resizable Extensions
+ */
+
+$.ui.plugin.add("resizable", "alsoResize", {
+
+       start: function(event, ui) {
+
+               var self = $(this).data("resizable"), o = self.options;
+
+               _store = function(exp) {
+                       $(exp).each(function() {
+                               $(this).data("resizable-alsoresize", {
+                                       width: parseInt($(this).width(), 10), height: parseInt($(this).height(), 10),
+                                       left: parseInt($(this).css('left'), 10), top: parseInt($(this).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, c) { _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 : ['width', 'height', 'top', 'left'];
+
+                               $.each(css || ['width', 'height', 'top', 'left'], function(i, prop) {
+                                       var sum = (start[prop]||0) + (delta[prop]||0);
+                                       if (sum && sum >= 0)
+                                               style[prop] = sum || null;
+                               });
+
+                               //Opera fixing relative position
+                               if (/relative/.test(el.css('position')) && $.browser.opera) {
+                                       self._revertToRelativePosition = true;
+                                       el.css({ position: 'absolute', top: 'auto', left: 'auto' });
+                               }
+
+                               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){
+               var self = $(this).data("resizable");
+
+               //Opera fixing relative position
+               if (self._revertToRelativePosition && $.browser.opera) {
+                       self._revertToRelativePosition = false;
+                       el.css({ position: 'relative' });
+               }
+
+               $(this).removeData("resizable-alsoresize-start");
+       }
+});
+
+$.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 / o.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 * o.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/js2/mwEmbed/jquery/jquery.ui/ui/ui.selectable.js b/js2/mwEmbed/jquery/jquery.ui/ui/ui.selectable.js
new file mode 100644 (file)
index 0000000..32bc3d3
--- /dev/null
@@ -0,0 +1,257 @@
+/*
+ * jQuery UI Selectable 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Selectables
+ *
+ * Depends:
+ *     ui.core.js
+ */
+(function($) {
+
+$.widget("ui.selectable", $.extend({}, $.ui.mouse, {
+
+       _init: 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.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 = $(document.createElement('div'))
+                       .css({border:'1px dotted black'})
+                       .addClass("ui-selectable-helper");
+       },
+
+       destroy: function() {
+               this.element
+                       .removeClass("ui-selectable ui-selectable-disabled")
+                       .removeData("selectable")
+                       .unbind(".selectable");
+               this._mouseDestroy();
+       },
+
+       _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({
+                       "z-index": 100,
+                       "position": "absolute",
+                       "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) {
+                               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) {
+                               selectee.$element.removeClass("ui-unselecting").addClass('ui-selecting');
+                               selectee.unselecting = false;
+                               selectee.selecting = true;
+                               selectee.selected = true;
+                               // selectable SELECTING callback
+                               self._trigger("selecting", event, {
+                                       selecting: 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 && 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 && !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.7.1",
+       defaults: {
+               appendTo: 'body',
+               autoRefresh: true,
+               cancel: ":input,option",
+               delay: 0,
+               distance: 0,
+               filter: '*',
+               tolerance: 'touch'
+       }
+});
+
+})(jQuery);
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/ui.slider.js b/js2/mwEmbed/jquery/jquery.ui/ui/ui.slider.js
new file mode 100644 (file)
index 0000000..b1c1da6
--- /dev/null
@@ -0,0 +1,533 @@
+/*
+ * jQuery UI Slider 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Slider
+ *
+ * Depends:
+ *     ui.core.js
+ */
+
+(function($) {
+
+$.widget("ui.slider", $.extend({}, $.ui.mouse, {
+
+       _init: function() {
+
+               var self = this, o = this.options;
+               this._keySliding = false;
+               this._handleIndex = null;
+               this._detectOrientation();
+               this._mouseInit();
+
+               this.element
+                       .addClass("ui-slider"
+                               + " ui-slider-" + this.orientation
+                               + " ui-widget"
+                               + " ui-widget-content"
+                               + " ui-corner-all");
+
+               this.range = $([]);
+
+               if (o.range) {
+
+                       if (o.range === true) {
+                               this.range = $('<div></div>');
+                               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]];
+                               }
+                       } else {
+                               this.range = $('<div></div>');
+                       }
+
+                       this.range
+                               .appendTo(this.element)
+                               .addClass("ui-slider-range");
+
+                       if (o.range == "min" || o.range == "max") {
+                               this.range.addClass("ui-slider-range-" + o.range);
+                       }
+
+                       // note: this isn't the most fittingly semantic framework class for this element,
+                       // but worked best visually with a variety of themes
+                       this.range.addClass("ui-widget-header");
+
+               }
+
+               if ($(".ui-slider-handle", this.element).length == 0)
+                       $('<a href="#"></a>')
+                               .appendTo(this.element)
+                               .addClass("ui-slider-handle");
+
+               if (o.values && o.values.length) {
+                       while ($(".ui-slider-handle", this.element).length < o.values.length)
+                               $('<a href="#"></a>')
+                                       .appendTo(this.element)
+                                       .addClass("ui-slider-handle");
+               }
+
+               this.handles = $(".ui-slider-handle", this.element)
+                       .addClass("ui-state-default"
+                               + " ui-corner-all");
+
+               this.handle = this.handles.eq(0);
+
+               this.handles.add(this.range).filter("a")
+                       .click(function(event) { event.preventDefault(); })
+                       .hover(function() { $(this).addClass('ui-state-hover'); }, function() { $(this).removeClass('ui-state-hover'); })
+                       .focus(function() { $(".ui-slider .ui-state-focus").removeClass('ui-state-focus'); $(this).addClass('ui-state-focus'); })
+                       .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 ret = true;
+
+                       var index = $(this).data("index.ui-slider-handle");
+
+                       if (self.options.disabled)
+                               return;
+
+                       switch (event.keyCode) {
+                               case $.ui.keyCode.HOME:
+                               case $.ui.keyCode.END:
+                               case $.ui.keyCode.UP:
+                               case $.ui.keyCode.RIGHT:
+                               case $.ui.keyCode.DOWN:
+                               case $.ui.keyCode.LEFT:
+                                       ret = false;
+                                       if (!self._keySliding) {
+                                               self._keySliding = true;
+                                               $(this).addClass("ui-state-active");
+                                               self._start(event, index);
+                                       }
+                                       break;
+                       }
+
+                       var curVal, newVal, step = self._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.UP:
+                               case $.ui.keyCode.RIGHT:
+                                       if(curVal == self._valueMax()) return;
+                                       newVal = curVal + step;
+                                       break;
+                               case $.ui.keyCode.DOWN:
+                               case $.ui.keyCode.LEFT:
+                                       if(curVal == self._valueMin()) return;
+                                       newVal = curVal - step;
+                                       break;
+                       }
+
+                       self._slide(event, index, newVal);
+
+                       return ret;
+
+               }).keyup(function(event) {
+
+                       var index = $(this).data("index.ui-slider-handle");
+
+                       if (self._keySliding) {
+                               self._stop(event, index);
+                               self._change(event, index);
+                               self._keySliding = false;
+                               $(this).removeClass("ui-state-active");
+                       }
+
+               });
+
+               this._refreshValue();
+
+       },
+
+       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();
+
+       },
+
+       _mouseCapture: function(event) {
+
+               var o = this.options;
+
+               if (o.disabled)
+                       return false;
+
+               this.elementSize = {
+                       width: this.element.outerWidth(),
+                       height: this.element.outerHeight()
+               };
+               this.elementOffset = this.element.offset();
+
+               var position = { x: event.pageX, y: event.pageY };
+               var normValue = this._normValueFromMouse(position);
+
+               var distance = this._valueMax() - this._valueMin() + 1, closestHandle;
+               var self = this, index;
+               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) {
+                       closestHandle = $(this.handles[++index]);
+               }
+
+               this._start(event, index);
+
+               self._handleIndex = index;
+
+               closestHandle
+                       .addClass("ui-state-active")
+                       .focus();
+               
+               var offset = closestHandle.offset();
+               var 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)
+               };
+
+               normValue = this._normValueFromMouse(position);
+               this._slide(event, index, normValue);
+               return true;
+
+       },
+
+       _mouseStart: function(event) {
+               return true;
+       },
+
+       _mouseDrag: function(event) {
+
+               var position = { x: event.pageX, y: event.pageY };
+               var normValue = this._normValueFromMouse(position);
+               
+               this._slide(event, this._handleIndex, normValue);
+
+               return false;
+
+       },
+
+       _mouseStop: function(event) {
+
+               this.handles.removeClass("ui-state-active");
+               this._stop(event, this._handleIndex);
+               this._change(event, this._handleIndex);
+               this._handleIndex = null;
+               this._clickOffset = null;
+
+               return false;
+
+       },
+       
+       _detectOrientation: function() {
+               this.orientation = this.options.orientation == 'vertical' ? 'vertical' : 'horizontal';
+       },
+
+       _normValueFromMouse: function(position) {
+
+               var pixelTotal, pixelMouse;
+               if ('horizontal' == this.orientation) {
+                       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);
+               }
+
+               var percentMouse = (pixelMouse / pixelTotal);
+               if (percentMouse > 1) percentMouse = 1;
+               if (percentMouse < 0) percentMouse = 0;
+               if ('vertical' == this.orientation)
+                       percentMouse = 1 - percentMouse;
+
+               var valueTotal = this._valueMax() - this._valueMin(),
+                       valueMouse = percentMouse * valueTotal,
+                       valueMouseModStep = valueMouse % this.options.step,
+                       normValue = this._valueMin() + valueMouse - valueMouseModStep;
+
+               if (valueMouseModStep > (this.options.step / 2))
+                       normValue += this.options.step;
+
+               // Since JavaScript has problems with large floats, round
+               // the final value to 5 digits after the decimal point (see #4124)
+               return parseFloat(normValue.toFixed(5));
+
+       },
+
+       _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()
+               }
+               this._trigger("start", event, uiHash);
+       },
+
+       _slide: function(event, index, newVal) {
+
+               var handle = this.handles[index];
+
+               if (this.options.values && this.options.values.length) {
+
+                       var otherVal = this.values(index ? 0 : 1);
+
+                       if ((index == 0 && newVal >= otherVal) || (index == 1 && newVal <= otherVal))
+                               newVal = otherVal;
+
+                       if (newVal != this.values(index)) {
+                               var newValues = this.values();
+                               newValues[index] = newVal;
+                               // A slide can be canceled by returning false from the slide callback
+                               var allowed = this._trigger("slide", event, {
+                                       handle: this.handles[index],
+                                       value: newVal,
+                                       values: newValues
+                               });
+                               var otherVal = this.values(index ? 0 : 1);
+                               if (allowed !== false) {
+                                       this.values(index, newVal, ( event.type == 'mousedown' && this.options.animate ), true);
+                               }
+                       }
+
+               } else {
+
+                       if (newVal != this.value()) {
+                               // A slide can be canceled by returning false from the slide callback
+                               var allowed = this._trigger("slide", event, {
+                                       handle: this.handles[index],
+                                       value: newVal
+                               });
+                               if (allowed !== false) {
+                                       this._setData('value', newVal, ( event.type == 'mousedown' && this.options.animate ));
+                               }
+                                       
+                       }
+
+               }
+
+       },
+
+       _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) {
+               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._setData("value", newValue);
+                       this._change(null, 0);
+               }
+
+               return this._value();
+
+       },
+
+       values: function(index, newValue, animated, noPropagation) {
+
+               if (arguments.length > 1) {
+                       this.options.values[index] = newValue;
+                       this._refreshValue(animated);
+                       if(!noPropagation) this._change(null, index);
+               }
+
+               if (arguments.length) {
+                       if (this.options.values && this.options.values.length) {
+                               return this._values(index);
+                       } else {
+                               return this.value();
+                       }
+               } else {
+                       return this._values();
+               }
+
+       },
+
+       _setData: function(key, value, animated) {
+
+               $.widget.prototype._setData.apply(this, arguments);
+
+               switch (key) {
+                       case 'orientation':
+
+                               this._detectOrientation();
+                               
+                               this.element
+                                       .removeClass("ui-slider-horizontal ui-slider-vertical")
+                                       .addClass("ui-slider-" + this.orientation);
+                               this._refreshValue(animated);
+                               break;
+                       case 'value':
+                               this._refreshValue(animated);
+                               break;
+               }
+
+       },
+
+       _step: function() {
+               var step = this.options.step;
+               return step;
+       },
+
+       _value: function() {
+
+               var val = this.options.value;
+               if (val < this._valueMin()) val = this._valueMin();
+               if (val > this._valueMax()) val = this._valueMax();
+
+               return val;
+
+       },
+
+       _values: function(index) {
+
+               if (arguments.length) {
+                       var val = this.options.values[index];
+                       if (val < this._valueMin()) val = this._valueMin();
+                       if (val > this._valueMax()) val = this._valueMax();
+
+                       return val;
+               } else {
+                       return this.options.values;
+               }
+
+       },
+
+       _valueMin: function() {
+               var valueMin = this.options.min;
+               return valueMin;
+       },
+
+       _valueMax: function() {
+               var valueMax = this.options.max;
+               return valueMax;
+       },
+
+       _refreshValue: function(animate) {
+
+               var oRange = this.options.range, o = this.options, self = this;
+
+               if (this.options.values && this.options.values.length) {
+                       var vp0, vp1;
+                       this.handles.each(function(i, j) {
+                               var valPercent = (self.values(i) - self._valueMin()) / (self._valueMax() - self._valueMin()) * 100;
+                               var _set = {}; _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') {
+                                               (i == 0) && self.range.stop(1,1)[animate ? 'animate' : 'css']({ left: valPercent + '%' }, o.animate);
+                                               (i == 1) && self.range[animate ? 'animate' : 'css']({ width: (valPercent - lastValPercent) + '%' }, { queue: false, duration: o.animate });
+                                       } else {
+                                               (i == 0) && self.range.stop(1,1)[animate ? 'animate' : 'css']({ bottom: (valPercent) + '%' }, o.animate);
+                                               (i == 1) && self.range[animate ? 'animate' : 'css']({ height: (valPercent - lastValPercent) + '%' }, { queue: false, duration: o.animate });
+                                       }
+                               }
+                               lastValPercent = valPercent;
+                       });
+               } else {
+                       var value = this.value(),
+                               valueMin = this._valueMin(),
+                               valueMax = this._valueMax(),
+                               valPercent = valueMax != valueMin
+                                       ? (value - valueMin) / (valueMax - valueMin) * 100
+                                       : 0;
+                       var _set = {}; _set[self.orientation == 'horizontal' ? 'left' : 'bottom'] = valPercent + '%';
+                       this.handle.stop(1,1)[animate ? 'animate' : 'css'](_set, o.animate);
+
+                       (oRange == "min") && (this.orientation == "horizontal") && this.range.stop(1,1)[animate ? 'animate' : 'css']({ width: valPercent + '%' }, o.animate);
+                       (oRange == "max") && (this.orientation == "horizontal") && this.range[animate ? 'animate' : 'css']({ width: (100 - valPercent) + '%' }, { queue: false, duration: o.animate });
+                       (oRange == "min") && (this.orientation == "vertical") && this.range.stop(1,1)[animate ? 'animate' : 'css']({ height: valPercent + '%' }, o.animate);
+                       (oRange == "max") && (this.orientation == "vertical") && this.range[animate ? 'animate' : 'css']({ height: (100 - valPercent) + '%' }, { queue: false, duration: o.animate });
+               }
+
+       }
+       
+}));
+
+$.extend($.ui.slider, {
+       getter: "value values",
+       version: "1.7.1",
+       eventPrefix: "slide",
+       defaults: {
+               animate: false,
+               delay: 0,
+               distance: 0,
+               max: 100,
+               min: 0,
+               orientation: 'horizontal',
+               range: false,
+               step: 1,
+               value: 0,
+               values: null
+       }
+});
+
+})(jQuery);
+
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/ui.sortable.js b/js2/mwEmbed/jquery/jquery.ui/ui/ui.sortable.js
new file mode 100644 (file)
index 0000000..a119a6e
--- /dev/null
@@ -0,0 +1,1019 @@
+/*
+ * jQuery UI Sortable 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Sortables
+ *
+ * Depends:
+ *     ui.core.js
+ */
+(function($) {
+
+$.widget("ui.sortable", $.extend({}, $.ui.mouse, {
+       _init: function() {
+
+               var o = this.options;
+               this.containerCache = {};
+               this.element.addClass("ui-sortable");
+
+               //Get the items
+               this.refresh();
+
+               //Let's determine if the items are floating
+               this.floating = this.items.length ? (/left|right/).test(this.items[0].item.css('float')) : false;
+
+               //Let's determine the parent's offset
+               this.offset = this.element.offset();
+
+               //Initialize mouse events for interaction
+               this._mouseInit();
+
+       },
+
+       destroy: function() {
+               this.element
+                       .removeClass("ui-sortable ui-sortable-disabled")
+                       .removeData("sortable")
+                       .unbind(".sortable");
+               this._mouseDestroy();
+
+               for ( var i = this.items.length - 1; i >= 0; i-- )
+                       this.items[i].item.removeData("sortable-item");
+       },
+
+       _mouseCapture: function(event, overrideHandle) {
+
+               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, 'sortable-item') == self) {
+                               currentItem = $(this);
+                               return false;
+                       }
+               });
+               if($.data(event.target, 'sortable-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
+               };
+
+               // 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");
+
+               $.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._generatePosition(event);
+               this.originalPageX = event.pageX;
+               this.originalPageY = event.pageY;
+
+               //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
+               if(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;
+
+                       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)
+                       ) {
+
+                               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();
+
+                       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;
+                               }
+                       }
+
+               }
+
+               //$(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 true;
+
+       },
+
+       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]));
+               });
+
+               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 = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
+                       isOverElementWidth = $.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();
+       },
+
+       _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], 'sortable');
+                                       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"), 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"), 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(sortable-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) {
+                       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], 'sortable');
+                                       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('sortable-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();
+                       };
+               }
+
+       },
+
+       _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) {
+               for (var i = this.containers.length - 1; i >= 0; i--){
+
+                       if(this._intersectsWith(this.containers[i].containerCache)) {
+                               if(!this.containers[i].containerCache.over) {
+
+                                       if(this.currentContainer != this.containers[i]) {
+
+                                               //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[i].floating ? 'left' : 'top'];
+                                               for (var j = this.items.length - 1; j >= 0; j--) {
+                                                       if(!$.ui.contains(this.containers[i].element[0], this.items[j].item[0])) continue;
+                                                       var cur = this.items[j][this.containers[i].floating ? 'left' : 'top'];
+                                                       if(Math.abs(cur - base) < dist) {
+                                                               dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
+                                                       }
+                                               }
+
+                                               if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled
+                                                       continue;
+
+                                               this.currentContainer = this.containers[i];
+                                               itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[i].element, true);
+                                               this._trigger("change", event, this._uiHash());
+                                               this.containers[i]._trigger("change", event, this._uiHash(this));
+
+                                               //Update the placeholder
+                                               this.options.placeholder.update(this.currentContainer, this.placeholder);
+
+                                       }
+
+                                       this.containers[i]._trigger("over", event, this._uiHash(this));
+                                       this.containers[i].containerCache.over = 1;
+                               }
+                       } else {
+                               if(this.containers[i].containerCache.over) {
+                                       this.containers[i]._trigger("out", event, this._uiHash(this));
+                                       this.containers[i].containerCache.over = 0;
+                               }
+                       }
+
+               };
+       },
+
+       _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(obj.left != undefined) this.offset.click.left = obj.left + this.margins.left;
+               if(obj.right != undefined) this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
+               if(obj.top != undefined) this.offset.click.top = obj.top + this.margins.top;
+               if(obj.bottom != undefined) 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[0].parentNode) 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
+               if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
+                       if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
+                       for (var i = this.containers.length - 1; i >= 0; i--){
+                               if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
+                                       delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
+                                       delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.containers[i]));
+                               }
+                       };
+               };
+
+               //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 cursor
+               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());
+                       }
+                       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,
+                       absolutePosition: self.positionAbs, //deprecated
+                       offset: self.positionAbs,
+                       item: self.currentItem,
+                       sender: inst ? inst.element : null
+               };
+       }
+
+}));
+
+$.extend($.ui.sortable, {
+       getter: "serialize toArray",
+       version: "1.7.1",
+       eventPrefix: "sort",
+       defaults: {
+               appendTo: "parent",
+               axis: false,
+               cancel: ":input,option",
+               connectWith: false,
+               containment: false,
+               cursor: 'auto',
+               cursorAt: false,
+               delay: 0,
+               distance: 1,
+               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
+       }
+});
+
+})(jQuery);
diff --git a/js2/mwEmbed/jquery/jquery.ui/ui/ui.tabs.js b/js2/mwEmbed/jquery/jquery.ui/ui/ui.tabs.js
new file mode 100644 (file)
index 0000000..a73dbc9
--- /dev/null
@@ -0,0 +1,685 @@
+/*
+ * jQuery UI Tabs 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Tabs
+ *
+ * Depends:
+ *     ui.core.js
+ */
+(function($) {
+
+$.widget("ui.tabs", {
+
+       _init: function() {
+               if (this.options.deselectable !== undefined) {
+                       this.options.collapsible = this.options.deselectable;
+               }
+               this._tabify(true);
+       },
+
+       _setData: function(key, value) {
+               if (key == 'selected') {
+                       if (this.options.collapsible && value == this.options.selected) {
+                               return;
+                       }
+                       this.select(value);
+               }
+               else {
+                       this.options[key] = value;
+                       if (key == 'deselectable') {
+                               this.options.collapsible = value;
+                       }
+                       this._tabify();
+               }
+       },
+
+       _tabId: function(a) {
+               return a.title && a.title.replace(/\s/g, '_').replace(/[^A-Za-z0-9\-_:\.]/g, '') ||
+                       this.options.idPrefix + $.data(a);
+       },
+
+       _sanitizeSelector: function(hash) {
+               return hash.replace(/:/g, '\\:'); // we need this because an id may contain a ":"
+       },
+
+       _cookie: function() {
+               var cookie = this.cookie || (this.cookie = this.options.cookie.name || 'ui-tabs-' + $.data(this.list[0]));
+               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) {
+
+               this.list = this.element.children('ul:first');
+               this.lis = $('li:has(a[href])', this.list);
+               this.anchors = this.lis.map(function() { return $('a', this)[0]; });
+               this.panels = $([]);
+
+               var self = this, o = this.options;
+
+               var fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
+               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._sanitizeSelector(href));
+                       }
+
+                       // remote tab
+                       else if (href != '#') { // prevent loading the page itself if href is just "#"
+                               $.data(a, 'href.tabs', href); // required for restore on destroy
+
+                               // TODO until #3808 is fixed strip fragment identifier from url
+                               // (IE fails to load from such url)
+                               $.data(a, 'load.tabs', href.replace(/#.*$/, '')); // mutable data
+
+                               var id = self._tabId(a);
+                               a.href = '#' + id;
+                               var $panel = $('#' + 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; // break
+                                               }
+                                       });
+                               }
+                               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 || 0;
+                       }
+                       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');
+                       if (o.selected >= 0 && this.anchors.length) { // check for length avoids error when initializing empty list
+                               this.panels.eq(o.selected).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.panels[o.selected]));
+                               });
+                               
+                               this.load(o.selected);
+                       }
+
+                       // clean up to avoid memory leaks in certain versions of IE 6
+                       $(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
+               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 &&
+                               !$(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 ($.browser.msie && fx.opacity) {
+                               $el[0].style.removeAttribute('filter');
+                       }
+               }
+
+               // Show a tab...
+               var showTab = showFx ?
+                       function(clicked, $show) {
+                               $(clicked).closest('li').removeClass('ui-state-default').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').removeClass('ui-state-default').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').addClass('ui-state-default');
+                                       $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').addClass('ui-state-default');
+                               $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 = $(this).closest('li'), $hide = self.panels.filter(':not(.ui-tabs-hide)'),
+                                       $show = $(self._sanitizeSelector(this.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._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);
+                                       });
+
+                                       self.load(self.anchors.index(this)); // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
+                                       
+                                       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;});
+
+       },
+
+       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);
+               }
+       },
+
+       add: function(url, label, index) {
+               if (index === undefined) {
+                       index = this.anchors.length; // append by default
+               }
+
+               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 = $('#' + 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) { // after tabify
+                       $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);
+               }
+
+               // callback
+               this._trigger('add', null, this._ui(this.anchors[index], this.panels[index]));
+       },
+
+       remove: function(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();
+
+               // callback
+               this._trigger('remove', null, this._ui($li.find('a')[0], $panel[0]));
+       },
+
+       enable: function(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; });
+
+               // callback
+               this._trigger('enable', null, this._ui(this.anchors[index], this.panels[index]));
+       },
+
+       disable: function(index) {
+               var self = this, o = this.options;
+               if (index != o.selected) { // cannot disable already selected tab
+                       this.lis.eq(index).addClass('ui-state-disabled');
+
+                       o.disabled.push(index);
+                       o.disabled.sort();
+
+                       // callback
+                       this._trigger('disable', null, this._ui(this.anchors[index], this.panels[index]));
+               }
+       },
+
+       select: function(index) {
+               if (typeof index == 'string') {
+                       index = this.anchors.index(this.anchors.filter('[href$=' + index + ']'));
+               }
+               else if (index === null) { // usage of null is deprecated, TODO remove in next release
+                       index = -1;
+               }
+               if (index == -1 && this.options.collapsible) {
+                       index = this.options.selected;
+               }
+
+               this.anchors.eq(index).trigger(this.options.event + '.tabs');
+       },
+
+       load: function(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._sanitizeSelector(a.hash)).html(r);
+
+                               // take care of tab labels
+                               self._cleanup();
+
+                               if (o.cache) {
+                                       $.data(a, 'cache.tabs', true); // if loaded once do not load them again
+                               }
+
+                               // callbacks
+                               self._trigger('load', null, self._ui(self.anchors[index], self.panels[index]));
+                               try {
+                                       o.ajaxOptions.success(r, s);
+                               }
+                               catch (e) {}
+
+                               // last, so that load event is fired before show...
+                               self.element.dequeue("tabs");
+                       }
+               }));
+       },
+
+       abort: function() {
+               // stop possibly running animations
+               this.element.queue([]);
+               this.panels.stop(false, true);
+
+               // terminate pending requests from other tabs
+               if (this.xhr) {
+                       this.xhr.abort();
+                       delete this.xhr;
+               }
+
+               // take care of tab labels
+               this._cleanup();
+
+       },
+
+       url: function(index, url) {
+               this.anchors.eq(index).removeData('cache.tabs').data('load.tabs', url);
+       },
+
+       length: function() {
+               return this.anchors.length;
+       }
+
+});
+
+$.extend($.ui.tabs, {
+       version: '1.7.1',
+       getter: 'length',
+       defaults: {
+               ajaxOptions: null,
+               cache: false,
+               cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
+               collapsible: false,
+               disabled: [],
+               event: 'click',
+               fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
+               idPrefix: 'ui-tabs-',
+               panelTemplate: '<div></div>',
+               spinner: '<em>Loading&#8230;</em>',
+               tabTemplate: '<li><a href="#{href}"><span>#{label}</span></a></li>'
+       }
+});
+
+/*
+ * 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) {
+                               t = o.selected;
+                               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;
+               }
+       }
+});
+
+})(jQuery);
diff --git a/js2/mwEmbed/jquery/jquery.ui/version.txt b/js2/mwEmbed/jquery/jquery.ui/version.txt
new file mode 100644 (file)
index 0000000..081af9a
--- /dev/null
@@ -0,0 +1 @@
+1.7.1
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/plugins/date.js b/js2/mwEmbed/jquery/plugins/date.js
new file mode 100644 (file)
index 0000000..86f802f
--- /dev/null
@@ -0,0 +1,467 @@
+/*
+ * Date prototype extensions. Doesn't depend on any
+ * other code. Doens't overwrite existing methods.
+ *
+ * Adds dayNames, abbrDayNames, monthNames and abbrMonthNames static properties and isLeapYear,
+ * isWeekend, isWeekDay, getDaysInMonth, getDayName, getMonthName, getDayOfYear, getWeekOfYear,
+ * setDayOfYear, addYears, addMonths, addDays, addHours, addMinutes, addSeconds methods
+ *
+ * Copyright (c) 2006 Jörn Zaefferer and Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
+ *
+ * Additional methods and properties added by Kelvin Luck: firstDayOfWeek, dateFormat, zeroTime, asString, fromString -
+ * I've added my name to these methods so you know who to blame if they are broken!
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *   http://www.gnu.org/licenses/gpl.html
+ *
+ */
+
+/**
+ * An Array of day names starting with Sunday.
+ *
+ * @example dayNames[0]
+ * @result 'Sunday'
+ *
+ * @name dayNames
+ * @type Array
+ * @cat Plugins/Methods/Date
+ */
+Date.dayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
+
+/**
+ * An Array of abbreviated day names starting with Sun.
+ *
+ * @example abbrDayNames[0]
+ * @result 'Sun'
+ *
+ * @name abbrDayNames
+ * @type Array
+ * @cat Plugins/Methods/Date
+ */
+Date.abbrDayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
+
+/**
+ * An Array of month names starting with Janurary.
+ *
+ * @example monthNames[0]
+ * @result 'January'
+ *
+ * @name monthNames
+ * @type Array
+ * @cat Plugins/Methods/Date
+ */
+Date.monthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
+
+/**
+ * An Array of abbreviated month names starting with Jan.
+ *
+ * @example abbrMonthNames[0]
+ * @result 'Jan'
+ *
+ * @name monthNames
+ * @type Array
+ * @cat Plugins/Methods/Date
+ */
+Date.abbrMonthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
+
+/**
+ * The first day of the week for this locale.
+ *
+ * @name firstDayOfWeek
+ * @type Number
+ * @cat Plugins/Methods/Date
+ * @author Kelvin Luck
+ */
+Date.firstDayOfWeek = 1;
+
+/**
+ * The format that string dates should be represented as (e.g. 'dd/mm/yyyy' for UK, 'mm/dd/yyyy' for US, 'yyyy-mm-dd' for Unicode etc).
+ *
+ * @name format
+ * @type String
+ * @cat Plugins/Methods/Date
+ * @author Kelvin Luck
+ */
+Date.format = 'dd/mm/yyyy';
+//Date.format = 'mm/dd/yyyy';
+//Date.format = 'yyyy-mm-dd';
+//Date.format = 'dd mmm yy';
+
+/**
+ * The first two numbers in the century to be used when decoding a two digit year. Since a two digit year is ambiguous (and date.setYear
+ * only works with numbers < 99 and so doesn't allow you to set years after 2000) we need to use this to disambiguate the two digit year codes.
+ *
+ * @name format
+ * @type String
+ * @cat Plugins/Methods/Date
+ * @author Kelvin Luck
+ */
+Date.fullYearStart = '20';
+
+(function() {
+
+       /**
+        * Adds a given method under the given name
+        * to the Date prototype if it doesn't
+        * currently exist.
+        *
+        * @private
+        */
+       function add(name, method) {
+               if( !Date.prototype[name] ) {
+                       Date.prototype[name] = method;
+               }
+       };
+
+       /**
+        * Checks if the year is a leap year.
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.isLeapYear();
+        * @result true
+        *
+        * @name isLeapYear
+        * @type Boolean
+        * @cat Plugins/Methods/Date
+        */
+       add("isLeapYear", function() {
+               var y = this.getFullYear();
+               return (y%4==0 && y%100!=0) || y%400==0;
+       });
+
+       /**
+        * Checks if the day is a weekend day (Sat or Sun).
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.isWeekend();
+        * @result false
+        *
+        * @name isWeekend
+        * @type Boolean
+        * @cat Plugins/Methods/Date
+        */
+       add("isWeekend", function() {
+               return this.getDay()==0 || this.getDay()==6;
+       });
+
+       /**
+        * Check if the day is a day of the week (Mon-Fri)
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.isWeekDay();
+        * @result false
+        *
+        * @name isWeekDay
+        * @type Boolean
+        * @cat Plugins/Methods/Date
+        */
+       add("isWeekDay", function() {
+               return !this.isWeekend();
+       });
+
+       /**
+        * Gets the number of days in the month.
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.getDaysInMonth();
+        * @result 31
+        *
+        * @name getDaysInMonth
+        * @type Number
+        * @cat Plugins/Methods/Date
+        */
+       add("getDaysInMonth", function() {
+               return [31,(this.isLeapYear() ? 29:28),31,30,31,30,31,31,30,31,30,31][this.getMonth()];
+       });
+
+       /**
+        * Gets the name of the day.
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.getDayName();
+        * @result 'Saturday'
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.getDayName(true);
+        * @result 'Sat'
+        *
+        * @param abbreviated Boolean When set to true the name will be abbreviated.
+        * @name getDayName
+        * @type String
+        * @cat Plugins/Methods/Date
+        */
+       add("getDayName", function(abbreviated) {
+               return abbreviated ? Date.abbrDayNames[this.getDay()] : Date.dayNames[this.getDay()];
+       });
+
+       /**
+        * Gets the name of the month.
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.getMonthName();
+        * @result 'Janurary'
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.getMonthName(true);
+        * @result 'Jan'
+        *
+        * @param abbreviated Boolean When set to true the name will be abbreviated.
+        * @name getDayName
+        * @type String
+        * @cat Plugins/Methods/Date
+        */
+       add("getMonthName", function(abbreviated) {
+               return abbreviated ? Date.abbrMonthNames[this.getMonth()] : Date.monthNames[this.getMonth()];
+       });
+
+       /**
+        * Get the number of the day of the year.
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.getDayOfYear();
+        * @result 11
+        *
+        * @name getDayOfYear
+        * @type Number
+        * @cat Plugins/Methods/Date
+        */
+       add("getDayOfYear", function() {
+               var tmpdtm = new Date("1/1/" + this.getFullYear());
+               return Math.floor((this.getTime() - tmpdtm.getTime()) / 86400000);
+       });
+
+       /**
+        * Get the number of the week of the year.
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.getWeekOfYear();
+        * @result 2
+        *
+        * @name getWeekOfYear
+        * @type Number
+        * @cat Plugins/Methods/Date
+        */
+       add("getWeekOfYear", function() {
+               return Math.ceil(this.getDayOfYear() / 7);
+       });
+
+       /**
+        * Set the day of the year.
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.setDayOfYear(1);
+        * dtm.toString();
+        * @result 'Tue Jan 01 2008 00:00:00'
+        *
+        * @name setDayOfYear
+        * @type Date
+        * @cat Plugins/Methods/Date
+        */
+       add("setDayOfYear", function(day) {
+               this.setMonth(0);
+               this.setDate(day);
+               return this;
+       });
+
+       /**
+        * Add a number of years to the date object.
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.addYears(1);
+        * dtm.toString();
+        * @result 'Mon Jan 12 2009 00:00:00'
+        *
+        * @name addYears
+        * @type Date
+        * @cat Plugins/Methods/Date
+        */
+       add("addYears", function(num) {
+               this.setFullYear(this.getFullYear() + num);
+               return this;
+       });
+
+       /**
+        * Add a number of months to the date object.
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.addMonths(1);
+        * dtm.toString();
+        * @result 'Tue Feb 12 2008 00:00:00'
+        *
+        * @name addMonths
+        * @type Date
+        * @cat Plugins/Methods/Date
+        */
+       add("addMonths", function(num) {
+               var tmpdtm = this.getDate();
+
+               this.setMonth(this.getMonth() + num);
+
+               if (tmpdtm > this.getDate())
+                       this.addDays(-this.getDate());
+
+               return this;
+       });
+
+       /**
+        * Add a number of days to the date object.
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.addDays(1);
+        * dtm.toString();
+        * @result 'Sun Jan 13 2008 00:00:00'
+        *
+        * @name addDays
+        * @type Date
+        * @cat Plugins/Methods/Date
+        */
+       add("addDays", function(num) {
+               this.setDate(this.getDate() + num);
+               return this;
+       });
+
+       /**
+        * Add a number of hours to the date object.
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.addHours(24);
+        * dtm.toString();
+        * @result 'Sun Jan 13 2008 00:00:00'
+        *
+        * @name addHours
+        * @type Date
+        * @cat Plugins/Methods/Date
+        */
+       add("addHours", function(num) {
+               this.setHours(this.getHours() + num);
+               return this;
+       });
+
+       /**
+        * Add a number of minutes to the date object.
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.addMinutes(60);
+        * dtm.toString();
+        * @result 'Sat Jan 12 2008 01:00:00'
+        *
+        * @name addMinutes
+        * @type Date
+        * @cat Plugins/Methods/Date
+        */
+       add("addMinutes", function(num) {
+               this.setMinutes(this.getMinutes() + num);
+               return this;
+       });
+
+       /**
+        * Add a number of seconds to the date object.
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.addSeconds(60);
+        * dtm.toString();
+        * @result 'Sat Jan 12 2008 00:01:00'
+        *
+        * @name addSeconds
+        * @type Date
+        * @cat Plugins/Methods/Date
+        */
+       add("addSeconds", function(num) {
+               this.setSeconds(this.getSeconds() + num);
+               return this;
+       });
+
+       /**
+        * Sets the time component of this Date to zero for cleaner, easier comparison of dates where time is not relevant.
+        *
+        * @example var dtm = new Date();
+        * dtm.zeroTime();
+        * dtm.toString();
+        * @result 'Sat Jan 12 2008 00:01:00'
+        *
+        * @name zeroTime
+        * @type Date
+        * @cat Plugins/Methods/Date
+        * @author Kelvin Luck
+        */
+       add("zeroTime", function() {
+               this.setMilliseconds(0);
+               this.setSeconds(0);
+               this.setMinutes(0);
+               this.setHours(0);
+               return this;
+       });
+
+       /**
+        * Returns a string representation of the date object according to Date.format.
+        * (Date.toString may be used in other places so I purposefully didn't overwrite it)
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.asString();
+        * @result '12/01/2008' // (where Date.format == 'dd/mm/yyyy'
+        *
+        * @name asString
+        * @type Date
+        * @cat Plugins/Methods/Date
+        * @author Kelvin Luck
+        */
+       add("asString", function() {
+               var r = Date.format;
+               return r
+                       .split('yyyy').join(this.getFullYear())
+                       .split('yy').join((this.getFullYear() + '').substring(2))
+                       .split('mmm').join(this.getMonthName(true))
+                       .split('mm').join(_zeroPad(this.getMonth()+1))
+                       .split('dd').join(_zeroPad(this.getDate()));
+       });
+
+       /**
+        * Returns a new date object created from the passed String according to Date.format or false if the attempt to do this results in an invalid date object
+        * (We can't simple use Date.parse as it's not aware of locale and I chose not to overwrite it incase it's functionality is being relied on elsewhere)
+        *
+        * @example var dtm = Date.fromString("12/01/2008");
+        * dtm.toString();
+        * @result 'Sat Jan 12 2008 00:00:00' // (where Date.format == 'dd/mm/yyyy'
+        *
+        * @name fromString
+        * @type Date
+        * @cat Plugins/Methods/Date
+        * @author Kelvin Luck
+        */
+       Date.fromString = function(s)
+       {
+               var f = Date.format;
+               var d = new Date('01/01/1977');
+               var iY = f.indexOf('yyyy');
+               if (iY > -1) {
+                       d.setFullYear(Number(s.substr(iY, 4)));
+               } else {
+                       // TODO - this doesn't work very well - are there any rules for what is meant by a two digit year?
+                       d.setFullYear(Number(Date.fullYearStart + s.substr(f.indexOf('yy'), 2)));
+               }
+               var iM = f.indexOf('mmm');
+               if (iM > -1) {
+                       var mStr = s.substr(iM, 3);
+                       for (var i=0; i<Date.abbrMonthNames.length; i++) {
+                               if (Date.abbrMonthNames[i] == mStr) break;
+                       }
+                       d.setMonth(i);
+               } else {
+                       d.setMonth(Number(s.substr(f.indexOf('mm'), 2)) - 1);
+               }
+               d.setDate(Number(s.substr(f.indexOf('dd'), 2)));
+               if (isNaN(d.getTime())) {
+                       return false;
+               }
+               return d;
+       };
+
+       // utility method
+       var _zeroPad = function(num) {
+               var s = '0'+num;
+               return s.substring(s.length-2)
+               //return ('0'+num).substring(-2); // doesn't work on IE :(
+       };
+
+})();
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/plugins/images/cut.png b/js2/mwEmbed/jquery/plugins/images/cut.png
new file mode 100644 (file)
index 0000000..f215d6f
Binary files /dev/null and b/js2/mwEmbed/jquery/plugins/images/cut.png differ
diff --git a/js2/mwEmbed/jquery/plugins/images/door.png b/js2/mwEmbed/jquery/plugins/images/door.png
new file mode 100644 (file)
index 0000000..369fc46
Binary files /dev/null and b/js2/mwEmbed/jquery/plugins/images/door.png differ
diff --git a/js2/mwEmbed/jquery/plugins/images/page_white_copy.png b/js2/mwEmbed/jquery/plugins/images/page_white_copy.png
new file mode 100644 (file)
index 0000000..a9f31a2
Binary files /dev/null and b/js2/mwEmbed/jquery/plugins/images/page_white_copy.png differ
diff --git a/js2/mwEmbed/jquery/plugins/images/page_white_delete.png b/js2/mwEmbed/jquery/plugins/images/page_white_delete.png
new file mode 100644 (file)
index 0000000..af1ecaf
Binary files /dev/null and b/js2/mwEmbed/jquery/plugins/images/page_white_delete.png differ
diff --git a/js2/mwEmbed/jquery/plugins/images/page_white_edit.png b/js2/mwEmbed/jquery/plugins/images/page_white_edit.png
new file mode 100644 (file)
index 0000000..b93e776
Binary files /dev/null and b/js2/mwEmbed/jquery/plugins/images/page_white_edit.png differ
diff --git a/js2/mwEmbed/jquery/plugins/images/page_white_paste.png b/js2/mwEmbed/jquery/plugins/images/page_white_paste.png
new file mode 100644 (file)
index 0000000..5b2cbb3
Binary files /dev/null and b/js2/mwEmbed/jquery/plugins/images/page_white_paste.png differ
diff --git a/js2/mwEmbed/jquery/plugins/indicator.gif b/js2/mwEmbed/jquery/plugins/indicator.gif
new file mode 100644 (file)
index 0000000..085ccae
Binary files /dev/null and b/js2/mwEmbed/jquery/plugins/indicator.gif differ
diff --git a/js2/mwEmbed/jquery/plugins/jquery.autocomplete.css b/js2/mwEmbed/jquery/plugins/jquery.autocomplete.css
new file mode 100644 (file)
index 0000000..cb9107b
--- /dev/null
@@ -0,0 +1,46 @@
+.ac_results {
+       padding: 0px;
+       border: 1px solid WindowFrame;
+       background-color: Window;
+       overflow: hidden;
+}
+
+.ac_results ul {
+       width: 100%;
+       list-style-position: outside;
+       list-style: none;
+       padding: 0;
+       margin: 0;
+}
+
+.ac_results iframe {
+       display:none;/*sorry for IE5*/
+       display/**/:block;/*sorry for IE5*/
+       position:absolute;
+       top:0;
+       left:0;
+       z-index:-1;
+       filter:mask();
+       width:3000px;
+       height:3000px;
+}
+
+.ac_results li {
+       margin: 0px;
+       padding: 2px 5px;
+       cursor: pointer;
+       display: block;
+       width: 100%;
+       font: menu;
+       font-size: 12px;
+       overflow: hidden;
+}
+
+.ac_loading {
+       background : Window url('./indicator.gif') right center no-repeat;
+}
+
+.ac_over {
+       background-color: Highlight;
+       color: HighlightText;
+}
diff --git a/js2/mwEmbed/jquery/plugins/jquery.autocomplete.js b/js2/mwEmbed/jquery/plugins/jquery.autocomplete.js
new file mode 100644 (file)
index 0000000..396ed27
--- /dev/null
@@ -0,0 +1,529 @@
+(function($){
+
+jQuery.autocomplete = function(input, options) {
+       // Create a link to self
+       var me = this;
+
+       // Create jQuery object for input element
+       var $input = $(input).attr("autocomplete", "off");
+
+       // Apply inputClass if necessary
+       if (options.inputClass) $input.addClass(options.inputClass);
+
+       // Create results
+       if(!options.resultElem){
+               var results = document.createElement("div");
+               // Create jQuery object for results
+               var $results = $(results);
+               // Add to body element
+               $("body").append(results);
+               $results.hide().addClass(options.resultsClass).css("position", "absolute");
+               if( options.width > 0 ) $results.css("width", options.width);
+       }else{
+               var results = $j(options.resultElem).get(0);
+               var $results = $j(options.resultElem);
+               $results.hide();
+       }
+
+
+       input.autocompleter = me;
+
+       var timeout = null;
+       var prev = "";
+       var active = -1;
+       var cache = {};
+       var keyb = false;
+       var hasFocus = false;
+       var lastKeyPressCode = null;
+
+       // flush cache
+       function flushCache(){
+               cache = {};
+               cache.data = {};
+               cache.length = 0;
+       };
+
+       // flush cache
+       flushCache();
+
+       // if there is a data array supplied
+       if( options.data != null ){
+               var sFirstChar = "", stMatchSets = {}, row = [];
+
+               // no url was specified, we need to adjust the cache length to make sure it fits the local data store
+               if( typeof options.url != "string" ) options.cacheLength = 1;
+
+               // loop through the array and create a lookup structure
+               for( var i=0; i < options.data.length; i++ ){
+                       // if row is a string, make an array otherwise just reference the array
+                       row = ((typeof options.data[i] == "string") ? [options.data[i]] : options.data[i]);
+
+                       // if the length is zero, don't add to list
+                       if( row[0].length > 0 ){
+                               // get the first character
+                               sFirstChar = row[0].substring(0, 1).toLowerCase();
+                               // if no lookup array for this character exists, look it up now
+                               if( !stMatchSets[sFirstChar] ) stMatchSets[sFirstChar] = [];
+                               // if the match is a string
+                               stMatchSets[sFirstChar].push(row);
+                       }
+               }
+
+               // add the data items to the cache
+               for( var k in stMatchSets ){
+                       // increase the cache size
+                       options.cacheLength++;
+                       // add to the cache
+                       addToCache(k, stMatchSets[k]);
+               }
+       }
+
+       $input
+       .keydown(function(e) {
+               // track last key pressed
+               lastKeyPressCode = e.keyCode;
+               switch(e.keyCode) {
+                       case 38: // up
+                               e.preventDefault();
+                               moveSelect(-1);
+                               break;
+                       case 40: // down
+                               e.preventDefault();
+                               moveSelect(1);
+                               break;
+                       case 9:  // tab
+                       case 13: // return
+                               if( selectCurrent() ){
+                                       // make sure to blur off the current field
+                                       $input.get(0).blur();
+                                       e.preventDefault();
+                               }
+                               break;
+                       default:
+                               active = -1;
+                               if (timeout) clearTimeout(timeout);
+                               timeout = setTimeout(function(){onChange();}, options.delay);
+                               break;
+               }
+       })
+       .focus(function(){
+               // track whether the field has focus, we shouldn't process any results if the field no longer has focus
+               hasFocus = true;
+       })
+       .blur(function() {
+               // track whether the field has focus
+               hasFocus = false;
+               hideResults();
+       });
+
+       hideResultsNow();
+
+       function onChange() {
+               // ignore if the following keys are pressed: [del] [shift] [capslock]
+               if( lastKeyPressCode == 46 || (lastKeyPressCode > 8 && lastKeyPressCode < 32) ) return $results.hide();
+               var v = $input.val();
+               if (v == prev) return;
+               prev = v;
+               if (v.length >= options.minChars) {
+                       $input.addClass(options.loadingClass);
+                       requestData(v);
+               } else {
+                       $input.removeClass(options.loadingClass);
+                       $results.hide();
+               }
+       };
+
+       function moveSelect(step) {
+               var lis = $("li", results);
+               if (!lis) return;
+
+               active += step;
+
+               if (active < 0) {
+                       active = 0;
+               } else if (active >= lis.size()) {
+                       active = lis.size() - 1;
+               }
+
+               lis.removeClass("ac_over");
+
+               $(lis[active]).addClass("ac_over");
+
+               // Weird behaviour in IE
+               // if (lis[active] && lis[active].scrollIntoView) {
+               //      lis[active].scrollIntoView(false);
+               // }
+
+       };
+       function selectCurrent() {
+               var li = $("li.ac_over", results)[0];
+               if (!li) {
+                       var $li = $("li", results);
+                       if (options.selectOnly) {
+                               if ($li.length == 1) li = $li[0];
+                       } else if (options.selectFirst) {
+                               li = $li[0];
+                       }
+               }
+               if (li) {
+                       selectItem(li);
+                       return true;
+               } else {
+                       return false;
+               }
+       };
+
+       function selectItem(li) {
+               if (!li) {
+                       li = document.createElement("li");
+                       li.extra = [];
+                       li.selectValue = "";
+               }
+               var v = $.trim(li.selectValue ? li.selectValue : li.innerHTML);
+               input.lastSelected = v;
+               prev = v;
+               $results.html("");
+               $input.val(v);
+               hideResultsNow();
+               if (options.onItemSelect) setTimeout(function() { options.onItemSelect(li) }, 1);
+       };
+
+       // selects a portion of the input string
+       function createSelection(start, end){
+               // get a reference to the input element
+               var field = $input.get(0);
+               if( field.createTextRange ){
+                       var selRange = field.createTextRange();
+                       selRange.collapse(true);
+                       selRange.moveStart("character", start);
+                       selRange.moveEnd("character", end);
+                       selRange.select();
+               } else if( field.setSelectionRange ){
+                       field.setSelectionRange(start, end);
+               } else {
+                       if( field.selectionStart ){
+                               field.selectionStart = start;
+                               field.selectionEnd = end;
+                       }
+               }
+               field.focus();
+       };
+
+       // fills in the input box w/the first match (assumed to be the best match)
+       function autoFill(sValue){
+               // if the last user key pressed was backspace, don't autofill
+               if( lastKeyPressCode != 8 ){
+                       // fill in the value (keep the case the user has typed)
+                       $input.val($input.val() + sValue.substring(prev.length));
+                       // select the portion of the value not typed by the user (so the next character will erase)
+                       createSelection(prev.length, sValue.length);
+               }
+       };
+
+       function showResults() {
+               // get the position of the input field right now (in case the DOM is shifted)
+               var pos = findPos(input);
+               // either use the specified width, or autocalculate based on form element
+               var iWidth = (options.width > 0) ? options.width : $input.width();
+               // reposition
+               if(!options.resultElem){
+                       $results.css({
+                               width: parseInt(iWidth) + "px",
+                               top: (pos.y + input.offsetHeight) + "px",
+                               left: pos.x + "px"
+                       }).show();
+               }else{
+                       $results.show();
+               }
+               if(options.resultContainer){
+                       $(options.resultContainer).css({top: (pos.y + input.offsetHeight) + "px",
+                               left: (pos.x- parseInt(iWidth)) + "px"}).show();
+               }
+       };
+
+       function hideResults() {
+               if (timeout) clearTimeout(timeout);
+               timeout = setTimeout(hideResultsNow, 200);
+       };
+
+       function hideResultsNow() {
+               if (timeout) clearTimeout(timeout);
+               $input.removeClass(options.loadingClass);
+               if ($results.is(":visible")) {
+                       $results.hide();
+               }
+               if(options.resultContainer){
+                       $(options.resultContainer).hide();
+               }
+               if (options.mustMatch) {
+                       var v = $input.val();
+                       if (v != input.lastSelected) {
+                               selectItem(null);
+                       }
+               }
+       };
+
+       function receiveData(q, data) {
+               if (data) {
+                       $input.removeClass(options.loadingClass);
+                       results.innerHTML = "";
+
+                       // if the field no longer has focus or if there are no matches, do not display the drop down
+                       if( !hasFocus || data.length == 0 ) return hideResultsNow();
+
+                       //messes with layout & ie7 does not have this problem
+                       /*if ($.browser.msie) {
+                               // we put a styled iframe behind the calendar so HTML SELECT elements don't show through
+                               $results.append(document.createElement('iframe'));
+                       }*/
+                       results.appendChild(dataToDom(data));
+                       // autofill in the complete box w/the first match as long as the user hasn't entered in more data
+                       if( options.autoFill && ($input.val().toLowerCase() == q.toLowerCase()) ) autoFill(data[0][0]);
+                       showResults();
+               } else {
+                       hideResultsNow();
+               }
+       };
+
+       function parseData(data) {
+               if (!data) return null;
+               var parsed = [];
+               var rows = data.split(options.lineSeparator);
+               for (var i=0; i < rows.length; i++) {
+                       var row = $.trim(rows[i]);
+                       if (row) {
+                               parsed[parsed.length] = row.split(options.cellSeparator);
+                       }
+               }
+               return parsed;
+       };
+
+       function dataToDom(data) {
+               var ul = document.createElement("ul");
+               if(options.ul_class)$(ul).addClass(options.ul_class);
+
+               var num = data.length;
+
+               // limited results to a max number
+               if( (options.maxItemsToShow > 0) && (options.maxItemsToShow < num) ) num = options.maxItemsToShow;
+
+               for (var i=0; i < num; i++) {
+                       var row = data[i];
+                       if (!row) continue;
+                       var li = document.createElement("li");
+                       if (options.formatItem) {
+                               li.innerHTML = options.formatItem(row, i, num);
+                               li.selectValue = row[0];
+                       } else {
+                               li.innerHTML = row[0];
+                               li.selectValue = row[0];
+                       }
+                       var extra = null;
+                       if (row.length > 1) {
+                               extra = [];
+                               for (var j=1; j < row.length; j++) {
+                                       extra[extra.length] = row[j];
+                               }
+                       }
+                       li.extra = extra;
+                       ul.appendChild(li);
+                       $(li).hover(
+                               function() { $("li", ul).removeClass("ac_over"); $(this).addClass("ac_over"); active = $("li", ul).indexOf($(this).get(0)); },
+                               function() { $(this).removeClass("ac_over"); }
+                       ).click(function(e) { e.preventDefault(); e.stopPropagation(); selectItem(this) });
+               }
+               return ul;
+       };
+
+       function requestData(q) {
+               if (!options.matchCase) q = q.toLowerCase();
+               //var data = options.cacheLength ? loadFromCache(q) : null;
+               var data=null;
+               // recieve the cached data
+               if (data) {
+                       receiveData(q, data);
+               // if an AJAX url has been supplied, try loading the data now
+               } else if( (typeof options.url == "string") && (options.url.length > 0) ){
+                       $.get(makeUrl(q), function(data) {
+                               data = parseData(data);
+                               addToCache(q, data);
+                               receiveData(q, data);
+                       });
+               // if there's been no data found, remove the loading class
+               } else {
+                       $input.removeClass(options.loadingClass);
+               }
+       };
+
+       function makeUrl(q) {
+               var url = options.url + "?"+options.paramName+'='+ encodeURI(q);
+               for (var i in options.extraParams) {
+                       url += "&" + i + "=" + encodeURI(options.extraParams[i]);
+               }
+               return url;
+       };
+
+       function loadFromCache(q) {
+               if (!q) return null;
+               if (typeof cache.data[q]!='undefined'){
+                       return cache.data[q];
+               }
+               if (options.matchSubset) {
+                       for (var i = q.length - 1; i >= options.minChars; i--) {
+                               var qs = q.substr(0, i);
+                               var c = cache.data[qs];
+                               if (c) {
+                                       var csub = [];
+                                       for (var j = 0; j < c.length; j++) {
+                                               var x = c[j];
+                                               var x0 = x[0];
+                                               if (matchSubset(x0, q)) {
+                                                       csub[csub.length] = x;
+                                               }
+                                       }
+                                       return csub;
+                               }
+                       }
+               }
+               return null;
+       };
+
+       function matchSubset(s, sub) {
+               if (!options.matchCase) s = s.toLowerCase();
+               var i = s.indexOf(sub);
+               if (i == -1) return false;
+               return i == 0 || options.matchContains;
+       };
+
+       this.flushCache = function() {
+               flushCache();
+       };
+
+       this.setExtraParams = function(p) {
+               options.extraParams = p;
+       };
+
+       this.findValue = function(){
+               var q = $input.val();
+
+               if (!options.matchCase) q = q.toLowerCase();
+               var data = options.cacheLength ? loadFromCache(q) : null;
+               if (data) {
+                       findValueCallback(q, data);
+               } else if( (typeof options.url == "string") && (options.url.length > 0) ){
+                       $.get(makeUrl(q), function(data) {
+                               data = parseData(data)
+                               addToCache(q, data);
+                               findValueCallback(q, data);
+                       });
+               } else {
+                       // no matches
+                       findValueCallback(q, null);
+               }
+       }
+
+       function findValueCallback(q, data){
+               if (data) $input.removeClass(options.loadingClass);
+
+               var num = (data) ? data.length : 0;
+               var li = null;
+
+               for (var i=0; i < num; i++) {
+                       var row = data[i];
+
+                       if( row[0].toLowerCase() == q.toLowerCase() ){
+                               li = document.createElement("li");
+                               if (options.formatItem) {
+                                       li.innerHTML = options.formatItem(row, i, num);
+                                       li.selectValue = row[0];
+                               } else {
+                                       li.innerHTML = row[0];
+                                       li.selectValue = row[0];
+                               }
+                               var extra = null;
+                               if( row.length > 1 ){
+                                       extra = [];
+                                       for (var j=1; j < row.length; j++) {
+                                               extra[extra.length] = row[j];
+                                       }
+                               }
+                               li.extra = extra;
+                       }
+               }
+
+               if( options.onFindValue ) setTimeout(function() { options.onFindValue(li) }, 1);
+       }
+
+       function addToCache(q, data) {
+               if (!data || !q || !options.cacheLength) return;
+               if (!cache.length || cache.length > options.cacheLength) {
+                       flushCache();
+                       cache.length++;
+               } else if (!cache[q]) {
+                       cache.length++;
+               }
+               cache.data[q] = data;
+       };
+
+       function findPos(obj) {
+               var curleft = obj.offsetLeft || 0;
+               var curtop = obj.offsetTop || 0;
+               while (obj = obj.offsetParent) {
+                       curleft += obj.offsetLeft
+                       curtop += obj.offsetTop
+               }
+               return {x:curleft,y:curtop};
+       }
+}
+})(jQuery);
+
+jQuery.fn.autocomplete = function(url, options, data) {
+       // Make sure options exists
+       options = options || {};
+       // Set url as option
+       options.url = url;
+       // set some bulk local data
+       options.data = ((typeof data == "object") && (data.constructor == Array)) ? data : null;
+
+       // Set default values for required options
+       options.resultElem = options.resultElem || null;
+       options.paramName = options.paramName || 'q';
+
+       options.inputClass = options.inputClass || "ac_input";
+       options.resultsClass = options.resultsClass || "ac_results";
+       options.lineSeparator = options.lineSeparator || "\n";
+       options.cellSeparator = options.cellSeparator || "|";
+       options.minChars = options.minChars || 1;
+       options.delay = options.delay || 400;
+       options.matchCase = options.matchCase || 0;
+       options.matchSubset = options.matchSubset || 1;
+       options.matchContains = options.matchContains || 0;
+       options.cacheLength = options.cacheLength || 1;
+       options.mustMatch = options.mustMatch || 0;
+       options.extraParams = options.extraParams || {};
+       options.loadingClass = options.loadingClass || "ac_loading";
+       options.selectFirst = options.selectFirst || false;
+       options.selectOnly = options.selectOnly || false;
+       options.maxItemsToShow = options.maxItemsToShow || -1;
+       options.autoFill = options.autoFill || false;
+       options.width = parseInt(options.width, 10) || 0;
+
+       this.each(function() {
+               var input = this;
+               new jQuery.autocomplete(input, options);
+       });
+
+       // Don't break the chain
+       return this;
+}
+
+jQuery.fn.autocompleteArray = function(data, options) {
+       return this.autocomplete(null, options, data);
+}
+
+jQuery.fn.indexOf = function(e){
+       for( var i=0; i<this.length; i++ ){
+               if( this[i] == e ) return i;
+       }
+       return -1;
+};
diff --git a/js2/mwEmbed/jquery/plugins/jquery.bgiframe.js b/js2/mwEmbed/jquery/plugins/jquery.bgiframe.js
new file mode 100644 (file)
index 0000000..d6369a1
--- /dev/null
@@ -0,0 +1,100 @@
+/* Copyright (c) 2006 Brandon Aaron (http://brandonaaron.net)
+ * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
+ * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
+ *
+ * $LastChangedDate$
+ * $Rev$
+ *
+ * Version 2.1.1
+ */
+
+(function($){
+
+/**
+ * The bgiframe is chainable and applies the iframe hack to get
+ * around zIndex issues in IE6. It will only apply itself in IE6
+ * and adds a class to the iframe called 'bgiframe'. The iframe
+ * is appeneded as the first child of the matched element(s)
+ * with a tabIndex and zIndex of -1.
+ *
+ * By default the plugin will take borders, sized with pixel units,
+ * into account. If a different unit is used for the border's width,
+ * then you will need to use the top and left settings as explained below.
+ *
+ * NOTICE: This plugin has been reported to cause perfromance problems
+ * when used on elements that change properties (like width, height and
+ * opacity) a lot in IE6. Most of these problems have been caused by
+ * the expressions used to calculate the elements width, height and
+ * borders. Some have reported it is due to the opacity filter. All
+ * these settings can be changed if needed as explained below.
+ *
+ * @example $('div').bgiframe();
+ * @before <div><p>Paragraph</p></div>
+ * @result <div><iframe class="bgiframe".../><p>Paragraph</p></div>
+ *
+ * @param Map settings Optional settings to configure the iframe.
+ * @option String|Number top The iframe must be offset to the top
+ *             by the width of the top border. This should be a negative
+ *       number representing the border-top-width. If a number is
+ *             is used here, pixels will be assumed. Otherwise, be sure
+ *             to specify a unit. An expression could also be used.
+ *             By default the value is "auto" which will use an expression
+ *             to get the border-top-width if it is in pixels.
+ * @option String|Number left The iframe must be offset to the left
+ *             by the width of the left border. This should be a negative
+ *       number representing the border-left-width. If a number is
+ *             is used here, pixels will be assumed. Otherwise, be sure
+ *             to specify a unit. An expression could also be used.
+ *             By default the value is "auto" which will use an expression
+ *             to get the border-left-width if it is in pixels.
+ * @option String|Number width This is the width of the iframe. If
+ *             a number is used here, pixels will be assume. Otherwise, be sure
+ *             to specify a unit. An experssion could also be used.
+ *             By default the value is "auto" which will use an experssion
+ *             to get the offsetWidth.
+ * @option String|Number height This is the height of the iframe. If
+ *             a number is used here, pixels will be assume. Otherwise, be sure
+ *             to specify a unit. An experssion could also be used.
+ *             By default the value is "auto" which will use an experssion
+ *             to get the offsetHeight.
+ * @option Boolean opacity This is a boolean representing whether or not
+ *             to use opacity. If set to true, the opacity of 0 is applied. If
+ *             set to false, the opacity filter is not applied. Default: true.
+ * @option String src This setting is provided so that one could change
+ *             the src of the iframe to whatever they need.
+ *             Default: "javascript:false;"
+ *
+ * @name bgiframe
+ * @type jQuery
+ * @cat Plugins/bgiframe
+ * @author Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
+ */
+$.fn.bgIframe = $.fn.bgiframe = function(s) {
+       // This is only for IE6
+       if ( $.browser.msie && /6.0/.test(navigator.userAgent) ) {
+               s = $.extend({
+                       top      : 'auto', // auto == .currentStyle.borderTopWidth
+                       left    : 'auto', // auto == .currentStyle.borderLeftWidth
+                       width   : 'auto', // auto == offsetWidth
+                       height  : 'auto', // auto == offsetHeight
+                       opacity : true,
+                       src      : 'javascript:false;'
+               }, s || {});
+               var prop = function(n){return n&&n.constructor==Number?n+'px':n;},
+                       html = '<iframe class="bgiframe"frameborder="0"tabindex="-1"src="'+s.src+'"'+
+                                          'style="display:block;position:absolute;z-index:-1;'+
+                                                  (s.opacity !== false?'filter:Alpha(Opacity=\'0\');':'')+
+                                                  'top:'+(s.top=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderTopWidth)||0)*-1)+\'px\')':prop(s.top))+';'+
+                                                  'left:'+(s.left=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderLeftWidth)||0)*-1)+\'px\')':prop(s.left))+';'+
+                                                  'width:'+(s.width=='auto'?'expression(this.parentNode.offsetWidth+\'px\')':prop(s.width))+';'+
+                                                  'height:'+(s.height=='auto'?'expression(this.parentNode.offsetHeight+\'px\')':prop(s.height))+';'+
+                                       '"/>';
+               return this.each(function() {
+                       if ( $('> iframe.bgiframe', this).length == 0 )
+                               this.insertBefore( document.createElement(html), this.firstChild );
+               });
+       }
+       return this;
+};
+
+})(jQuery);
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/plugins/jquery.contextMenu.css b/js2/mwEmbed/jquery/plugins/jquery.contextMenu.css
new file mode 100644 (file)
index 0000000..cc67001
--- /dev/null
@@ -0,0 +1,62 @@
+/* Generic context menu styles */
+.contextMenu {
+       position: absolute;
+       width: 120px;
+       z-index: 99999;
+       border: solid 1px #CCC;
+       background: #EEE;
+       padding: 0px;
+       margin: 0px;
+       display: none;
+}
+
+.contextMenu LI {
+       list-style: none;
+       padding: 0px;
+       margin: 0px;
+}
+
+.contextMenu A {
+       color: #333;
+       text-decoration: none;
+       display: block;
+       line-height: 20px;
+       height: 20px;
+       background-position: 6px center;
+       background-repeat: no-repeat;
+       outline: none;
+       padding: 1px 5px;
+       padding-left: 28px;
+}
+
+.contextMenu LI.hover A {
+       color: #FFF;
+       background-color: #3399FF;
+}
+
+.contextMenu LI.disabled A {
+       color: #AAA;
+       cursor: default;
+}
+
+.contextMenu LI.hover.disabled A {
+       background-color: transparent;
+}
+
+.contextMenu LI.separator {
+       border-top: solid 1px #CCC;
+}
+
+/*
+       Adding Icons
+       
+       You can add icons to the context menu by adding
+       classes to the respective LI element(s)
+*/
+
+.contextMenu LI.edit A { background-image: url(images/page_white_edit.png); }
+.contextMenu LI.cut A { background-image: url(images/cut.png); }
+.contextMenu LI.copy A { background-image: url(images/page_white_copy.png); }
+.contextMenu LI.paste A { background-image: url(images/page_white_paste.png); }
+.contextMenu LI.delete A { background-image: url(images/page_white_delete.png); }
+.contextMenu LI.quit A { background-image: url(images/door.png); }
diff --git a/js2/mwEmbed/jquery/plugins/jquery.contextMenu.js b/js2/mwEmbed/jquery/plugins/jquery.contextMenu.js
new file mode 100644 (file)
index 0000000..c93defc
--- /dev/null
@@ -0,0 +1,211 @@
+// jQuery Context Menu Plugin
+//
+// Version 1.00
+//
+// Cory S.N. LaViska
+// A Beautiful Site (http://abeautifulsite.net/)
+//
+// Visit http://abeautifulsite.net/notebook/80 for usage and more information
+//
+// Terms of Use
+//
+// This software is licensed under a Creative Commons License and is copyrighted
+// (C)2008 by Cory S.N. LaViska.
+//
+// For details, visit http://creativecommons.org/licenses/by/3.0/us/
+//
+(function($){
+       $.extend({
+               
+               contextMenu: function(o, callback) {
+                       // Defaults
+                       if( o.menu == undefined ) return false;
+                       if( o.inSpeed == undefined ) o.inSpeed = 150;
+                       if( o.outSpeed == undefined ) o.outSpeed = 75;
+                       // 0 needs to be -1 for expected results (no fade)
+                       if( o.inSpeed == 0 ) o.inSpeed = -1;
+                       if( o.outSpeed == 0 ) o.outSpeed = -1;
+                       // Loop each context menu
+                       $(this).each( function() {
+                               var el = $(this);
+                               var offset = $(el).offset();
+                               // Add contextMenu class
+                               $('#' + o.menu).addClass('contextMenu');
+                               // Simulate a true right click
+                               $(this).mousedown( function(e) {
+                                       var evt = e;
+                                       $(this).mouseup( function(e) {
+                                               var srcElement = $(this);
+                                               $(this).unbind('mouseup');
+                                               if( evt.button == 2 ) {
+                                                       // Hide context menus that may be showing
+                                                       $(".contextMenu").hide();
+                                                       // Get this context menu
+                                                       var menu = $('#' + o.menu);
+                                                       
+                                                       if( $(el).hasClass('disabled') ) return false;
+                                                       
+                                                       // Detect mouse position
+                                                       var d = {}, x, y;
+                                                       if( self.innerHeight ) {
+                                                               d.pageYOffset = self.pageYOffset;
+                                                               d.pageXOffset = self.pageXOffset;
+                                                               d.innerHeight = self.innerHeight;
+                                                               d.innerWidth = self.innerWidth;
+                                                       } else if( document.documentElement &&
+                                                               document.documentElement.clientHeight ) {
+                                                               d.pageYOffset = document.documentElement.scrollTop;
+                                                               d.pageXOffset = document.documentElement.scrollLeft;
+                                                               d.innerHeight = document.documentElement.clientHeight;
+                                                               d.innerWidth = document.documentElement.clientWidth;
+                                                       } else if( document.body ) {
+                                                               d.pageYOffset = document.body.scrollTop;
+                                                               d.pageXOffset = document.body.scrollLeft;
+                                                               d.innerHeight = document.body.clientHeight;
+                                                               d.innerWidth = document.body.clientWidth;
+                                                       }
+                                                       (e.pageX) ? x = e.pageX : x = e.clientX + d.scrollLeft;
+                                                       (e.pageY) ? y = e.pageY : x = e.clientY + d.scrollTop;
+                                                       
+                                                       // Show the menu
+                                                       $(document).unbind('click');
+                                                       $(menu).css({ top: y, left: x }).fadeIn(o.inSpeed);
+                                                       // Hover events
+                                                       $(menu).find('A').mouseover( function() {
+                                                               $(menu).find('LI.hover').removeClass('hover');
+                                                               $(this).parent().addClass('hover');
+                                                       }).mouseout( function() {
+                                                               $(menu).find('LI.hover').removeClass('hover');
+                                                       });
+                                                       
+                                                       // Keyboard
+                                                       $(document).keypress( function(e) {
+                                                               switch( e.keyCode ) {
+                                                                       case 38: // up
+                                                                               if( $(menu).find('LI.hover').size() == 0 ) {
+                                                                                       $(menu).find('LI:last').addClass('hover');
+                                                                               } else {
+                                                                                       $(menu).find('LI.hover').removeClass('hover').prevAll('LI:not(.disabled)').eq(0).addClass('hover');
+                                                                                       if( $(menu).find('LI.hover').size() == 0 ) $(menu).find('LI:last').addClass('hover');
+                                                                               }
+                                                                       break;
+                                                                       case 40: // down
+                                                                               if( $(menu).find('LI.hover').size() == 0 ) {
+                                                                                       $(menu).find('LI:first').addClass('hover');
+                                                                               } else {
+                                                                                       $(menu).find('LI.hover').removeClass('hover').nextAll('LI:not(.disabled)').eq(0).addClass('hover');
+                                                                                       if( $(menu).find('LI.hover').size() == 0 ) $(menu).find('LI:first').addClass('hover');
+                                                                               }
+                                                                       break;
+                                                                       case 13: // enter
+                                                                               $(menu).find('LI.hover A').trigger('click');
+                                                                       break;
+                                                                       case 27: // esc
+                                                                               $(document).trigger('click');
+                                                                       break
+                                                               }
+                                                       });
+                                                       
+                                                       // When items are selected
+                                                       $('#' + o.menu).find('A').unbind('click');
+                                                       $('#' + o.menu).find('LI:not(.disabled) A').click( function() {
+                                                               $(document).unbind('click').unbind('keypress');
+                                                               $(".contextMenu").hide();
+                                                               // Callback
+                                                               if( callback ) callback( $(this).attr('href').substr(1), $(srcElement), {x: x - offset.left, y: y - offset.top, docX: x, docY: y} );
+                                                               return false;
+                                                       });
+                                                       
+                                                       // Hide bindings
+                                                       setTimeout( function() { // Delay for Mozilla
+                                                               $(document).click( function() {
+                                                                       $(document).unbind('click').unbind('keypress');
+                                                                       $(menu).fadeOut(o.outSpeed);
+                                                                       return false;
+                                                               });
+                                                       }, 0);
+                                               }
+                                       });
+                               });
+                               
+                               // Disable text selection
+                               if( $.browser.mozilla ) {
+                                       $('#' + o.menu).each( function() { $(this).css({ 'MozUserSelect' : 'none' }); });
+                               } else if( $.browser.msie ) {
+                                       $('#' + o.menu).each( function() { $(this).bind('selectstart.disableTextSelect', function() { return false; }); });
+                               } else {
+                                       $('#' + o.menu).each(function() { $(this).bind('mousedown.disableTextSelect', function() { return false; }); });
+                               }
+                               // Disable browser context menu (requires both selectors to work in IE/Safari + FF/Chrome)
+                               $(el).add('UL.contextMenu').bind('contextmenu', function() { return false; });
+                               
+                       });
+                       return $(this);
+               },
+               
+               // Disable context menu items on the fly
+               disableContextMenuItems: function(o) {
+                       if( o == undefined ) {
+                               // Disable all
+                               $(this).find('LI').addClass('disabled');
+                               return( $(this) );
+                       }
+                       $(this).each( function() {
+                               if( o != undefined ) {
+                                       var d = o.split(',');
+                                       for( var i = 0; i < d.length; i++ ) {
+                                               $(this).find('A[href="' + d[i] + '"]').parent().addClass('disabled');
+                                               
+                                       }
+                               }
+                       });
+                       return( $(this) );
+               },
+               
+               // Enable context menu items on the fly
+               enableContextMenuItems: function(o) {
+                       if( o == undefined ) {
+                               // Enable all
+                               $(this).find('LI.disabled').removeClass('disabled');
+                               return( $(this) );
+                       }
+                       $(this).each( function() {
+                               if( o != undefined ) {
+                                       var d = o.split(',');
+                                       for( var i = 0; i < d.length; i++ ) {
+                                               $(this).find('A[href="' + d[i] + '"]').parent().removeClass('disabled');
+                                               
+                                       }
+                               }
+                       });
+                       return( $(this) );
+               },
+               
+               // Disable context menu(s)
+               disableContextMenu: function() {
+                       $(this).each( function() {
+                               $(this).addClass('disabled');
+                       });
+                       return( $(this) );
+               },
+               
+               // Enable context menu(s)
+               enableContextMenu: function() {
+                       $(this).each( function() {
+                               $(this).removeClass('disabled');
+                       });
+                       return( $(this) );
+               },
+               
+               // Destroy context menu(s)
+               destroyContextMenu: function() {
+                       // Destroy specified context menus
+                       $(this).each( function() {
+                               // Disable action
+                               $(this).unbind('mousedown').unbind('mouseup');
+                       });
+                       return( $(this) );
+               }
+               
+       });
+})(jQuery);
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/plugins/jquery.cookie.js b/js2/mwEmbed/jquery/plugins/jquery.cookie.js
new file mode 100644 (file)
index 0000000..a80bfa2
--- /dev/null
@@ -0,0 +1,97 @@
+/**
+ * Cookie plugin
+ *
+ * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ */
+
+/**
+ * Create a cookie with the given name and value and other optional parameters.
+ *
+ * @example $.cookie('the_cookie', 'the_value');
+ * @desc Set the value of a cookie.
+ * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
+ * @desc Create a cookie with all available options.
+ * @example $.cookie('the_cookie', 'the_value');
+ * @desc Create a session cookie.
+ * @example $.cookie('the_cookie', null);
+ * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
+ *       used when the cookie was set.
+ *
+ * @param String name The name of the cookie.
+ * @param String value The value of the cookie.
+ * @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
+ * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
+ *                             If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
+ *                             If set to null or omitted, the cookie will be a session cookie and will not be retained
+ *                             when the the browser exits.
+ * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
+ * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
+ * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
+ *                        require a secure protocol (like HTTPS).
+ * @type undefined
+ *
+ * @name $.cookie
+ * @cat Plugins/Cookie
+ * @author Klaus Hartl/klaus.hartl@stilbuero.de
+ */
+
+/**
+ * Get the value of a cookie with the given name.
+ *
+ * @example $.cookie('the_cookie');
+ * @desc Get the value of a cookie.
+ *
+ * @param String name The name of the cookie.
+ * @return The value of the cookie.
+ * @type String
+ *
+ * @name $.cookie
+ * @cat Plugins/Cookie
+ * @author Klaus Hartl/klaus.hartl@stilbuero.de
+ */
+jQuery.cookie = function(name, value, options) {
+    if (typeof value != 'undefined') { // name and value given, set cookie
+        options = options || {};
+        if (value === null) {
+            value = '';
+            options = $.extend({}, options); // clone object since it's unexpected behavior if the expired property were changed
+            options.expires = -1;
+        }
+        var expires = '';
+        if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
+            var date;
+            if (typeof options.expires == 'number') {
+                date = new Date();
+                date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
+            } else {
+                date = options.expires;
+            }
+            expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
+        }
+        // NOTE Needed to parenthesize options.path and options.domain
+        // in the following expressions, otherwise they evaluate to undefined
+        // in the packed version for some reason...
+        var path = options.path ? '; path=' + (options.path) : '';
+        var domain = options.domain ? '; domain=' + (options.domain) : '';
+        var secure = options.secure ? '; secure' : '';
+        document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
+    } else { // only name given, get cookie
+        var cookieValue = null;
+        if (document.cookie && document.cookie != '') {
+            var cookies = document.cookie.split(';');
+            for (var i = 0; i < cookies.length; i++) {
+                var cookie = jQuery.trim(cookies[i]);
+                // Does this cookie string begin with the name we want?
+                if (cookie.substring(0, name.length + 1) == (name + '=')) {
+                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
+                    break;
+                }
+            }
+        }
+        return cookieValue;
+    }
+};
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/plugins/jquery.datePicker.js b/js2/mwEmbed/jquery/plugins/jquery.datePicker.js
new file mode 100644 (file)
index 0000000..f576c37
--- /dev/null
@@ -0,0 +1,1525 @@
+/**
+ * Copyright (c) 2007 Kelvin Luck (http://www.kelvinluck.com/)
+ * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
+ * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
+ *
+ * $Id: jquery.datePicker.js 3739 2007-10-25 13:55:30Z kelvin.luck $
+ **/
+
+(function($){
+
+       $.fn.extend({
+/**
+ * Render a calendar table into any matched elements.
+ *
+ * @param Object s (optional) Customize your calendars.
+ * @option Number month The month to render (NOTE that months are zero based). Default is today's month.
+ * @option Number year The year to render. Default is today's year.
+ * @option Function renderCallback A reference to a function that is called as each cell is rendered and which can add classes and event listeners to the created nodes. Default is no callback.
+ * @option Number showHeader Whether or not to show the header row, possible values are: $.dpConst.SHOW_HEADER_NONE (no header), $.dpConst.SHOW_HEADER_SHORT (first letter of each day) and $.dpConst.SHOW_HEADER_LONG (full name of each day). Default is $.dpConst.SHOW_HEADER_SHORT.
+ * @option String hoverClass The class to attach to each cell when you hover over it (to allow you to use hover effects in IE6 which doesn't support the :hover pseudo-class on elements other than links). Default is dp-hover. Pass false if you don't want a hover class.
+ * @type jQuery
+ * @name renderCalendar
+ * @cat plugins/datePicker
+ * @author Kelvin Luck (http://www.kelvinluck.com/)
+ *
+ * @example $('#calendar-me').renderCalendar({month:0, year:2007});
+ * @desc Renders a calendar displaying January 2007 into the element with an id of calendar-me.
+ *
+ * @example
+ * var testCallback = function($td, thisDate, month, year)
+ * {
+ * if ($td.is('.current-month') && thisDate.getDay() == 4) {
+ *             var d = thisDate.getDate();
+ *             $td.bind(
+ *                     'click',
+ *                     function()
+ *                     {
+ *                             alert('You clicked on ' + d + '/' + (Number(month)+1) + '/' + year);
+ *                     }
+ *             ).addClass('thursday');
+ *     } else if (thisDate.getDay() == 5) {
+ *             $td.html('Friday the ' + $td.html() + 'th');
+ *     }
+ * }
+ * $('#calendar-me').renderCalendar({month:0, year:2007, renderCallback:testCallback});
+ *
+ * @desc Renders a calendar displaying January 2007 into the element with an id of calendar-me. Every Thursday in the current month has a class of "thursday" applied to it, is clickable and shows an alert when clicked. Every Friday on the calendar has the number inside replaced with text.
+ **/
+               renderCalendar  :   function(s)
+               {
+                       var dc = function(a)
+                       {
+                               return document.createElement(a);
+                       };
+
+                       s = $.extend(
+                               {
+                                       month                   : null,
+                                       year                    : null,
+                                       renderCallback  : null,
+                                       showHeader              : $.dpConst.SHOW_HEADER_SHORT,
+                                       dpController    : null,
+                                       hoverClass              : 'dp-hover'
+                               }
+                               , s
+                       );
+
+                       if (s.showHeader != $.dpConst.SHOW_HEADER_NONE) {
+                               var headRow = $(dc('tr'));
+                               for (var i=Date.firstDayOfWeek; i<Date.firstDayOfWeek+7; i++) {
+                                       var weekday = i%7;
+                                       var day = Date.dayNames[weekday];
+                                       headRow.append(
+                                               jQuery(dc('th')).attr({'scope':'col', 'abbr':day, 'title':day, 'class':(weekday == 0 || weekday == 6 ? 'weekend' : 'weekday')}).html(s.showHeader == $.dpConst.SHOW_HEADER_SHORT ? day.substr(0, 1) : day)
+                                       );
+                               }
+                       };
+
+                       var calendarTable = $(dc('table'))
+                                                                       .attr(
+                                                                               {
+                                                                                       'cellspacing':2,
+                                                                                       'className':'jCalendar'
+                                                                               }
+                                                                       )
+                                                                       .append(
+                                                                               (s.showHeader != $.dpConst.SHOW_HEADER_NONE ?
+                                                                                       $(dc('thead'))
+                                                                                               .append(headRow)
+                                                                                       :
+                                                                                       dc('thead')
+                                                                               )
+                                                                       );
+                       var tbody = $(dc('tbody'));
+
+                       var today = (new Date()).zeroTime();
+
+                       var month = s.month == undefined ? today.getMonth() : s.month;
+                       var year = s.year || today.getFullYear();
+
+                       var currentDate = new Date(year, month, 1);
+
+
+                       var firstDayOffset = Date.firstDayOfWeek - currentDate.getDay() + 1;
+                       if (firstDayOffset > 1) firstDayOffset -= 7;
+                       var weeksToDraw = Math.ceil(( (-1*firstDayOffset+1) + currentDate.getDaysInMonth() ) /7);
+                       currentDate.addDays(firstDayOffset-1);
+
+                       var doHover = function()
+                       {
+                               if (s.hoverClass) {
+                                       $(this).addClass(s.hoverClass);
+                               }
+                       };
+                       var unHover = function()
+                       {
+                               if (s.hoverClass) {
+                                       $(this).removeClass(s.hoverClass);
+                               }
+                       };
+
+                       var w = 0;
+                       while (w++<weeksToDraw) {
+                               var r = jQuery(dc('tr'));
+                               for (var i=0; i<7; i++) {
+                                       var thisMonth = currentDate.getMonth() == month;
+                                       var d = $(dc('td'))
+                                                               .text(currentDate.getDate() + '')
+                                                               .attr('className', (thisMonth ? 'current-month ' : 'other-month ') +
+                                                                                                       (currentDate.isWeekend() ? 'weekend ' : 'weekday ') +
+                                                                                                       (thisMonth && currentDate.getTime() == today.getTime() ? 'today ' : '')
+                                                               )
+                                                               .hover(doHover, unHover)
+                                                       ;
+                                       if (s.renderCallback) {
+                                               s.renderCallback(d, currentDate, month, year);
+                                       }
+                                       r.append(d);
+                                       currentDate.addDays(1);
+                               }
+                               tbody.append(r);
+                       }
+                       calendarTable.append(tbody);
+
+                       return this.each(
+                               function()
+                               {
+                                       $(this).empty().append(calendarTable);
+                               }
+                       );
+               },
+/**
+ * Create a datePicker associated with each of the matched elements.
+ *
+ * The matched element will receive a few custom events with the following signatures:
+ *
+ * dateSelected(event, date, $td, status)
+ * Triggered when a date is selected. event is a reference to the event, date is the Date selected, $td is a jquery object wrapped around the TD that was clicked on and status is whether the date was selected (true) or deselected (false)
+ *
+ * dpClosed(event, selected)
+ * Triggered when the date picker is closed. event is a reference to the event and selected is an Array containing Date objects.
+ *
+ * dpMonthChanged(event, displayedMonth, displayedYear)
+ * Triggered when the month of the popped up calendar is changed. event is a reference to the event, displayedMonth is the number of the month now displayed (zero based) and displayedYear is the year of the month.
+ *
+ * dpDisplayed(event, $datePickerDiv)
+ * Triggered when the date picker is created. $datePickerDiv is the div containing the date picker. Use this event to add custom content/ listeners to the popped up date picker.
+ *
+ * @param Object s (optional) Customize your date pickers.
+ * @option Number month The month to render when the date picker is opened (NOTE that months are zero based). Default is today's month.
+ * @option Number year The year to render when the date picker is opened. Default is today's year.
+ * @option String startDate The first date date can be selected.
+ * @option String endDate The last date that can be selected.
+ * @option Boolean inline Whether to create the datePicker as inline (e.g. always on the page) or as a model popup. Default is false (== modal popup)
+ * @option Boolean createButton Whether to create a .dp-choose-date anchor directly after the matched element which when clicked will trigger the showing of the date picker. Default is true.
+ * @option Boolean showYearNavigation Whether to display buttons which allow the user to navigate through the months a year at a time. Default is true.
+ * @option Boolean closeOnSelect Whether to close the date picker when a date is selected. Default is true.
+ * @option Boolean displayClose Whether to create a "Close" button within the date picker popup. Default is false.
+ * @option Boolean selectMultiple Whether a user should be able to select multiple dates with this date picker. Default is false.
+ * @option Boolean clickInput If the matched element is an input type="text" and this option is true then clicking on the input will cause the date picker to appear.
+ * @option Number verticalPosition The vertical alignment of the popped up date picker to the matched element. One of $.dpConst.POS_TOP and $.dpConst.POS_BOTTOM. Default is $.dpConst.POS_TOP.
+ * @option Number horizontalPosition The horizontal alignment of the popped up date picker to the matched element. One of $.dpConst.POS_LEFT and $.dpConst.POS_RIGHT.
+ * @option Number verticalOffset The number of pixels offset from the defined verticalPosition of this date picker that it should pop up in. Default in 0.
+ * @option Number horizontalOffset The number of pixels offset from the defined horizontalPosition of this date picker that it should pop up in. Default in 0.
+ * @option (Function|Array) renderCallback A reference to a function (or an array of separate functions) that is called as each cell is rendered and which can add classes and event listeners to the created nodes. Each callback function will receive four arguments; a jquery object wrapping the created TD, a Date object containing the date this TD represents, a number giving the currently rendered month and a number giving the currently rendered year. Default is no callback.
+ * @option String hoverClass The class to attach to each cell when you hover over it (to allow you to use hover effects in IE6 which doesn't support the :hover pseudo-class on elements other than links). Default is dp-hover. Pass false if you don't want a hover class.
+ * @type jQuery
+ * @name datePicker
+ * @cat plugins/datePicker
+ * @author Kelvin Luck (http://www.kelvinluck.com/)
+ *
+ * @example $('input.date-picker').datePicker();
+ * @desc Creates a date picker button next to all matched input elements. When the button is clicked on the value of the selected date will be placed in the corresponding input (formatted according to Date.format).
+ *
+ * @example demo/index.html
+ * @desc See the projects homepage for many more complex examples...
+ **/
+               datePicker : function(s)
+               {
+                       if (!$.event._dpCache) $.event._dpCache = [];
+
+                       // initialise the date picker controller with the relevant settings...
+                       s = $.extend(
+                               {
+                                       month                           : undefined,
+                                       year                            : undefined,
+                                       startDate                       : undefined,
+                                       endDate                         : undefined,
+                                       inline                          : false,
+                                       renderCallback          : [],
+                                       createButton            : true,
+                                       showYearNavigation      : true,
+                                       closeOnSelect           : true,
+                                       displayClose            : false,
+                                       selectMultiple          : false,
+                                       clickInput                      : false,
+                                       verticalPosition        : $.dpConst.POS_TOP,
+                                       horizontalPosition      : $.dpConst.POS_LEFT,
+                                       verticalOffset          : 0,
+                                       horizontalOffset        : 0,
+                                       hoverClass                      : 'dp-hover'
+                               }
+                               , s
+                       );
+
+                       return this.each(
+                               function()
+                               {
+                                       var $this = $(this);
+                                       var alreadyExists = true;
+
+                                       if (!this._dpId) {
+                                               this._dpId = $.event.guid++;
+                                               $.event._dpCache[this._dpId] = new DatePicker(this);
+                                               alreadyExists = false;
+                                       }
+
+                                       if (s.inline) {
+                                               s.createButton = false;
+                                               s.displayClose = false;
+                                               s.closeOnSelect = false;
+                                               $this.empty();
+                                       }
+
+                                       var controller = $.event._dpCache[this._dpId];
+
+                                       controller.init(s);
+
+                                       if (!alreadyExists && s.createButton) {
+                                               // create it!
+                                               controller.button = $('<a href="#" class="dp-choose-date" title="' + $.dpText.TEXT_CHOOSE_DATE + '">' + $.dpText.TEXT_CHOOSE_DATE + '</a>')
+                                                               .bind(
+                                                                       'click',
+                                                                       function()
+                                                                       {
+                                                                               $this.dpDisplay(this);
+                                                                               this.blur();
+                                                                               return false;
+                                                                       }
+                                                               );
+                                               $this.after(controller.button);
+                                       }
+
+                                       if (!alreadyExists && $this.is(':text')) {
+                                               $this
+                                                       .bind(
+                                                               'dateSelected',
+                                                               function(e, selectedDate, $td)
+                                                               {
+                                                                       this.value = selectedDate.asString();
+                                                               }
+                                                       ).bind(
+                                                               'change',
+                                                               function()
+                                                               {
+                                                                       var d = Date.fromString(this.value);
+                                                                       if (d) {
+                                                                               controller.setSelected(d, true, true);
+                                                                       }
+                                                               }
+                                                       );
+                                               if (s.clickInput) {
+                                                       $this.bind(
+                                                               'click',
+                                                               function()
+                                                               {
+                                                                       $this.dpDisplay();
+                                                               }
+                                                       );
+                                               }
+                                               var d = Date.fromString(this.value);
+                                               if (this.value != '' && d) {
+                                                       controller.setSelected(d, true, true);
+                                               }
+                                       }
+
+                                       $this.addClass('dp-applied');
+
+                               }
+                       )
+               },
+/**
+ * Disables or enables this date picker
+ *
+ * @param Boolean s Whether to disable (true) or enable (false) this datePicker
+ * @type jQuery
+ * @name dpSetDisabled
+ * @cat plugins/datePicker
+ * @author Kelvin Luck (http://www.kelvinluck.com/)
+ *
+ * @example $('.date-picker').datePicker();
+ * $('.date-picker').dpSetDisabled(true);
+ * @desc Prevents this date picker from displaying and adds a class of dp-disabled to it (and it's associated button if it has one) for styling purposes. If the matched element is an input field then it will also set the disabled attribute to stop people directly editing the field.
+ **/
+               dpSetDisabled : function(s)
+               {
+                       return _w.call(this, 'setDisabled', s);
+               },
+/**
+ * Updates the first selectable date for any date pickers on any matched elements.
+ *
+ * @param String d A string representing the first selectable date (formatted according to Date.format).
+ * @type jQuery
+ * @name dpSetStartDate
+ * @cat plugins/datePicker
+ * @author Kelvin Luck (http://www.kelvinluck.com/)
+ *
+ * @example $('.date-picker').datePicker();
+ * $('.date-picker').dpSetStartDate('01/01/2000');
+ * @desc Creates a date picker associated with all elements with a class of "date-picker" then sets the first selectable date for each of these to the first day of the millenium.
+ **/
+               dpSetStartDate : function(d)
+               {
+                       return _w.call(this, 'setStartDate', d);
+               },
+/**
+ * Updates the last selectable date for any date pickers on any matched elements.
+ *
+ * @param String d A string representing the last selectable date (formatted according to Date.format).
+ * @type jQuery
+ * @name dpSetEndDate
+ * @cat plugins/datePicker
+ * @author Kelvin Luck (http://www.kelvinluck.com/)
+ *
+ * @example $('.date-picker').datePicker();
+ * $('.date-picker').dpSetEndDate('01/01/2010');
+ * @desc Creates a date picker associated with all elements with a class of "date-picker" then sets the last selectable date for each of these to the first Janurary 2010.
+ **/
+               dpSetEndDate : function(d)
+               {
+                       return _w.call(this, 'setEndDate', d);
+               },
+/**
+ * Gets a list of Dates currently selected by this datePicker. This will be an empty array if no dates are currently selected or NULL if there is no datePicker associated with the matched element.
+ *
+ * @type Array
+ * @name dpGetSelected
+ * @cat plugins/datePicker
+ * @author Kelvin Luck (http://www.kelvinluck.com/)
+ *
+ * @example $('.date-picker').datePicker();
+ * alert($('.date-picker').dpGetSelected());
+ * @desc Will alert an empty array (as nothing is selected yet)
+ **/
+               dpGetSelected : function()
+               {
+                       var c = _getController(this[0]);
+                       if (c) {
+                               return c.getSelected();
+                       }
+                       return null;
+               },
+/**
+ * Selects or deselects a date on any matched element's date pickers. Deselcting is only useful on date pickers where selectMultiple==true. Selecting will only work if the passed date is within the startDate and endDate boundries for a given date picker.
+ *
+ * @param String d A string representing the date you want to select (formatted according to Date.format).
+ * @param Boolean v Whether you want to select (true) or deselect (false) this date. Optional - default = true.
+ * @param Boolean m Whether you want the date picker to open up on the month of this date when it is next opened. Optional - default = true.
+ * @type jQuery
+ * @name dpSetSelected
+ * @cat plugins/datePicker
+ * @author Kelvin Luck (http://www.kelvinluck.com/)
+ *
+ * @example $('.date-picker').datePicker();
+ * $('.date-picker').dpSetSelected('01/01/2010');
+ * @desc Creates a date picker associated with all elements with a class of "date-picker" then sets the selected date on these date pickers to the first Janurary 2010. When the date picker is next opened it will display Janurary 2010.
+ **/
+               dpSetSelected : function(d, v, m)
+               {
+                       if (v == undefined) v=true;
+                       if (m == undefined) m=true;
+                       return _w.call(this, 'setSelected', Date.fromString(d), v, m);
+               },
+/**
+ * Sets the month that will be displayed when the date picker is next opened. If the passed month is before startDate then the month containing startDate will be displayed instead. If the passed month is after endDate then the month containing the endDate will be displayed instead.
+ *
+ * @param Number m The month you want the date picker to display. Optional - defaults to the currently displayed month.
+ * @param Number y The year you want the date picker to display. Optional - defaults to the currently displayed year.
+ * @type jQuery
+ * @name dpSetDisplayedMonth
+ * @cat plugins/datePicker
+ * @author Kelvin Luck (http://www.kelvinluck.com/)
+ *
+ * @example $('.date-picker').datePicker();
+ * $('.date-picker').dpSetDisplayedMonth(10, 2008);
+ * @desc Creates a date picker associated with all elements with a class of "date-picker" then sets the selected date on these date pickers to the first Janurary 2010. When the date picker is next opened it will display Janurary 2010.
+ **/
+               dpSetDisplayedMonth : function(m, y)
+               {
+                       return _w.call(this, 'setDisplayedMonth', Number(m), Number(y));
+               },
+/**
+ * Displays the date picker associated with the matched elements. Since only one date picker can be displayed at once then the date picker associated with the last matched element will be the one that is displayed.
+ *
+ * @param HTMLElement e An element that you want the date picker to pop up relative in position to. Optional - default behaviour is to pop up next to the element associated with this date picker.
+ * @type jQuery
+ * @name dpDisplay
+ * @cat plugins/datePicker
+ * @author Kelvin Luck (http://www.kelvinluck.com/)
+ *
+ * @example $('#date-picker').datePicker();
+ * $('#date-picker').dpDisplay();
+ * @desc Creates a date picker associated with the element with an id of date-picker and then causes it to pop up.
+ **/
+               dpDisplay : function(e)
+               {
+                       return _w.call(this, 'display', e);
+               },
+/**
+ * Sets a function or array of functions that is called when each TD of the date picker popup is rendered to the page
+ *
+ * @param (Function|Array) a A function or an array of functions that are called when each td is rendered. Each function will receive four arguments; a jquery object wrapping the created TD, a Date object containing the date this TD represents, a number giving the currently rendered month and a number giving the currently rendered year.
+ * @type jQuery
+ * @name dpSetRenderCallback
+ * @cat plugins/datePicker
+ * @author Kelvin Luck (http://www.kelvinluck.com/)
+ *
+ * @example $('#date-picker').datePicker();
+ * $('#date-picker').dpSetRenderCallback(function($td, thisDate, month, year)
+ * {
+ *     // do stuff as each td is rendered dependant on the date in the td and the displayed month and year
+ * });
+ * @desc Creates a date picker associated with the element with an id of date-picker and then creates a function which is called as each td is rendered when this date picker is displayed.
+ **/
+               dpSetRenderCallback : function(a)
+               {
+                       return _w.call(this, 'setRenderCallback', a);
+               },
+/**
+ * Sets the position that the datePicker will pop up (relative to it's associated element)
+ *
+ * @param Number v The vertical alignment of the created date picker to it's associated element. Possible values are $.dpConst.POS_TOP and $.dpConst.POS_BOTTOM
+ * @param Number h The horizontal alignment of the created date picker to it's associated element. Possible values are $.dpConst.POS_LEFT and $.dpConst.POS_RIGHT
+ * @type jQuery
+ * @name dpSetPosition
+ * @cat plugins/datePicker
+ * @author Kelvin Luck (http://www.kelvinluck.com/)
+ *
+ * @example $('#date-picker').datePicker();
+ * $('#date-picker').dpSetPosition($.dpConst.POS_BOTTOM, $.dpConst.POS_RIGHT);
+ * @desc Creates a date picker associated with the element with an id of date-picker and makes it so that when this date picker pops up it will be bottom and right aligned to the #date-picker element.
+ **/
+               dpSetPosition : function(v, h)
+               {
+                       return _w.call(this, 'setPosition', v, h);
+               },
+/**
+ * Sets the offset that the popped up date picker will have from it's default position relative to it's associated element (as set by dpSetPosition)
+ *
+ * @param Number v The vertical offset of the created date picker.
+ * @param Number h The horizontal offset of the created date picker.
+ * @type jQuery
+ * @name dpSetOffset
+ * @cat plugins/datePicker
+ * @author Kelvin Luck (http://www.kelvinluck.com/)
+ *
+ * @example $('#date-picker').datePicker();
+ * $('#date-picker').dpSetOffset(-20, 200);
+ * @desc Creates a date picker associated with the element with an id of date-picker and makes it so that when this date picker pops up it will be 20 pixels above and 200 pixels to the right of it's default position.
+ **/
+               dpSetOffset : function(v, h)
+               {
+                       return _w.call(this, 'setOffset', v, h);
+               },
+/**
+ * Closes the open date picker associated with this element.
+ *
+ * @type jQuery
+ * @name dpClose
+ * @cat plugins/datePicker
+ * @author Kelvin Luck (http://www.kelvinluck.com/)
+ *
+ * @example $('.date-pick')
+ *             .datePicker()
+ *             .bind(
+ *                     'focus',
+ *                     function()
+ *                     {
+ *                             $(this).dpDisplay();
+ *                     }
+ *             ).bind(
+ *                     'blur',
+ *                     function()
+ *                     {
+ *                             $(this).dpClose();
+ *                     }
+ *             );
+ * @desc Creates a date picker and makes it appear when the relevant element is focused and disappear when it is blurred.
+ **/
+               dpClose : function()
+               {
+                       return _w.call(this, '_closeCalendar', false, this[0]);
+               },
+               // private function called on unload to clean up any expandos etc and prevent memory links...
+               _dpDestroy : function()
+               {
+                       // TODO - implement this?
+               }
+       });
+
+       // private internal function to cut down on the amount of code needed where we forward
+       // dp* methods on the jQuery object on to the relevant DatePicker controllers...
+       var _w = function(f, a1, a2, a3)
+       {
+               return this.each(
+                       function()
+                       {
+                               var c = _getController(this);
+                               if (c) {
+                                       c[f](a1, a2, a3);
+                               }
+                       }
+               );
+       };
+
+       function DatePicker(ele)
+       {
+               this.ele = ele;
+
+               // initial values...
+               this.displayedMonth             =       null;
+               this.displayedYear              =       null;
+               this.startDate                  =       null;
+               this.endDate                    =       null;
+               this.showYearNavigation =       null;
+               this.closeOnSelect              =       null;
+               this.displayClose               =       null;
+               this.selectMultiple             =       null;
+               this.verticalPosition   =       null;
+               this.horizontalPosition =       null;
+               this.verticalOffset             =       null;
+               this.horizontalOffset   =       null;
+               this.button                             =       null;
+               this.renderCallback             =       [];
+               this.selectedDates              =       {};
+               this.inline                             =       null;
+               this.context                    =       '#dp-popup';
+       };
+       $.extend(
+               DatePicker.prototype,
+               {
+                       init : function(s)
+                       {
+                               this.setStartDate(s.startDate);
+                               this.setEndDate(s.endDate);
+                               this.setDisplayedMonth(Number(s.month), Number(s.year));
+                               this.setRenderCallback(s.renderCallback);
+                               this.showYearNavigation = s.showYearNavigation;
+                               this.closeOnSelect = s.closeOnSelect;
+                               this.displayClose = s.displayClose;
+                               this.selectMultiple = s.selectMultiple;
+                               this.verticalPosition = s.verticalPosition;
+                               this.horizontalPosition = s.horizontalPosition;
+                               this.hoverClass = s.hoverClass;
+                               this.setOffset(s.verticalOffset, s.horizontalOffset);
+                               this.inline = s.inline;
+                               if (this.inline) {
+                                       this.context = this.ele;
+                                       this.display();
+                               }
+                       },
+                       setStartDate : function(d)
+                       {
+                               if (d) {
+                                       this.startDate = Date.fromString(d);
+                               }
+                               if (!this.startDate) {
+                                       this.startDate = (new Date()).zeroTime();
+                               }
+                               this.setDisplayedMonth(this.displayedMonth, this.displayedYear);
+                       },
+                       setEndDate : function(d)
+                       {
+                               if (d) {
+                                       this.endDate = Date.fromString(d);
+                               }
+                               if (!this.endDate) {
+                                       this.endDate = (new Date('12/31/2999')); // using the JS Date.parse function which expects mm/dd/yyyy
+                               }
+                               if (this.endDate.getTime() < this.startDate.getTime()) {
+                                       this.endDate = this.startDate;
+                               }
+                               this.setDisplayedMonth(this.displayedMonth, this.displayedYear);
+                       },
+                       setPosition : function(v, h)
+                       {
+                               this.verticalPosition = v;
+                               this.horizontalPosition = h;
+                       },
+                       setOffset : function(v, h)
+                       {
+                               this.verticalOffset = parseInt(v) || 0;
+                               this.horizontalOffset = parseInt(h) || 0;
+                       },
+                       setDisabled : function(s)
+                       {
+                               $e = $(this.ele);
+                               $e[s ? 'addClass' : 'removeClass']('dp-disabled');
+                               if (this.button) {
+                                       $but = $(this.button);
+                                       $but[s ? 'addClass' : 'removeClass']('dp-disabled');
+                                       $but.attr('title', s ? '' : $.dpText.TEXT_CHOOSE_DATE);
+                               }
+                               if ($e.is(':text')) {
+                                       $e.attr('disabled', s ? 'disabled' : '');
+                               }
+                       },
+                       setDisplayedMonth : function(m, y)
+                       {
+                               if (this.startDate == undefined || this.endDate == undefined) {
+                                       return;
+                               }
+                               var s = new Date(this.startDate.getTime());
+                               s.setDate(1);
+                               var e = new Date(this.endDate.getTime());
+                               e.setDate(1);
+
+                               var t;
+                               if ((!m && !y) || (isNaN(m) && isNaN(y))) {
+                                       // no month or year passed - default to current month
+                                       t = new Date().zeroTime();
+                                       t.setDate(1);
+                               } else if (isNaN(m)) {
+                                       // just year passed in - presume we want the displayedMonth
+                                       t = new Date(y, this.displayedMonth, 1);
+                               } else if (isNaN(y)) {
+                                       // just month passed in - presume we want the displayedYear
+                                       t = new Date(this.displayedYear, m, 1);
+                               } else {
+                                       // year and month passed in - that's the date we want!
+                                       t = new Date(y, m, 1)
+                               }
+
+                               // check if the desired date is within the range of our defined startDate and endDate
+                               if (t.getTime() < s.getTime()) {
+                                       t = s;
+                               } else if (t.getTime() > e.getTime()) {
+                                       t = e;
+                               }
+                               this.displayedMonth = t.getMonth();
+                               this.displayedYear = t.getFullYear();
+                       },
+                       setSelected : function(d, v, moveToMonth)
+                       {
+                               if (this.selectMultiple == false) {
+                                       this.selectedDates = {};
+                                       $('td.selected', this.context).removeClass('selected');
+                               }
+                               if (moveToMonth) {
+                                       this.setDisplayedMonth(d.getMonth(), d.getFullYear());
+                               }
+                               this.selectedDates[d.toString()] = v;
+                       },
+                       isSelected : function(d)
+                       {
+                               return this.selectedDates[d.toString()];
+                       },
+                       getSelected : function()
+                       {
+                               var r = [];
+                               for(s in this.selectedDates) {
+                                       if (this.selectedDates[s] == true) {
+                                               r.push(Date.parse(s));
+                                       }
+                               }
+                               return r;
+                       },
+                       display : function(eleAlignTo)
+                       {
+                               if ($(this.ele).is('.dp-disabled')) return;
+
+                               eleAlignTo = eleAlignTo || this.ele;
+                               var c = this;
+                               var $ele = $(eleAlignTo);
+                               var eleOffset = $ele.offset();
+
+                               var $createIn;
+                               var attrs;
+                               var attrsCalendarHolder;
+                               var cssRules;
+
+                               if (c.inline) {
+                                       $createIn = $(this.ele);
+                                       attrs = {
+                                               'id'            :       'calendar-' + this.ele._dpId,
+                                               'className'     :       'dp-popup dp-popup-inline'
+                                       };
+                                       cssRules = {
+                                       };
+                               } else {
+                                       $createIn = $('body');
+                                       attrs = {
+                                               'id'            :       'dp-popup',
+                                               'className'     :       'dp-popup'
+                                       };
+                                       cssRules = {
+                                               'top'   :       eleOffset.top + c.verticalOffset,
+                                               'left'  :       eleOffset.left + c.horizontalOffset
+                                       };
+
+                                       var _checkMouse = function(e)
+                                       {
+                                               var el = e.target;
+                                               var cal = $('#dp-popup')[0];
+
+                                               while (true){
+                                                       if (el == cal) {
+                                                               return true;
+                                                       } else if (el == document) {
+                                                               c._closeCalendar();
+                                                               return false;
+                                                       } else {
+                                                               el = $(el).parent()[0];
+                                                       }
+                                               }
+                                       };
+                                       this._checkMouse = _checkMouse;
+
+                                       this._closeCalendar(true);
+                               }
+
+
+                               $createIn
+                                       .append(
+                                               $('<div></div>')
+                                                       .attr(attrs)
+                                                       .css(cssRules)
+                                                       .append(
+                                                               $('<h2></h2>'),
+                                                               $('<div class="dp-nav-prev"></div>')
+                                                                       .append(
+                                                                               $('<a class="dp-nav-prev-year" href="#" title="' + $.dpText.TEXT_PREV_YEAR + '">&lt;&lt;</a>')
+                                                                                       .bind(
+                                                                                               'click',
+                                                                                               function()
+                                                                                               {
+                                                                                                       return c._displayNewMonth.call(c, this, 0, -1);
+                                                                                               }
+                                                                                       ),
+                                                                               $('<a class="dp-nav-prev-month" href="#" title="' + $.dpText.TEXT_PREV_MONTH + '">&lt;</a>')
+                                                                                       .bind(
+                                                                                               'click',
+                                                                                               function()
+                                                                                               {
+                                                                                                       return c._displayNewMonth.call(c, this, -1, 0);
+                                                                                               }
+                                                                                       )
+                                                                       ),
+                                                               $('<div class="dp-nav-next"></div>')
+                                                                       .append(
+                                                                               $('<a class="dp-nav-next-year" href="#" title="' + $.dpText.TEXT_NEXT_YEAR + '">&gt;&gt;</a>')
+                                                                                       .bind(
+                                                                                               'click',
+                                                                                               function()
+                                                                                               {
+                                                                                                       return c._displayNewMonth.call(c, this, 0, 1);
+                                                                                               }
+                                                                                       ),
+                                                                               $('<a class="dp-nav-next-month" href="#" title="' + $.dpText.TEXT_NEXT_MONTH + '">&gt;</a>')
+                                                                                       .bind(
+                                                                                               'click',
+                                                                                               function()
+                                                                                               {
+                                                                                                       return c._displayNewMonth.call(c, this, 1, 0);
+                                                                                               }
+                                                                                       )
+                                                                       ),
+                                                               $('<div></div>')
+                                                                       .attr('className', 'dp-calendar')
+                                                       )
+                                                       .bgIframe()
+                                               );
+
+                               var $pop = this.inline ? $('.dp-popup', this.context) : $('#dp-popup');
+
+                               if (this.showYearNavigation == false) {
+                                       $('.dp-nav-prev-year, .dp-nav-next-year', c.context).css('display', 'none');
+                               }
+                               if (this.displayClose) {
+                                       $pop.append(
+                                               $('<a href="#" id="dp-close">' + $.dpText.TEXT_CLOSE + '</a>')
+                                                       .bind(
+                                                               'click',
+                                                               function()
+                                                               {
+                                                                       c._closeCalendar();
+                                                                       return false;
+                                                               }
+                                                       )
+                                       );
+                               }
+                               c._renderCalendar();
+
+                               $(this.ele).trigger('dpDisplayed', $pop);
+
+                               if (!c.inline) {
+                                       if (this.verticalPosition == $.dpConst.POS_BOTTOM) {
+                                               $pop.css('top', eleOffset.top + $ele.height() - $pop.height() + c.verticalOffset);
+                                       }
+                                       if (this.horizontalPosition == $.dpConst.POS_RIGHT) {
+                                               $pop.css('left', eleOffset.left + $ele.width() - $pop.width() + c.horizontalOffset);
+                                       }
+                                       $(document).bind('mousedown', this._checkMouse);
+                               }
+                       },
+                       setRenderCallback : function(a)
+                       {
+                               if (a && typeof(a) == 'function') {
+                                       a = [a];
+                               }
+                               this.renderCallback = this.renderCallback.concat(a);
+                       },
+                       cellRender : function ($td, thisDate, month, year) {
+                               var c = this.dpController;
+                               var d = new Date(thisDate.getTime());
+
+                               // add our click handlers to deal with it when the days are clicked...
+
+                               $td.bind(
+                                       'click',
+                                       function()
+                                       {
+                                               var $this = $(this);
+                                               if (!$this.is('.disabled')) {
+                                                       c.setSelected(d, !$this.is('.selected') || !c.selectMultiple);
+                                                       var s = c.isSelected(d);
+                                                       $(c.ele).trigger('dateSelected', [d, $td, s]);
+                                                       $(c.ele).trigger('change');
+                                                       if (c.closeOnSelect) {
+                                                               c._closeCalendar();
+                                                       } else {
+                                                               $this[s ? 'addClass' : 'removeClass']('selected');
+                                                       }
+                                               }
+                                       }
+                               );
+
+                               if (c.isSelected(d)) {
+                                       $td.addClass('selected');
+                               }
+
+                               // call any extra renderCallbacks that were passed in
+                               for (var i=0; i<c.renderCallback.length; i++) {
+                                       c.renderCallback[i].apply(this, arguments);
+                               }
+
+
+                       },
+                       // ele is the clicked button - only proceed if it doesn't have the class disabled...
+                       // m and y are -1, 0 or 1 depending which direction we want to go in...
+                       _displayNewMonth : function(ele, m, y)
+                       {
+                               if (!$(ele).is('.disabled')) {
+                                       this.setDisplayedMonth(this.displayedMonth + m, this.displayedYear + y);
+                                       this._clearCalendar();
+                                       this._renderCalendar();
+                                       $(this.ele).trigger('dpMonthChanged', [this.displayedMonth, this.displayedYear]);
+                               }
+                               ele.blur();
+                               return false;
+                       },
+                       _renderCalendar : function()
+                       {
+                               // set the title...
+                               $('h2', this.context).html(Date.monthNames[this.displayedMonth] + ' ' + this.displayedYear);
+
+                               // render the calendar...
+                               $('.dp-calendar', this.context).renderCalendar(
+                                       {
+                                               month                   : this.displayedMonth,
+                                               year                    : this.displayedYear,
+                                               renderCallback  : this.cellRender,
+                                               dpController    : this,
+                                               hoverClass              : this.hoverClass
+                                       }
+                               );
+
+                               // update the status of the control buttons and disable dates before startDate or after endDate...
+                               // TODO: When should the year buttons be disabled? When you can't go forward a whole year from where you are or is that annoying?
+                               if (this.displayedYear == this.startDate.getFullYear() && this.displayedMonth == this.startDate.getMonth()) {
+                                       $('.dp-nav-prev-year', this.context).addClass('disabled');
+                                       $('.dp-nav-prev-month', this.context).addClass('disabled');
+                                       $('.dp-calendar td.other-month', this.context).each(
+                                               function()
+                                               {
+                                                       var $this = $(this);
+                                                       if (Number($this.text()) > 20) {
+                                                               $this.addClass('disabled');
+                                                       }
+                                               }
+                                       );
+                                       var d = this.startDate.getDate();
+                                       $('.dp-calendar td.current-month', this.context).each(
+                                               function()
+                                               {
+                                                       var $this = $(this);
+                                                       if (Number($this.text()) < d) {
+                                                               $this.addClass('disabled');
+                                                       }
+                                               }
+                                       );
+                               } else {
+                                       $('.dp-nav-prev-year', this.context).removeClass('disabled');
+                                       $('.dp-nav-prev-month', this.context).removeClass('disabled');
+                                       var d = this.startDate.getDate();
+                                       if (d > 20) {
+                                               // check if the startDate is last month as we might need to add some disabled classes...
+                                               var sd = new Date(this.startDate.getTime());
+                                               sd.addMonths(1);
+                                               if (this.displayedYear == sd.getFullYear() && this.displayedMonth == sd.getMonth()) {
+                                                       $('dp-calendar td.other-month', this.context).each(
+                                                               function()
+                                                               {
+                                                                       var $this = $(this);
+                                                                       if (Number($this.text()) < d) {
+                                                                               $this.addClass('disabled');
+                                                                       }
+                                                               }
+                                                       );
+                                               }
+                                       }
+                               }
+                               if (this.displayedYear == this.endDate.getFullYear() && this.displayedMonth == this.endDate.getMonth()) {
+                                       $('.dp-nav-next-year', this.context).addClass('disabled');
+                                       $('.dp-nav-next-month', this.context).addClass('disabled');
+                                       $('.dp-calendar td.other-month', this.context).each(
+                                               function()
+                                               {
+                                                       var $this = $(this);
+                                                       if (Number($this.text()) < 14) {
+                                                               $this.addClass('disabled');
+                                                       }
+                                               }
+                                       );
+                                       var d = this.endDate.getDate();
+                                       $('.dp-calendar td.current-month', this.context).each(
+                                               function()
+                                               {
+                                                       var $this = $(this);
+                                                       if (Number($this.text()) > d) {
+                                                               $this.addClass('disabled');
+                                                       }
+                                               }
+                                       );
+                               } else {
+                                       $('.dp-nav-next-year', this.context).removeClass('disabled');
+                                       $('.dp-nav-next-month', this.context).removeClass('disabled');
+                                       var d = this.endDate.getDate();
+                                       if (d < 13) {
+                                               // check if the endDate is next month as we might need to add some disabled classes...
+                                               var ed = new Date(this.endDate.getTime());
+                                               ed.addMonths(-1);
+                                               if (this.displayedYear == ed.getFullYear() && this.displayedMonth == ed.getMonth()) {
+                                                       $('.dp-calendar td.other-month', this.context).each(
+                                                               function()
+                                                               {
+                                                                       var $this = $(this);
+                                                                       if (Number($this.text()) > d) {
+                                                                               $this.addClass('disabled');
+                                                                       }
+                                                               }
+                                                       );
+                                               }
+                                       }
+                               }
+                       },
+                       _closeCalendar : function(programatic, ele)
+                       {
+                               if (!ele || ele == this.ele)
+                               {
+                                       $(document).unbind('mousedown', this._checkMouse);
+                                       this._clearCalendar();
+                                       $('#dp-popup a').unbind();
+                                       $('#dp-popup').empty().remove();
+                                       if (!programatic) {
+                                               $(this.ele).trigger('dpClosed', [this.getSelected()]);
+                                       }
+                               }
+                       },
+                       // empties the current dp-calendar div and makes sure that all events are unbound
+                       // and expandos removed to avoid memory leaks...
+                       _clearCalendar : function()
+                       {
+                               // TODO.
+                               $('.dp-calendar td', this.context).unbind();
+                               $('.dp-calendar', this.context).empty();
+                       }
+               }
+       );
+
+       // static constants
+       $.dpConst = {
+               SHOW_HEADER_NONE        :       0,
+               SHOW_HEADER_SHORT       :       1,
+               SHOW_HEADER_LONG        :       2,
+               POS_TOP                         :       0,
+               POS_BOTTOM                      :       1,
+               POS_LEFT                        :       0,
+               POS_RIGHT                       :       1
+       };
+       // localisable text
+       $.dpText = {
+               TEXT_PREV_YEAR          :       'Previous year',
+               TEXT_PREV_MONTH         :       'Previous month',
+               TEXT_NEXT_YEAR          :       'Next year',
+               TEXT_NEXT_MONTH         :       'Next month',
+               TEXT_CLOSE                      :       'Close',
+               TEXT_CHOOSE_DATE        :       'Choose date'
+       };
+       // version
+       $.dpVersion = '$Id: jquery.datePicker.js 3739 2007-10-25 13:55:30Z kelvin.luck $';
+
+       function _getController(ele)
+       {
+               if (ele._dpId) return $.event._dpCache[ele._dpId];
+               return false;
+       };
+
+       // make it so that no error is thrown if bgIframe plugin isn't included (allows you to use conditional
+       // comments to only include bgIframe where it is needed in IE without breaking this plugin).
+       if ($.fn.bgIframe == undefined) {
+               $.fn.bgIframe = function() {return this; };
+       };
+
+
+       // clean-up
+       $(window)
+               .bind('unload', function() {
+                       var els = $.event._dpCache || [];
+                       for (var i in els) {
+                               $(els[i].ele)._dpDestroy();
+                       }
+               });
+
+
+})(jQuery);
+
+
+/*
+ * Date prototype extensions. Doesn't depend on any
+ * other code. Doens't overwrite existing methods.
+ *
+ * Adds dayNames, abbrDayNames, monthNames and abbrMonthNames static properties and isLeapYear,
+ * isWeekend, isWeekDay, getDaysInMonth, getDayName, getMonthName, getDayOfYear, getWeekOfYear,
+ * setDayOfYear, addYears, addMonths, addDays, addHours, addMinutes, addSeconds methods
+ *
+ * Copyright (c) 2006 Jörn Zaefferer and Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
+ *
+ * Additional methods and properties added by Kelvin Luck: firstDayOfWeek, dateFormat, zeroTime, asString, fromString -
+ * I've added my name to these methods so you know who to blame if they are broken!
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *   http://www.gnu.org/licenses/gpl.html
+ *
+ */
+
+/**
+ * An Array of day names starting with Sunday.
+ *
+ * @example dayNames[0]
+ * @result 'Sunday'
+ *
+ * @name dayNames
+ * @type Array
+ * @cat Plugins/Methods/Date
+ */
+Date.dayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
+
+/**
+ * An Array of abbreviated day names starting with Sun.
+ *
+ * @example abbrDayNames[0]
+ * @result 'Sun'
+ *
+ * @name abbrDayNames
+ * @type Array
+ * @cat Plugins/Methods/Date
+ */
+Date.abbrDayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
+
+/**
+ * An Array of month names starting with Janurary.
+ *
+ * @example monthNames[0]
+ * @result 'January'
+ *
+ * @name monthNames
+ * @type Array
+ * @cat Plugins/Methods/Date
+ */
+Date.monthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
+
+/**
+ * An Array of abbreviated month names starting with Jan.
+ *
+ * @example abbrMonthNames[0]
+ * @result 'Jan'
+ *
+ * @name monthNames
+ * @type Array
+ * @cat Plugins/Methods/Date
+ */
+Date.abbrMonthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
+
+/**
+ * The first day of the week for this locale.
+ *
+ * @name firstDayOfWeek
+ * @type Number
+ * @cat Plugins/Methods/Date
+ * @author Kelvin Luck
+ */
+Date.firstDayOfWeek = 1;
+
+/**
+ * The format that string dates should be represented as (e.g. 'dd/mm/yyyy' for UK, 'mm/dd/yyyy' for US, 'yyyy-mm-dd' for Unicode etc).
+ *
+ * @name format
+ * @type String
+ * @cat Plugins/Methods/Date
+ * @author Kelvin Luck
+ */
+Date.format = 'dd/mm/yyyy';
+//Date.format = 'mm/dd/yyyy';
+//Date.format = 'yyyy-mm-dd';
+//Date.format = 'dd mmm yy';
+
+/**
+ * The first two numbers in the century to be used when decoding a two digit year. Since a two digit year is ambiguous (and date.setYear
+ * only works with numbers < 99 and so doesn't allow you to set years after 2000) we need to use this to disambiguate the two digit year codes.
+ *
+ * @name format
+ * @type String
+ * @cat Plugins/Methods/Date
+ * @author Kelvin Luck
+ */
+Date.fullYearStart = '20';
+
+(function() {
+
+       /**
+        * Adds a given method under the given name
+        * to the Date prototype if it doesn't
+        * currently exist.
+        *
+        * @private
+        */
+       function add(name, method) {
+               if( !Date.prototype[name] ) {
+                       Date.prototype[name] = method;
+               }
+       };
+
+       /**
+        * Checks if the year is a leap year.
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.isLeapYear();
+        * @result true
+        *
+        * @name isLeapYear
+        * @type Boolean
+        * @cat Plugins/Methods/Date
+        */
+       add("isLeapYear", function() {
+               var y = this.getFullYear();
+               return (y%4==0 && y%100!=0) || y%400==0;
+       });
+
+       /**
+        * Checks if the day is a weekend day (Sat or Sun).
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.isWeekend();
+        * @result false
+        *
+        * @name isWeekend
+        * @type Boolean
+        * @cat Plugins/Methods/Date
+        */
+       add("isWeekend", function() {
+               return this.getDay()==0 || this.getDay()==6;
+       });
+
+       /**
+        * Check if the day is a day of the week (Mon-Fri)
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.isWeekDay();
+        * @result false
+        *
+        * @name isWeekDay
+        * @type Boolean
+        * @cat Plugins/Methods/Date
+        */
+       add("isWeekDay", function() {
+               return !this.isWeekend();
+       });
+
+       /**
+        * Gets the number of days in the month.
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.getDaysInMonth();
+        * @result 31
+        *
+        * @name getDaysInMonth
+        * @type Number
+        * @cat Plugins/Methods/Date
+        */
+       add("getDaysInMonth", function() {
+               return [31,(this.isLeapYear() ? 29:28),31,30,31,30,31,31,30,31,30,31][this.getMonth()];
+       });
+
+       /**
+        * Gets the name of the day.
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.getDayName();
+        * @result 'Saturday'
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.getDayName(true);
+        * @result 'Sat'
+        *
+        * @param abbreviated Boolean When set to true the name will be abbreviated.
+        * @name getDayName
+        * @type String
+        * @cat Plugins/Methods/Date
+        */
+       add("getDayName", function(abbreviated) {
+               return abbreviated ? Date.abbrDayNames[this.getDay()] : Date.dayNames[this.getDay()];
+       });
+
+       /**
+        * Gets the name of the month.
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.getMonthName();
+        * @result 'Janurary'
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.getMonthName(true);
+        * @result 'Jan'
+        *
+        * @param abbreviated Boolean When set to true the name will be abbreviated.
+        * @name getDayName
+        * @type String
+        * @cat Plugins/Methods/Date
+        */
+       add("getMonthName", function(abbreviated) {
+               return abbreviated ? Date.abbrMonthNames[this.getMonth()] : Date.monthNames[this.getMonth()];
+       });
+
+       /**
+        * Get the number of the day of the year.
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.getDayOfYear();
+        * @result 11
+        *
+        * @name getDayOfYear
+        * @type Number
+        * @cat Plugins/Methods/Date
+        */
+       add("getDayOfYear", function() {
+               var tmpdtm = new Date("1/1/" + this.getFullYear());
+               return Math.floor((this.getTime() - tmpdtm.getTime()) / 86400000);
+       });
+
+       /**
+        * Get the number of the week of the year.
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.getWeekOfYear();
+        * @result 2
+        *
+        * @name getWeekOfYear
+        * @type Number
+        * @cat Plugins/Methods/Date
+        */
+       add("getWeekOfYear", function() {
+               return Math.ceil(this.getDayOfYear() / 7);
+       });
+
+       /**
+        * Set the day of the year.
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.setDayOfYear(1);
+        * dtm.toString();
+        * @result 'Tue Jan 01 2008 00:00:00'
+        *
+        * @name setDayOfYear
+        * @type Date
+        * @cat Plugins/Methods/Date
+        */
+       add("setDayOfYear", function(day) {
+               this.setMonth(0);
+               this.setDate(day);
+               return this;
+       });
+
+       /**
+        * Add a number of years to the date object.
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.addYears(1);
+        * dtm.toString();
+        * @result 'Mon Jan 12 2009 00:00:00'
+        *
+        * @name addYears
+        * @type Date
+        * @cat Plugins/Methods/Date
+        */
+       add("addYears", function(num) {
+               this.setFullYear(this.getFullYear() + num);
+               return this;
+       });
+
+       /**
+        * Add a number of months to the date object.
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.addMonths(1);
+        * dtm.toString();
+        * @result 'Tue Feb 12 2008 00:00:00'
+        *
+        * @name addMonths
+        * @type Date
+        * @cat Plugins/Methods/Date
+        */
+       add("addMonths", function(num) {
+               var tmpdtm = this.getDate();
+
+               this.setMonth(this.getMonth() + num);
+
+               if (tmpdtm > this.getDate())
+                       this.addDays(-this.getDate());
+
+               return this;
+       });
+
+       /**
+        * Add a number of days to the date object.
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.addDays(1);
+        * dtm.toString();
+        * @result 'Sun Jan 13 2008 00:00:00'
+        *
+        * @name addDays
+        * @type Date
+        * @cat Plugins/Methods/Date
+        */
+       add("addDays", function(num) {
+               this.setDate(this.getDate() + num);
+               return this;
+       });
+
+       /**
+        * Add a number of hours to the date object.
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.addHours(24);
+        * dtm.toString();
+        * @result 'Sun Jan 13 2008 00:00:00'
+        *
+        * @name addHours
+        * @type Date
+        * @cat Plugins/Methods/Date
+        */
+       add("addHours", function(num) {
+               this.setHours(this.getHours() + num);
+               return this;
+       });
+
+       /**
+        * Add a number of minutes to the date object.
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.addMinutes(60);
+        * dtm.toString();
+        * @result 'Sat Jan 12 2008 01:00:00'
+        *
+        * @name addMinutes
+        * @type Date
+        * @cat Plugins/Methods/Date
+        */
+       add("addMinutes", function(num) {
+               this.setMinutes(this.getMinutes() + num);
+               return this;
+       });
+
+       /**
+        * Add a number of seconds to the date object.
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.addSeconds(60);
+        * dtm.toString();
+        * @result 'Sat Jan 12 2008 00:01:00'
+        *
+        * @name addSeconds
+        * @type Date
+        * @cat Plugins/Methods/Date
+        */
+       add("addSeconds", function(num) {
+               this.setSeconds(this.getSeconds() + num);
+               return this;
+       });
+
+       /**
+        * Sets the time component of this Date to zero for cleaner, easier comparison of dates where time is not relevant.
+        *
+        * @example var dtm = new Date();
+        * dtm.zeroTime();
+        * dtm.toString();
+        * @result 'Sat Jan 12 2008 00:01:00'
+        *
+        * @name zeroTime
+        * @type Date
+        * @cat Plugins/Methods/Date
+        * @author Kelvin Luck
+        */
+       add("zeroTime", function() {
+               this.setMilliseconds(0);
+               this.setSeconds(0);
+               this.setMinutes(0);
+               this.setHours(0);
+               return this;
+       });
+
+       /**
+        * Returns a string representation of the date object according to Date.format.
+        * (Date.toString may be used in other places so I purposefully didn't overwrite it)
+        *
+        * @example var dtm = new Date("01/12/2008");
+        * dtm.asString();
+        * @result '12/01/2008' // (where Date.format == 'dd/mm/yyyy'
+        *
+        * @name asString
+        * @type Date
+        * @cat Plugins/Methods/Date
+        * @author Kelvin Luck
+        */
+       add("asString", function() {
+               var r = Date.format;
+               return r
+                       .split('yyyy').join(this.getFullYear())
+                       .split('yy').join((this.getFullYear() + '').substring(2))
+                       .split('mmm').join(this.getMonthName(true))
+                       .split('mm').join(_zeroPad(this.getMonth()+1))
+                       .split('dd').join(_zeroPad(this.getDate()));
+       });
+
+       /**
+        * Returns a new date object created from the passed String according to Date.format or false if the attempt to do this results in an invalid date object
+        * (We can't simple use Date.parse as it's not aware of locale and I chose not to overwrite it incase it's functionality is being relied on elsewhere)
+        *
+        * @example var dtm = Date.fromString("12/01/2008");
+        * dtm.toString();
+        * @result 'Sat Jan 12 2008 00:00:00' // (where Date.format == 'dd/mm/yyyy'
+        *
+        * @name fromString
+        * @type Date
+        * @cat Plugins/Methods/Date
+        * @author Kelvin Luck
+        */
+       Date.fromString = function(s)
+       {
+               var f = Date.format;
+               var d = new Date('01/01/1977');
+               var iY = f.indexOf('yyyy');
+               if (iY > -1) {
+                       d.setFullYear(Number(s.substr(iY, 4)));
+               } else {
+                       // TODO - this doesn't work very well - are there any rules for what is meant by a two digit year?
+                       d.setFullYear(Number(Date.fullYearStart + s.substr(f.indexOf('yy'), 2)));
+               }
+               var iM = f.indexOf('mmm');
+               if (iM > -1) {
+                       var mStr = s.substr(iM, 3);
+                       for (var i=0; i<Date.abbrMonthNames.length; i++) {
+                               if (Date.abbrMonthNames[i] == mStr) break;
+                       }
+                       d.setMonth(i);
+               } else {
+                       d.setMonth(Number(s.substr(f.indexOf('mm'), 2)) - 1);
+               }
+               d.setDate(Number(s.substr(f.indexOf('dd'), 2)));
+               if (isNaN(d.getTime())) {
+                       return false;
+               }
+               return d;
+       };
+
+       // utility method
+       var _zeroPad = function(num) {
+               var s = '0'+num;
+               return s.substring(s.length-2)
+               //return ('0'+num).substring(-2); // doesn't work on IE :(
+       };
+
+})();
diff --git a/js2/mwEmbed/jquery/plugins/jquery.dimensions.js b/js2/mwEmbed/jquery/plugins/jquery.dimensions.js
new file mode 100644 (file)
index 0000000..100e60c
--- /dev/null
@@ -0,0 +1,116 @@
+/* Copyright (c) 2007 Paul Bakaus (paul.bakaus@googlemail.com) and Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
+ * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
+ * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
+ *
+ * $LastChangedDate: 2007-09-10 19:38:31 -0700 (Mon, 10 Sep 2007) $
+ * $Rev: 3238 $
+ *
+ * Version: @VERSION
+ *
+ * Requires: jQuery 1.2+
+ */
+
+(function($){
+
+$.dimensions = {
+       version: '@VERSION'
+};
+
+// Create innerHeight, innerWidth, outerHeight and outerWidth methods
+$.each( [ 'Height', 'Width' ], function(i, name){
+
+       // innerHeight and innerWidth
+       $.fn[ 'inner' + name ] = function() {
+               if (!this[0]) return;
+
+               var torl = name == 'Height' ? 'Top'     : 'Left',  // top or left
+                       borr = name == 'Height' ? 'Bottom' : 'Right'; // bottom or right
+
+               return this[ name.toLowerCase() ]() + num(this, 'padding' + torl) + num(this, 'padding' + borr);
+       };
+
+       // outerHeight and outerWidth
+       $.fn[ 'outer' + name ] = function(options) {
+               if (!this[0]) return;
+
+               var torl = name == 'Height' ? 'Top'     : 'Left',  // top or left
+                       borr = name == 'Height' ? 'Bottom' : 'Right'; // bottom or right
+
+               options = $.extend({ margin: false }, options || {});
+
+               return this[ name.toLowerCase() ]()
+                               + num(this, 'border' + torl + 'Width') + num(this, 'border' + borr + 'Width')
+                               + num(this, 'padding' + torl) + num(this, 'padding' + borr)
+                               + (options.margin ? (num(this, 'margin' + torl) + num(this, 'margin' + borr)) : 0);
+       };
+});
+
+// Create scrollLeft and scrollTop methods
+$.each( ['Left', 'Top'], function(i, name) {
+       $.fn[ 'scroll' + name ] = function(val) {
+               if (!this[0]) return;
+
+               return val != undefined ?
+
+                       // Set the scroll offset
+                       this.each(function() {
+                               this == window || this == document ?
+                                       window.scrollTo(
+                                               name == 'Left' ? val : $(window)[ 'scrollLeft' ](),
+                                               name == 'Top'  ? val : $(window)[ 'scrollTop'  ]()
+                                       ) :
+                                       this[ 'scroll' + name ] = val;
+                       }) :
+
+                       // Return the scroll offset
+                       this[0] == window || this[0] == document ?
+                               self[ (name == 'Left' ? 'pageXOffset' : 'pageYOffset') ] ||
+                                       $.boxModel && document.documentElement[ 'scroll' + name ] ||
+                                       document.body[ 'scroll' + name ] :
+                               this[0][ 'scroll' + name ];
+       };
+});
+
+$.fn.extend({
+       position: function() {
+               var left = 0, top = 0, elem = this[0], offset, parentOffset, offsetParent, results;
+
+               if (elem) {
+                       // Get *real* offsetParent
+                       offsetParent = this.offsetParent();
+
+                       // Get correct offsets
+                       offset     = this.offset();
+                       parentOffset = offsetParent.offset();
+
+                       // Subtract element margins
+                       offset.top  -= num(elem, 'marginTop');
+                       offset.left -= num(elem, 'marginLeft');
+
+                       // Add offsetParent borders
+                       parentOffset.top  += num(offsetParent, 'borderTopWidth');
+                       parentOffset.left += num(offsetParent, 'borderLeftWidth');
+
+                       // Subtract the two offsets
+                       results = {
+                               top:  offset.top  - parentOffset.top,
+                               left: offset.left - parentOffset.left
+                       };
+               }
+
+               return results;
+       },
+
+       offsetParent: function() {
+               var offsetParent = this[0].offsetParent;
+               while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && $.css(offsetParent, 'position') == 'static') )
+                       offsetParent = offsetParent.offsetParent;
+               return $(offsetParent);
+       }
+});
+
+var num = function(el, prop) {
+       return parseInt($.css(el.jquery?el[0]:el,prop))||0;
+};
+
+})(jQuery);
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/plugins/jquery.highlight.js b/js2/mwEmbed/jquery/plugins/jquery.highlight.js
new file mode 100644 (file)
index 0000000..c10c805
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+highlight v1
+
+Highlights arbitrary terms.
+<http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html>
+MIT license.
+
+Johann Burkard
+<http://johannburkard.de>
+<mailto:jb@eaio.com>
+*/
+$(function() {
+ jQuery.highlight = document.body.createTextRange ?
+
+/*
+Version for IE using TextRanges.
+*/
+  function(node, te) {
+   var r = document.body.createTextRange();
+   r.moveToElementText(node);
+   for (var i = 0; r.findText(te); i++) {
+    r.pasteHTML('<span class="highlight">' +  r.text + '<\/span>');
+    r.collapse(false);
+   }
+  }
+
+ :
+
+/*
+ (Complicated) version for Mozilla and Opera using span tags.
+*/
+  function(node, te) {
+   var pos, skip, spannode, middlebit, endbit, middleclone;
+   skip = 0;
+   if (node.nodeType == 3) {
+    pos = node.data.toUpperCase().indexOf(te);
+    if (pos >= 0) {
+     spannode = document.createElement('span');
+     spannode.className = 'highlight';
+     middlebit = node.splitText(pos);
+     endbit = middlebit.splitText(te.length);
+     middleclone = middlebit.cloneNode(true);
+     spannode.appendChild(middleclone);
+     middlebit.parentNode.replaceChild(spannode, middlebit);
+     skip = 1;
+    }
+   }
+   else if (node.nodeType == 1 && node.childNodes && !/(script|style)/i.test(node.tagName)) {
+    for (var i = 0; i < node.childNodes.length; ++i) {
+     i += $.highlight(node.childNodes[i], te);
+    }
+   }
+   return skip;
+  }
+
+ ;
+});
+
+jQuery.fn.removeHighlight = function() {
+ return this.find("span.highlight").each(function() {
+  this.parentNode.replaceChild(this.firstChild, this).normalize();
+ });
+};
diff --git a/js2/mwEmbed/jquery/plugins/jquery.hoverIntent.js b/js2/mwEmbed/jquery/plugins/jquery.hoverIntent.js
new file mode 100644 (file)
index 0000000..9687ca0
--- /dev/null
@@ -0,0 +1,112 @@
+/**
+* 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: 2, // number = sensitivity threshold (must be 1 or higher)
+*      interval: 50,   // number = milliseconds of polling interval
+*      over: showNav,  // function = onMouseOver callback (required)
+*      timeout: 100,   // 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)
+* @return    The object (aka "this") that called hoverIntent, and the event 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 = jQuery.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/js2/mwEmbed/jquery/plugins/jquery.pngFix.js b/js2/mwEmbed/jquery/plugins/jquery.pngFix.js
new file mode 100644 (file)
index 0000000..e80b568
--- /dev/null
@@ -0,0 +1,113 @@
+/**
+ * --------------------------------------------------------------------
+ * jQuery-Plugin "pngFix"
+ * Version: 1.2, 09.03.2009
+ * by Andreas Eberhard, andreas.eberhard@gmail.com
+ *                      http://jquery.andreaseberhard.de/
+ *
+ * Copyright (c) 2007 Andreas Eberhard
+ * Licensed under GPL (http://www.opensource.org/licenses/gpl-license.php)
+ *
+ * Changelog:
+ *    09.03.2009 Version 1.2
+ *    - Update for jQuery 1.3.x, removed @ from selectors
+ *    11.09.2007 Version 1.1
+ *    - removed noConflict
+ *    - added png-support for input type=image
+ *    - 01.08.2007 CSS background-image support extension added by Scott Jehl, scott@filamentgroup.com, http://www.filamentgroup.com
+ *    31.05.2007 initial Version 1.0
+ * --------------------------------------------------------------------
+ * @example $(function(){$(document).pngFix();});
+ * @desc Fixes all PNG's in the document on document.ready
+ *
+ * jQuery(function(){jQuery(document).pngFix();});
+ * @desc Fixes all PNG's in the document on document.ready when using noConflict
+ *
+ * @example $(function(){$('div.examples').pngFix();});
+ * @desc Fixes all PNG's within div with class examples
+ *
+ * @example $(function(){$('div.examples').pngFix( { blankgif:'ext.gif' } );});
+ * @desc Fixes all PNG's within div with class examples, provides blank gif for input with png
+ * --------------------------------------------------------------------
+ */
+
+(function($) {
+
+jQuery.fn.pngFix = function(settings) {
+
+       // Settings
+       settings = jQuery.extend({
+               blankgif: 'blank.gif'
+       }, settings);
+
+       var ie55 = (navigator.appName == "Microsoft Internet Explorer" && parseInt(navigator.appVersion) == 4 && navigator.appVersion.indexOf("MSIE 5.5") != -1);
+       var ie6 = (navigator.appName == "Microsoft Internet Explorer" && parseInt(navigator.appVersion) == 4 && navigator.appVersion.indexOf("MSIE 6.0") != -1);
+
+       if (jQuery.browser.msie && (ie55 || ie6)) {
+
+               //fix images with png-source
+               jQuery(this).find("img[src$=.png]").each(function() {
+
+                       jQuery(this).attr('width',jQuery(this).width());
+                       jQuery(this).attr('height',jQuery(this).height());
+
+                       var prevStyle = '';
+                       var strNewHTML = '';
+                       var imgId = (jQuery(this).attr('id')) ? 'id="' + jQuery(this).attr('id') + '" ' : '';
+                       var imgClass = (jQuery(this).attr('class')) ? 'class="' + jQuery(this).attr('class') + '" ' : '';
+                       var imgTitle = (jQuery(this).attr('title')) ? 'title="' + jQuery(this).attr('title') + '" ' : '';
+                       var imgAlt = (jQuery(this).attr('alt')) ? 'alt="' + jQuery(this).attr('alt') + '" ' : '';
+                       var imgAlign = (jQuery(this).attr('align')) ? 'float:' + jQuery(this).attr('align') + ';' : '';
+                       var imgHand = (jQuery(this).parent().attr('href')) ? 'cursor:hand;' : '';
+                       if (this.style.border) {
+                               prevStyle += 'border:'+this.style.border+';';
+                               this.style.border = '';
+                       }
+                       if (this.style.padding) {
+                               prevStyle += 'padding:'+this.style.padding+';';
+                               this.style.padding = '';
+                       }
+                       if (this.style.margin) {
+                               prevStyle += 'margin:'+this.style.margin+';';
+                               this.style.margin = '';
+                       }
+                       var imgStyle = (this.style.cssText);
+
+                       strNewHTML += '<span '+imgId+imgClass+imgTitle+imgAlt;
+                       strNewHTML += 'style="position:relative;white-space:pre-line;display:inline-block;background:transparent;'+imgAlign+imgHand;
+                       strNewHTML += 'width:' + jQuery(this).width() + 'px;' + 'height:' + jQuery(this).height() + 'px;';
+                       strNewHTML += 'filter:progid:DXImageTransform.Microsoft.AlphaImageLoader' + '(src=\'' + jQuery(this).attr('src') + '\', sizingMethod=\'scale\');';
+                       strNewHTML += imgStyle+'"></span>';
+                       if (prevStyle != ''){
+                               strNewHTML = '<span style="position:relative;display:inline-block;'+prevStyle+imgHand+'width:' + jQuery(this).width() + 'px;' + 'height:' + jQuery(this).height() + 'px;'+'">' + strNewHTML + '</span>';
+                       }
+
+                       jQuery(this).hide();
+                       jQuery(this).after(strNewHTML);
+
+               });
+
+               // fix css background pngs
+               jQuery(this).find("*").each(function(){
+                       var bgIMG = jQuery(this).css('background-image');
+                       if(bgIMG.indexOf(".png")!=-1){
+                               var iebg = bgIMG.split('url("')[1].split('")')[0];
+                               jQuery(this).css('background-image', 'none');
+                               jQuery(this).get(0).runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + iebg + "',sizingMethod='scale')";
+                       }
+               });
+               
+               //fix input with png-source
+               jQuery(this).find("input[src$=.png]").each(function() {
+                       var bgIMG = jQuery(this).attr('src');
+                       jQuery(this).get(0).runtimeStyle.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader' + '(src=\'' + bgIMG + '\', sizingMethod=\'scale\');';
+               jQuery(this).attr('src', settings.blankgif)
+               });
+       
+       }
+       
+       return jQuery;
+
+};
+
+})(jQuery);
diff --git a/js2/mwEmbed/jquery/plugins/jquery.suggestions.js b/js2/mwEmbed/jquery/plugins/jquery.suggestions.js
new file mode 100644 (file)
index 0000000..489f52f
--- /dev/null
@@ -0,0 +1,459 @@
+/**
+ * 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();
+ * 
+ * Available options:
+ * animationDuration: How long (in ms) the animated growing of the results box
+ *     should take (default: 200)
+ * cancelPending(): Function called when any pending asynchronous suggestions
+ *     fetches should be canceled (optional). Executed in the context of the
+ *     textbox
+ * delay: Number of ms to wait for the user to stop typing (default: 120)
+ * fetch(query): Callback that should fetch suggestions and set the suggestions
+ *     property (required). Executed in the context of the textbox
+ * maxGrowFactor: Maximum width of the suggestions box as a factor of the width
+ *     of the textbox (default: 2)
+ * maxRows: Maximum number of suggestion rows to show
+ * submitOnClick: If true, submit the form when a suggestion is clicked
+ *     (default: false)
+ * suggestions: Array of suggestions to display (default: [])
+ * 
+ */
+(function($) {
+$.fn.suggestions = function( param, param2 ) {
+       /**
+        * Handle special keypresses (arrow keys and escape)
+        * @param key Key code
+        */
+       function processKey( key ) {
+               switch ( key ) {
+                       case 40:
+                               // Arrow down
+                               if ( conf._data.div.is( ':visible' ) ) {
+                                       highlightResult( 'next', true );
+                               } else {
+                                       // Load suggestions right now
+                                       updateSuggestions( false );
+                               }
+                       break;
+                       case 38:
+                               // Arrow up
+                               if ( conf._data.div.is( ':visible' ) ) {
+                                       highlightResult( 'prev', true );
+                               }
+                       break;
+                       case 27:
+                               // Escape
+                               conf._data.div.hide();
+                               restoreText();
+                               cancelPendingSuggestions();
+                       break;
+                       default:
+                               updateSuggestions( true );
+               }
+       }
+       
+       /**
+        * Restore the text the user originally typed in the textbox,
+        * before it was overwritten by highlightResult(). This restores the
+        * value the currently displayed suggestions are based on, rather than
+        * the value just before highlightResult() overwrote it; the former
+        * is arguably slightly more sensible.
+        */
+       function restoreText() {
+               conf._data.textbox.val( conf._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 hasn't changed since the last time
+        * suggestions were fetched, this function does nothing.
+        * @param delayed If true, delay this by the user-specified delay
+        */
+       function updateSuggestions( delayed ) {
+               // Cancel previous call
+               if ( conf._data.timerID != null )
+                       clearTimeout( conf._data.timerID );
+               if ( delayed )
+                       setTimeout( doUpdateSuggestions, conf.delay );
+               else
+                       doUpdateSuggestions();
+       }
+       
+       /**
+        * Delayed part of updateSuggestions()
+        * Don't call this, use updateSuggestions( false ) instead
+        */
+       function doUpdateSuggestions() {
+               if ( conf._data.textbox.val() == conf._data.prevText )
+                       // Value in textbox didn't change
+                       return;
+               
+               conf._data.prevText = conf._data.textbox.val();
+               conf.fetch.call ( conf._data.textbox,
+                       conf._data.textbox.val() );
+       }
+       
+       /**
+        * Called when the user changes the suggestions post-init.
+        * Typically happens asynchronously from conf.fetch()
+        */
+       function suggestionsChanged() {
+               conf._data.div.show();
+               updateSuggestionsTable();
+               fitContainer();
+               trimResultText();
+       }
+       
+       /**
+        * Cancel any delayed updateSuggestions() call and inform the user so
+        * they can cancel their result fetching if they use AJAX or something 
+        */
+       function cancelPendingSuggestions() {
+               if ( conf._data.timerID != null )
+                       clearTimeout( conf._data.timerID );
+               conf.cancelPending.call( this );
+       }
+       
+       /**
+        * Rebuild the suggestions table
+        */
+       function updateSuggestionsTable() {
+               // If there are no suggestions, hide the div
+               if ( conf.suggestions.length == 0 ) {
+                       conf._data.div.hide();
+                       return;
+               }
+               
+               var table = conf._data.div.children( 'table' );
+               table.empty();
+               for ( var i = 0; i < conf.suggestions.length; i++ ) {
+                       var td = $( '<td />' ) // FIXME: why use a span?
+                               .append( $( '<span />' ).text( conf.suggestions[i] ) );
+                               //.addClass( 'os-suggest-result' ); //FIXME: use descendant selector
+                       $( '<tr />' )
+                               .addClass( 'os-suggest-result' ) // FIXME: use descendant selector
+                               .attr( 'rel', i )
+                               .data( 'text', conf.suggestions[i] )
+                               .append( td )
+                               .appendTo( table );
+               }
+       }
+       
+       /**
+        * Make the container fit into the screen
+        */
+       function fitContainer() {
+               if ( conf._data.div.is( ':hidden' ) )
+                       return;
+               
+               // FIXME: Mysterious -20 from mwsuggest.js,
+               // presumably to make room for a scrollbar
+               var availableHeight = $( 'body' ).height() - (
+                       Math.round( conf._data.div.offset().top ) -
+                       $( document ).scrollTop() ) - 20;
+               var rowHeight = conf._data.div.find( 'tr' ).outerHeight();
+               var numRows = Math.floor( availableHeight / rowHeight );
+               
+               // Show at least 2 rows if there are multiple results
+               if ( numRows < 2 && conf.suggestions.length >= 2 )
+                       numRows = 2;
+               if ( numRows > conf.maxRows )
+                       numRows = conf.maxRows;
+               
+               var tableHeight = conf._data.div.find( 'table' ).outerHeight();
+               if ( numRows * rowHeight < tableHeight ) {
+                       // The container is too small
+                       conf._data.div.height( numRows * rowHeight );
+                       conf._data.visibleResults = numRows;
+               } else {
+                       // The container is possibly too large
+                       conf._data.div.height( tableHeight );
+                       conf._data.visibleResults = conf.suggestions.length;
+               }
+       }
+       
+       /**
+        * If there are results wider than the container, try to grow the
+        * container or trim them to end with "..."
+        */
+       function trimResultText() {
+               if ( conf._data.div.is( ':hidden' ) )
+                       return;
+               
+               // Try to grow the container so all results fit
+               // Can't use each() here because the inner function can read
+               // but not write maxWidth for some crazy reason
+               var maxWidth = 0;
+               var spans = conf._data.div.find( 'span' ).get();
+               for ( var i = 0; i < spans.length; i++ )
+                       if ( $(spans[i]).outerWidth() > maxWidth )
+                               maxWidth = $(spans[i]).outerWidth();
+               
+               // FIXME: Some mysterious fixing going on here
+               // FIXME: Left out Opera fix for now
+               // FIXME: This doesn't check that the container won't run off the screen
+               // FIXME: This should try growing to the left instead if no space on the right
+               var fix = 0;
+               if ( conf._data.visibleResults < conf.suggestions.length )
+                       fix = 20;
+               //else
+               //      fix = operaWidthFix();
+               if ( fix < 4 )
+                       // FIXME: Make 4px configurable?
+                       fix = 4; // Always pad at least 4px
+               maxWidth += fix;
+               
+               var textBoxWidth = conf._data.textbox.outerWidth();
+               var factor = maxWidth / textBoxWidth;
+               if ( factor > conf.maxGrowFactor ) 
+                       factor = conf.maxGrowFactor;
+               if ( factor < 1 )
+                       // Don't shrink the container to be smaller
+                       // than the textbox
+                       factor = 1;
+               var newWidth = Math.round( textBoxWidth * factor );
+               if ( newWidth != conf._data.div.outerWidth() )
+                       conf._data.div.animate( { width: newWidth },
+                               conf.animationDuration );
+               // FIXME: mwsuggest.js has this inside the if != block
+               // but I don't think that's right
+               newWidth -= fix;
+               
+               // If necessary, trim and add ...
+               conf._data.div.find( 'tr' ).each( function() {
+                       var span = $(this).find( 'span' );
+                       if ( span.outerWidth() > newWidth ) {
+                               var span = $(this).find( 'span' );
+                               span.text( span.text() + '...' );
+                               
+                               // While it's still too wide and the last
+                               // iteration shrunk it, remove the character
+                               // before '...'
+                               while ( span.outerWidth() > newWidth && span.text().length > 3 ) {
+                                       span.text( span.text().substring( 0,
+                                               span.text().length - 4 ) + '...' );
+                               }
+                               $(this).attr( 'title', $(this).data( 'text' ) );
+                       }
+               });
+       }
+       
+       /**
+        * Get a jQuery object for the currently highlighted row
+        */
+       function getHighlightedRow() {
+               return conf._data.div.find( '.os-suggest-result-hl' );
+       }
+       
+       /**
+        * 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
+        */
+       function highlightResult( result, updateTextbox ) {
+               // TODO: Use our own class here
+               var selected = getHighlightedRow();
+               if ( !result.get || selected.get( 0 ) != result.get( 0 ) ) {
+                       if ( result == 'prev' ) {
+                               result = selected.prev();
+                       } else if ( result == 'next' ) {
+                               if ( selected.size() == 0 )
+                                       // No item selected, go to the first one
+                                       result = conf._data.div.find( 'tr:first' );
+                               else {
+                                       result = selected.next();
+                                       if ( result.size() == 0 )
+                                               // We were at the last item, stay there
+                                               result = selected;
+                               }
+                       }
+                       
+                       selected.removeClass( 'os-suggest-result-hl' );
+                       result.addClass( 'os-suggest-result-hl' );
+               }
+               
+               if ( updateTextbox ) {
+                       if ( result.size() == 0 )
+                               restoreText();
+                       else
+                               conf._data.textbox.val( result.data( 'text' ) );
+               }
+               
+               if ( result.size() > 0 && conf._data.visibleResults < conf.suggestions.length ) {
+                       // Not all suggestions are visible
+                       // Scroll if needed
+                       
+                       // height of a result row
+                       var rowHeight = result.outerHeight();
+                       // index of first visible element
+                       var first = conf._data.div.scrollTop() / rowHeight;  
+                       // index of last visible element
+                       var last = first + conf._data.visibleResults - 1;
+                       // index of element to scroll to
+                       var to = result.attr( 'rel' );
+                       
+                       if ( to < first )
+                               // Need to scroll up
+                               conf._data.div.scrollTop( to * rowHeight );
+                       else if ( result.attr( 'rel' ) > last )
+                               // Need to scroll down
+                               conf._data.div.scrollTop( ( to - conf._data.visibleResults + 1 ) * rowHeight );
+               }
+       }
+       
+       /**
+        * Initialize the widget
+        */
+       function init() {
+               if ( typeof conf != 'object' || typeof conf._data != 'undefined' )
+                       // Configuration not set or init already done
+                       return;
+               
+               // Set defaults
+               if ( typeof conf.animationDuration == 'undefined' )
+                       conf.animationDuration = 200;
+               if ( typeof conf.cancelPending != 'function' )
+                       conf.cancelPending = function() {};
+               if ( typeof conf.delay == 'undefined' )
+                       conf.delay = 250;
+               if ( typeof conf.maxGrowFactor == 'undefined' )
+                       conf.maxGrowFactor = 2;
+               if ( typeof conf.maxRows == 'undefined' )
+                       conf.maxRows = 7;
+               if ( typeof conf.submitOnClick == 'undefined' )
+                       conf.submitOnClick = false;
+               if ( typeof conf.suggestions != 'object' )
+                       conf.suggestions = [];
+               
+               conf._data = {};
+               conf._data.textbox = $(this);
+               conf._data.timerID = null; // ID of running timer
+               conf._data.prevText = null; // Text in textbox when suggestions were last fetched
+               conf._data.visibleResults = 0; // Number of results visible without scrolling
+               conf._data.mouseDownOn = $( [] ); // Suggestion the last mousedown event occured on
+       
+               // Create container div for suggestions
+               conf._data.div = $( '<div />' )
+                       .addClass( 'os-suggest' ) //TODO: use own CSS
+                       .css( {
+                               top: Math.round( $(this).offset().top ) + this.offsetHeight,
+                               left: Math.round( $(this).offset().left ),
+                               width: $(this).outerWidth()
+                       })
+                       .hide()
+                       .appendTo( $( 'body' ) );
+               
+               // Create results table
+               $( '<table />' )
+                       .addClass( 'os-suggest-results' ) // TODO: use descendant selector
+                       .width( $(this).outerWidth() ) // TODO: see if we need Opera width fix 
+                       .appendTo( conf._data.div );
+               
+               $(this)
+                       // Stop browser autocomplete from interfering
+                       .attr( 'autocomplete', 'off')
+                       .keydown( function( e ) {
+                               // Store key pressed to handle later
+                               conf._data.keypressed = (e.keyCode == undefined) ? e.which : e.keyCode;
+                               conf._data.keypressed_count = 0;
+                       })
+                       .keypress( function() {
+                               conf._data.keypressed_count++;
+                               processKey( conf._data.keypressed );
+                       })
+                       .keyup( function() {
+                               // Some browsers won't throw keypress() for
+                               // arrow keys. If we got a keydown and a keyup
+                               // without a keypress in between, solve that
+                               if (conf._data.keypressed_count == 0 )
+                                       processKey( conf._data.keypressed );
+                       })
+                       .blur( function() {
+                               // When losing focus because of a mousedown
+                               // on a suggestion, don't hide the suggestions 
+                               if ( conf._data.mouseDownOn.size() > 0 )
+                                       return;
+                               conf._data.div.hide();
+                               cancelPendingSuggestions();
+                       });
+               
+               conf._data.div
+                       .mouseover( function( e ) {
+                               var tr = $( e.target ).closest( '.os-suggest tr' );
+                               highlightResult( tr, false );
+                       })
+                       // 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 <tr>
+                       .mousedown( function( e ) {
+                               var tr = $( e.target ).closest( '.os-suggest tr' );
+                               conf._data.mouseDownOn = tr;
+                       })
+                       .mouseup( function( e ) {
+                               var tr = $( e.target ).closest( '.os-suggest tr' );
+                               var other = conf._data.mouseDownOn;
+                               conf._data.mouseDownOn = $( [] );
+                               if ( tr.get( 0 ) != other.get( 0 ) )
+                                       return;
+                                
+                               highlightResult( tr, true );
+                               conf._data.div.hide();
+                               conf._data.textbox.focus();
+                               if ( conf.submitOnClick )
+                                       conf._data.textbox.closest( 'form' )
+                                               .submit();
+                       });
+       }
+       
+       function getProperty( prop ) {
+               return ( param[0] == '_' ? undefined : conf[param] );
+       }
+       
+       function setProperty( prop, value ) {
+               if ( typeof conf == 'undefined' ) {
+                       $(this).data( 'suggestionsConfiguration', {} );
+                       conf = $(this).data( 'suggestionsConfiguration' );
+               }
+               if ( prop[0] != '_' )
+                       conf[prop] = value;
+               if ( prop == 'suggestions' && conf._data )
+                       // Setting suggestions post-init
+                       suggestionsChanged();
+       }
+       
+       
+       // Body of suggestions() starts here
+       var conf = $(this).data( 'suggestionsConfiguration' );
+       if ( typeof param == 'object' )
+               return this.each( function() {
+                       // Bulk-set properties
+                       for ( key in param ) {
+                               // Make sure that this in setProperty()
+                               // is set right
+                               setProperty.call( this, key, param[key] );
+                       }
+               });
+       else if ( typeof param == 'string' ) {
+               if ( typeof param2 != 'undefined' )
+                       return this.each( function() {
+                               setProperty( param, param2 );
+                       });
+               else
+                       return getProperty( param );
+       } else if ( typeof param != 'undefined' )
+               // Incorrect usage, ignore
+               return this;
+       
+       // No parameters given, initialize
+       return this.each( init );
+};})(jQuery);
diff --git a/js2/mwEmbed/jquery/plugins/jquery.textSelection.js b/js2/mwEmbed/jquery/plugins/jquery.textSelection.js
new file mode 100644 (file)
index 0000000..4fedc9f
--- /dev/null
@@ -0,0 +1,323 @@
+/**
+ * These plugins provide extra functionality for interaction with textareas.
+ */
+( function( $ ) { $.fn.extend( {
+/**
+ * Get the currently selected text in this textarea. Will focus the textarea
+ * in some browsers (IE/Opera)
+ */
+textSelection: function() {
+       var e = this.jquery ? this[0] : this;
+       var retval = '';
+       if ( e.style.display == 'none' ) {
+               // Do nothing
+       } else if ( document.selection && document.selection.createRange ) {
+               e.focus();
+               var range = document.selection.createRange();
+               retval = range.text;
+       } else if ( e.selectionStart || e.selectionStart == '0' ) {
+               retval = e.value.substring( e.selectionStart, e.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 begining and end of a text selection, optionally
+ * inserting text at the caret when selection is empty.
+ * 
+ * @param pre Text to insert before selection
+ * @param peri Text to insert at caret if selection is empty
+ * @param post Text to insert after selection
+ * @param ownline If true, put the inserted text is on its own line
+ * @param replace If true, replaces any selected text with peri; if false, peri is ignored and selected text is left alone
+ */
+encapsulateSelection: function( pre, peri, post, ownline, replace ) {
+       return this.each( function() {
+               /**
+                * Check if the selected text is the same as the insert text
+                */ 
+               function checkSelectedText() {
+                       if ( !selText ) {
+                               selText = peri;
+                               isSample = true;
+                       } else if ( replace ) {
+                               selText = peri;
+                       } else if ( selText.charAt( selText.length - 1 ) == ' ' ) {
+                               // Exclude ending space char
+                               selText = selText.substring(0, selText.length - 1);
+                               post += ' ';
+                       }
+               }
+               var selText = $(this).getSelection();
+               var isSample = false;
+               if ( this.style.display == 'none' ) {
+                       // Do nothing
+               } else if ( this.selectionStart || this.selectionStart == '0' ) {
+                       // Mozilla/Opera
+                       $(this).focus();
+                       var startPos = this.selectionStart;
+                       var endPos = this.selectionEnd;
+                       checkSelectedText();
+                       if ( ownline ) {
+                               if ( startPos != 0 && this.value.charAt( startPos - 1 ) != "\n" ) {
+                                       pre = "\n" + pre;
+                               }
+                               if ( this.value.charAt( endPos ) != "\n" ) {
+                                       post += "\n";
+                               }
+                       }
+                       this.value = this.value.substring( 0, startPos ) + pre + selText + post + this.value.substring( endPos, this.value.length );
+                       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 ) {
+                               this.selectionStart = startPos + pre.length;
+                               this.selectionEnd = startPos + pre.length + selText.length;
+                       } else {
+                               this.selectionStart = startPos + pre.length + selText.length + post.length;
+                               this.selectionEnd = this.selectionStart;
+                       }
+               } else if ( document.selection && document.selection.createRange ) {
+                       // IE
+                       $(this).focus();
+                       var range = document.selection.createRange();
+                       if ( ownline && range.moveStart ) {
+                               var range2 = document.selection.createRange();
+                               range2.collapse();
+                               range2.moveStart( 'character', -1 );
+                               // FIXME: Which check is correct?
+                               if ( range2.text != "\r" && range2.text != "\n" && range2.text != "" ) {
+                                       pre = "\n" + pre;
+                               }
+                               var range3 = document.selection.createRange();
+                               range3.collapse( false );
+                               range3.moveEnd( 'character', 1 );
+                               if ( range3.text != "\r" && range3.text != "\n" && range3.text != "" ) {
+                                       post += "\n";
+                               }
+                       }
+                       checkSelectedText();
+                       range.text = pre + selText + post;
+                       if ( isSample && range.moveStart ) {
+                               range.moveStart( 'character', - post.length - selText.length );
+                               range.moveEnd( 'character', - post.length );
+                       }
+                       range.select();
+               }
+               // Scroll the textarea to the inserted text
+               $(this).scrollToCaretPosition();
+               $(this).trigger( 'encapsulateSelection', [ pre, peri, post, ownline, replace ] );
+       });
+},
+/**
+ * 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 nessecarily characters)
+ * in a textarea 
+ */
+ getCaretPosition: function( startAndEnd ) {
+       function getCaret( e ) {
+               var caretPos = 0, endPos = 0;
+               if ( $.browser.msie ) {
+                       // IE Support
+                       var postFinished = false;
+                       var periFinished = false;
+                       var postFinished = false;
+                       var preText, rawPreText, periText;
+                       var rawPeriText, postText, rawPostText;
+                       // Create range containing text in the selection
+                       var periRange = document.selection.createRange().duplicate();
+                       // Create range containing text before the selection
+                       var preRange = document.body.createTextRange();
+                       // Select all the text
+                       preRange.moveToElementText(e);
+                       // Move the end where we need it
+                       preRange.setEndPoint("EndToStart", periRange);
+                       // Create range containing text after the selection
+                       var postRange = document.body.createTextRange();
+                       // Select all the text
+                       postRange.moveToElementText(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 ( !postFinished ) {
+                                       if ( preRange.compareEndPoints( "StartToEnd", preRange ) == 0 ) {
+                                               postFinished = true;
+                                       } else {
+                                               preRange.moveEnd( "character", -1 )
+                                               if ( preRange.text == preText ) {
+                                                       rawPreText += "\r\n";
+                                               } else {
+                                                       postFinished = 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 ( ( !postFinished || !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 startAndEnd ? [ caretPos, endPos ] : caretPos;
+       }
+       return getCaret( this.get( 0 ) );
+},
+setSelection: function( start, end ) {
+       if ( typeof end == 'undefined' )
+               end = start;
+       return this.each( function() {
+               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 ( start > this.selectionEnd ) {
+                               this.selectionEnd = end;
+                               this.selectionStart = start;
+                       } else {
+                               this.selectionStart = start;
+                               this.selectionEnd = end;
+                       }
+               } else if ( document.body.createTextRange ) {
+                       var selection = document.body.createTextRange();
+                       selection.moveToElementText( this );
+                       var length = selection.text.length;
+                       selection.moveStart( 'character', start );
+                       selection.moveEnd( 'character', -length + end );
+                       selection.select();
+               }
+       });
+},
+/**
+ * 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 force boolean Whether to force a scroll even if the caret position
+ *  is already visible. Defaults to false
+ */
+scrollToCaretPosition: function( force ) {
+       function getLineLength( e ) {
+               return Math.floor( e.scrollWidth / ( $.os.name == '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 text = e.value.replace( /\r/g, "" );
+               var caret = $( e ).getCaretPosition();
+               var lineLength = getLineLength( e );
+               var row = 0;
+               var charInLine = 0;
+               var 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++;
+                               }
+                       }
+               }
+               var 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 ( $.os.name == 'mac' ? 13 : ( $.os.name == 'linux' ? 15 : 16 ) ) * row;
+       }
+       return this.each(function() {
+               if ( this.selectionStart || this.selectionStart == '0' ) {
+                       // Mozilla
+                       var scroll = getCaretScrollPosition( this );
+                       if ( 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.
+                        */
+                       var range = document.selection.createRange();
+                       var pos = $(this).getCaretPosition();
+                       var 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 ( force ) {
+                               range.move( 'character', -1 );
+                               range.select();
+                       }
+               }
+               $(this).trigger( 'scrollToPosition' );
+       } );
+}
+
+} ); } )( jQuery );
\ No newline at end of file
diff --git a/js2/mwEmbed/jquery/plugins/jquery.timers.js b/js2/mwEmbed/jquery/plugins/jquery.timers.js
new file mode 100644 (file)
index 0000000..406de7e
--- /dev/null
@@ -0,0 +1,142 @@
+jQuery.fn.extend({
+       everyTime: function(interval, label, fn, times, belay) {
+               return this.each(function() {
+                       jQuery.timer.add(this, interval, label, fn, times, belay);
+               });
+       },
+       oneTime: function(interval, label, fn) {
+               return this.each(function() {
+                       jQuery.timer.add(this, interval, label, fn, 1);
+               });
+       },
+       stopTime: function(label, fn) {
+               return this.each(function() {
+                       jQuery.timer.remove(this, label, fn);
+               });
+       }
+});
+
+jQuery.extend({
+       timer: {
+               guid: 1,
+               global: {},
+               regex: /^([0-9]+)\s*(.*s)?$/,
+               powers: {
+                       // Yeah this is major overkill...
+                       'ms': 1,
+                       'cs': 10,
+                       'ds': 100,
+                       's': 1000,
+                       'das': 10000,
+                       'hs': 100000,
+                       'ks': 1000000
+               },
+               timeParse: function(value) {
+                       if (value == undefined || value == null)
+                               return null;
+                       var result = this.regex.exec(jQuery.trim(value.toString()));
+                       if (result[2]) {
+                               var num = parseInt(result[1], 10);
+                               var mult = this.powers[result[2]] || 1;
+                               return num * mult;
+                       } else {
+                               return value;
+                       }
+               },
+               add: function(element, interval, label, fn, times, belay) {
+                       var counter = 0;
+                       
+                       if (jQuery.isFunction(label)) {
+                               if (!times) 
+                                       times = fn;
+                               fn = label;
+                               label = interval;
+                       }
+                       
+                       interval = jQuery.timer.timeParse(interval);
+
+                       if (typeof interval != 'number' || isNaN(interval) || interval <= 0)
+                               return;
+
+                       if (times && times.constructor != Number) {
+                               belay = !!times;
+                               times = 0;
+                       }
+                       
+                       times = times || 0;
+                       belay = belay || false;
+                       
+                       if (!element.$timers) 
+                               element.$timers = {};
+                       
+                       if (!element.$timers[label])
+                               element.$timers[label] = {};
+                       
+                       fn.$timerID = fn.$timerID || this.guid++;
+                       
+                       var handler = function() {
+                               if (belay && this.inProgress) 
+                                       return;
+                               this.inProgress = true;
+                               if ((++counter > times && times !== 0) || fn.call(element, counter) === false)
+                                       jQuery.timer.remove(element, label, fn);
+                               this.inProgress = false;
+                       };
+                       
+                       handler.$timerID = fn.$timerID;
+                       
+                       if (!element.$timers[label][fn.$timerID]) 
+                               element.$timers[label][fn.$timerID] = window.setInterval(handler,interval);
+                       
+                       if ( !this.global[label] )
+                               this.global[label] = [];
+                       this.global[label].push( element );
+                       
+               },
+               remove: function(element, label, fn) {
+                       var timers = element.$timers, ret;
+                       
+                       if ( timers ) {
+                               
+                               if (!label) {
+                                       for ( label in timers )
+                                               this.remove(element, label, fn);
+                               } else if ( timers[label] ) {
+                                       if ( fn ) {
+                                               if ( fn.$timerID ) {
+                                                       window.clearInterval(timers[label][fn.$timerID]);
+                                                       delete timers[label][fn.$timerID];
+                                               }
+                                       } else {
+                                               for ( var fn in timers[label] ) {
+                                                       window.clearInterval(timers[label][fn]);
+                                                       delete timers[label][fn];
+                                               }
+                                       }
+                                       
+                                       for ( ret in timers[label] ) break;
+                                       if ( !ret ) {
+                                               ret = null;
+                                               delete timers[label];
+                                       }
+                               }
+                               
+                               for ( ret in timers ) break;
+                               if ( !ret ) 
+                                       element.$timers = null;
+                       }
+               }
+       }
+});
+
+if (jQuery.browser.msie)
+       jQuery(window).one("unload", function() {
+               var global = jQuery.timer.global;
+               for ( var label in global ) {
+                       var els = global[label], i = els.length;
+                       while ( --i )
+                               jQuery.timer.remove(els[i], label);
+               }
+       });
+
+
diff --git a/js2/mwEmbed/jsScriptLoader.php b/js2/mwEmbed/jsScriptLoader.php
new file mode 100644 (file)
index 0000000..5dca6a7
--- /dev/null
@@ -0,0 +1,618 @@
+<?php
+/**
+ * This core jsScriptLoader class provides the script loader functionality
+ * @file
+ */
+
+
+//Setup the script local script cache directory (has to be hard coded rather than config based for fast non-mediawiki config hits
+$wgScriptCacheDirectory = realpath( dirname( __FILE__ ) ) . '/php/script-cache';
+
+// Check if we are being invoked in a MediaWiki context or stand alone usage:
+if ( !defined( 'MEDIAWIKI' ) && !defined( 'MW_CACHE_SCRIPT_CHECK' ) ){
+       // Load noMediaWiki helper for quick cache result
+       $myScriptLoader = new jsScriptLoader();
+       if( $myScriptLoader->outputFromCache() )
+               exit();
+       //Else load up all the config and do normal stand alone ScriptLoader process:
+       require_once( realpath( dirname( __FILE__ ) ) . '/php/noMediaWikiConfig.php' );
+       $myScriptLoader->doScriptLoader();
+}
+
+class jsScriptLoader {
+       var $jsFileList = array();
+       var $langCode = '';
+       var $jsout = '';
+       var $rKey = ''; // the request key
+       var $error_msg = '';
+       var $debug = false;
+       var $jsvarurl = false; // whether we should include generated JS (special class '-')
+       var $doProcReqFlag = true;
+
+       function outputFromCache(){
+               // Process the request
+               $this->rKey = $this->preProcRequestVars();
+               // Setup file cache object
+               $this->sFileCache = new simpleFileCache( $this->rKey );
+               if ( $this->sFileCache->isFileCached() ) {
+                       // Just output headers so we can use PHP's @readfile::
+                       $this->outputJsHeaders();
+                       $this->sFileCache->outputFromFileCache();
+                       return true;
+               }
+               return false;
+       }
+
+       function doScriptLoader() {
+               global  $wgJSAutoloadClasses, $wgJSAutoloadLocalClasses, $IP,
+               $wgEnableScriptMinify, $wgUseFileCache, $wgExtensionMessagesFiles;
+
+               //load the ExtensionMessagesFiles
+               $wgExtensionMessagesFiles['mwEmbed'] = realpath( dirname( __FILE__ ) ) . '/php/languages/mwEmbed.i18n.php';
+
+               //reset the rKey:
+               $this->rKey = '';
+               //do the post proc request with configuration vars:
+               $this->postProcRequestVars();
+               //update the filename (if gzip is on)
+               $this->sFileCache->getCacheFileName();
+
+               // Setup script loader header info
+               // @@todo we might want to put these into the mw var per class request set
+               // and or include a callback to avoid pulling in old browsers that don't support
+               // the onLoad attribute for script elements.
+               $this->jsout .= 'var mwSlScript = "' .  $_SERVER['SCRIPT_NAME']  . '";' . "\n";
+               $this->jsout .= 'var mwSlGenISODate = "' . date( 'c' ) . '";'  . "\n";
+               $this->jsout .= 'var mwSlURID = "' . htmlspecialchars( $this->urid ) . '";'  . "\n";
+               $this->jsout .= 'var mwLang = "' . htmlspecialchars( $this->langCode ) . '";' . "\n";
+               // Build the output
+
+               // Swap in the appropriate language per js_file
+               foreach ( $this->jsFileList as $classKey => $file_name ) {
+                       //get the script content
+                       $jstxt = $this->getScriptText($classKey, $file_name);
+                       if( $jstxt ){
+                               $this->jsout .= $this->doProcessJs( $jstxt );
+                       }
+               }
+               // Check if we should minify the whole thing:
+               if ( !$this->debug ) {
+                       // do the minification and output
+                       $this->jsout = JSMin::minify( $this->jsout );
+               }
+               // Save to the file cache
+               if ( $wgUseFileCache && !$this->debug ) {
+                       $status = $this->sFileCache->saveToFileCache( $this->jsout );
+                       if ( $status !== true )
+                       $this->error_msg .= $status;
+               }
+               // Check for an error msg
+               if ( $this->error_msg != '' ) {
+                       //just set the content type (don't send cache header)
+                       header( 'Content-Type: text/javascript' );
+                       echo 'alert(\'Error With ScriptLoader.php ::' . str_replace( "\n", '\'+"\n"+' . "\n'", $this->error_msg ) . '\');';
+                       echo trim( $this->jsout );
+               } else {
+                       // All good, let's output "cache" headers
+                       $this->outputJsWithHeaders();
+               }
+       }
+       function getScriptText($classKey, $file_name=''){
+               $jsout = '';
+               // Special case: title classes
+               if ( substr( $classKey, 0, 3 ) == 'WT:' ) {
+                       global $wgUser;
+                       // Get just the title part
+                       $title_block = substr( $classKey, 3 );
+                       if ( $title_block[0] == '-' && strpos( $title_block, '|' ) !== false ) {
+                               // Special case of "-" title with skin
+                               $parts = explode( '|', $title_block );
+                               $title = array_shift( $parts );
+                               foreach ( $parts as $tparam ) {
+                                       list( $key, $val ) = explode( '=', $tparam );
+                                       if ( $key == 'useskin' ) {
+                                               $skin = $val;
+                                       }
+                               }
+                               $sk = $wgUser->getSkin();
+                               // Make sure the skin name is valid
+                               $skinNames = Skin::getSkinNames();
+                               $skinNames = array_keys( $skinNames );
+                               if ( in_array( strtolower( $skin ), $skinNames ) ) {
+                                       // If in debug mode, add a comment with wiki title and rev:
+                                       if ( $this->debug )
+                                       $jsout .= "\n/**\n* GenerateUserJs: \n*/\n";
+                                       return $jsout . $sk->generateUserJs( $skin ) . "\n";
+                               }
+                       } else {
+                               // Make sure the wiki title ends with .js
+                               if ( substr( $title_block, -3 ) != '.js' ) {
+                                       $this->error_msg .= 'WikiTitle includes should end with .js';
+                                       return false;
+                               }
+                               // It's a wiki title, append the output of the wikitext:
+                               $t = Title::newFromText( $title_block );
+                               $a = new Article( $t );
+                               // Only get the content if the page is not empty:
+                               if ( $a->getID() !== 0 ) {
+                                       // If in debug mode, add a comment with wiki title and rev:
+                                       if ( $this->debug )
+                                       $jsout .= "\n/**\n* WikiJSPage: " . htmlspecialchars( $title_block ) . " rev: " . $a->getID() . " \n*/\n";
+
+                                       return $jsout . $a->getContent() . "\n";
+                               }
+                       }
+               }else{
+                       // Dealing with files
+
+                       // Check that the filename ends with .js and does not include ../ traversing
+                       if ( substr( $file_name, -3 ) != '.js' ) {
+                               $this->error_msg .= "\nError file name must end with .js: " . htmlspecialchars( $file_name ) . " \n ";
+                               return false;
+                       }
+                       if ( strpos( $file_name, '../' ) !== false ) {
+                               $this->error_msg .= "\nError file name must not traverse paths: " . htmlspecialchars( $file_name ) . " \n ";
+                               return false;
+                       }
+
+                       if ( trim( $file_name ) != '' ) {
+                               if ( $this->debug )
+                               $jsout .= "\n/**\n* File: " . htmlspecialchars( $file_name ) . "\n*/\n";
+
+                               $jsFileStr = $this->doGetJsFile( $file_name ) . "\n";
+                               if( $jsFileStr ){
+                                       return $jsout . $jsFileStr;
+                               }else{
+                                       $this->error_msg .= "\nError could not read file: ". htmlspecialchars( $file_name )  ."\n";
+                                       return false;
+                               }
+                       }
+               }
+               //if we did not return some js
+               $this->error_msg .= "\nUnknown error\n";
+               return false;
+       }
+       function outputJsHeaders() {
+               // Output JS MIME type:
+               header( 'Content-Type: text/javascript' );
+               header( 'Pragma: public' );
+               // Cache for 1 day ( we should always change the request URL
+               // based on the SVN or article version.
+               $one_day = 60 * 60 * 24;
+               header( "Expires: " . gmdate( "D, d M Y H:i:s", time() + $one_day ) . " GM" );
+       }
+
+       function outputJsWithHeaders() {
+               global $wgUseGzip;
+               $this->outputJsHeaders();
+               if ( $wgUseGzip ) {
+                       if ( $this->clientAcceptsGzip() ) {
+                               header( 'Content-Encoding: gzip' );
+                               echo gzencode( $this->jsout );
+                       } else {
+                               echo $this->jsout;
+                       }
+               } else {
+                       echo $this->jsout;
+               }
+       }
+
+       function clientAcceptsGzip() {
+               $m = array();
+               if( preg_match(
+                       '/\bgzip(?:;(q)=([0-9]+(?:\.[0-9]+)))?\b/',
+               $_SERVER['HTTP_ACCEPT_ENCODING'],
+               $m ) ) {
+                       if( isset( $m[2] ) && ( $m[1] == 'q' ) && ( $m[2] == 0 ) )
+                       return false;
+                       //no gzip support found
+                       return true;
+               }
+               return false;
+       }
+       /*
+        * postProcRequestVars uses globals, configuration and mediaWiki to test wiki-titles and files exist etc.
+        */
+       function postProcRequestVars(){
+               global $wgContLanguageCode, $wgEnableScriptMinify, $wgJSAutoloadClasses,
+               $wgJSAutoloadLocalClasses, $wgStyleVersion;
+
+               // Set debug flag
+               if ( ( isset( $_GET['debug'] ) && $_GET['debug'] == 'true' ) || ( isset( $wgEnableScriptDebug ) && $wgEnableScriptDebug == true ) ) {
+                       $this->debug = true;
+               }
+
+               // Set the urid. Be sure to escape it as it goes into our JS output.
+               if ( isset( $_GET['urid'] ) && $_GET['urid'] != '' ) {
+                       $this->urid = htmlspecialchars( $_GET['urid'] );
+               } else {
+                       // Just give it the current style sheet ID:
+                       // @@todo read the svn version number
+                       $this->urid = $wgStyleVersion;
+               }
+
+               //get the language code (if not provided use the "default" language
+               if ( isset( $_GET['uselang'] ) && $_GET['uselang'] != '' ) {
+                       //make sure its a valid lang code:
+                       $this->langCode = preg_replace( "/[^A-Za-z]/", '', $_GET['uselang']);
+               }else{
+                       //set english as default
+                       $this->langCode = 'en';
+               }
+               $this->langCode = self::checkForCommonsLanguageFormHack( $this->langCode );
+
+               $reqClassList = false;
+               if ( isset( $_GET['class'] ) && $_GET['class'] != '' ) {
+                       $reqClassList = explode( ',', $_GET['class'] );
+               }
+
+               // Check for the requested classes
+               if ( $reqClassList ) {
+                       // Clean the class list and populate jsFileList
+                       foreach ( $reqClassList as $reqClass ) {
+                               if ( trim( $reqClass ) != '' ) {
+                                       if ( substr( $reqClass, 0, 3 ) == 'WT:' ) {
+                                               $doAddWT = false;
+                                               // Check for special case '-' class for user-generated JS
+                                               if( substr( $reqClass, 3, 1) == '-'){
+                                                       $doAddWT = true;
+                                               }else{
+                                                       if( strtolower( substr( $reqClass, -3) ) == '.js'){
+                                                               //make sure its a valid wikipage before doing processing
+                                                               $t = Title::newFromDBkey( substr( $reqClass, 3) );
+                                                               if( $t->exists()
+                                                               && ( $t->getNamespace() == NS_MEDIAWIKI
+                                                               || $t->getNamespace() == NS_USER ) ){
+                                                                       $doAddWT = true;
+                                                               }
+                                                       }
+                                               }
+                                               if( $doAddWT ){
+                                                       $this->jsFileList[$reqClass] = true;
+                                                       $this->rKey .= $reqClass;
+                                                       $this->jsvarurl = true;
+                                               }
+                                               continue;
+                                       }
+
+                                       $reqClass = preg_replace( "/[^A-Za-z0-9_\-\.]/", '', $reqClass );
+
+                                       $jsFilePath = self::getJsPathFromClass( $reqClass );
+                                       if(!$jsFilePath){
+                                               $this->error_msg .= 'Requested class: ' . htmlspecialchars( $reqClass ) . ' not found' . "\n";
+                                       }else{
+                                               $this->jsFileList[ $reqClass ] = $jsFilePath;
+                                               $this->rKey .= $reqClass;
+                                       }
+                               }
+                       }
+               }
+
+
+               // Add the language code to the rKey:
+               $this->rKey .= '_' . $wgContLanguageCode;
+
+               // Add the unique rid
+               $this->rKey .= $this->urid;
+
+               // Add a minify flag
+               if ( $wgEnableScriptMinify ) {
+                       $this->rKey .= '_min';
+               }
+       }
+       /**
+        * Pre-process request variables ~without configuration~ or much utility function~
+        *  This is to quickly get a rKey that we can check against the cache
+        */
+       function preProcRequestVars() {
+               $rKey = '';
+               // Check for debug (won't use the cache)
+               if ( ( isset( $_GET['debug'] ) && $_GET['debug'] == 'true' ) ) {
+                       //we are going to have to run postProcRequest
+                       return false;
+               }
+
+               // Check for the urid. Be sure to escape it as it goes into our JS output.
+               if ( isset( $_GET['urid'] ) && $_GET['urid'] != '' ) {
+                       $urid = htmlspecialchars( $_GET['urid'] );
+               }else{
+                       die( 'missing urid param');
+               }
+
+               //get the language code (if not provided use the "default" language
+               if ( isset( $_GET['uselang'] ) && $_GET['uselang'] != '' ) {
+                       //make sure its a valid lang code:
+                       $langCode = preg_replace( "/[^A-Za-z]/", '', $_GET['uselang']);
+               }else{
+                       //set english as default
+                       $langCode = 'en';
+               }
+
+               $langCode = self::checkForCommonsLanguageFormHack( $langCode );
+
+
+               $reqClassList = false;
+               if ( isset( $_GET['class'] ) && $_GET['class'] != '' ) {
+                       $reqClassList = explode( ',', $_GET['class'] );
+               }
+
+               // Check for the requested classes
+               if ( count( $reqClassList ) > 0 ) {
+                       // Clean the class list and populate jsFileList
+                       foreach (  $reqClassList as $reqClass ) {
+                               //do some simple checks:
+                               if ( trim( $reqClass ) != '' ){
+                                       if( substr( $reqClass, 0, 3 ) == 'WT:'  && strtolower( substr( $reqClass, -3) ) == '.js' ){
+                                               //wiki page requests (must end with .js):
+                                               $rKey .= $reqClass;
+                                       }else if( substr( $reqClass, 0, 3 ) != 'WT:' ){
+                                               //normal class requests:
+                                               $reqClass = preg_replace( "/[^A-Za-z0-9_\-\.]/", '', $reqClass );
+                                               $rKey .= $reqClass;
+                                       }else{
+                                               //not a valid class don't add it
+                                       }
+                               }
+                       }
+               }
+               // Add the language code to the rKey:
+               $rKey .= '_' . $langCode;
+
+               // Add the unique rid
+               $rKey .= $urid;
+
+               return $rKey;
+       }
+       public static function checkForCommonsLanguageFormHack( $langKey){
+               $formNames = array( 'ownwork', 'fromflickr', 'fromwikimedia', 'fromgov');
+               foreach($formNames as $formName){
+                       // Directly reference a form Name then its "english"
+                       if( $formName == $langKey )
+                               return 'en';
+                       // If the langKey includes a form name (ie esownwork)
+                       // then strip the form name use that as the language key
+                       if( strpos($langKey, $formName)!==false){
+                               return str_replace($formName, '', $langKey);
+                       }
+               }
+               //else just return the key unchanged:
+               return $langKey;
+       }
+       public static function getJsPathFromClass( $reqClass ){
+               global $wgJSAutoloadLocalClasses, $wgJSAutoloadClasses;
+               if ( isset( $wgJSAutoloadLocalClasses[$reqClass] ) ) {
+                       return $wgJSAutoloadLocalClasses[$reqClass];
+               } else if ( isset( $wgJSAutoloadClasses[$reqClass] ) ) {
+                       return $wgJSAutoloadClasses[$reqClass];
+               } else {
+                       return false;
+               }
+       }
+       function doGetJsFile( $file_path ) {
+               global $IP;
+               // Load the file
+               $str = @file_get_contents( "{$IP}/{$file_path}" );
+
+               if ( $str === false ) {
+                       // @@todo check PHP error level. Don't want to expose paths if errors are hidden.
+                       $this->error_msg .= 'Requested File: ' . htmlspecialchars( $file_path ) . ' could not be read' . "\n";
+                       return false;
+               }
+               return $str;
+       }
+       function doProcessJs( $str ){
+               global $wgEnableScriptLocalization;
+               // Strip out js_log debug lines (if not in debug mode)
+               if( !$this->debug )
+                        $str = preg_replace('/\n\s*js_log\(([^\)]*\))*\s*[\;\n]/U', "\n", $str);
+
+               // Do language swap by index:
+               if ( $wgEnableScriptLocalization ){
+                       $inx = self::getLoadGmIndex( $str );
+                       if($inx){
+                               $translated = $this->languageMsgReplace( substr($str, $inx['s'], ($inx['e']-$inx['s']) ));
+                               //return the final string (without double {})
+                               return substr($str, 0, $inx['s']-1) . $translated . substr($str, $inx['e']+1);
+                       }
+               }
+               //return the js str unmodified if we did not transform with the localisation.
+               return $str;
+       }
+       static public function getLoadGmIndex( $str ){
+               $returnIndex = array();
+               preg_match('/loadGM\s*\(\s*\{/', $str, $matches, PREG_OFFSET_CAPTURE );
+               if( count($matches) == 0){
+                       return false;
+               }
+               if( count( $matches ) > 0 ){
+                       //offset + match str length gives startIndex:
+                       $returnIndex['s'] = strlen( $matches[0][0] ) + $matches[0][1];
+                       $foundMatch = true;
+               }
+               $ignorenext = false;
+               $inquote = false;
+               //look for closing } not inside quotes::
+               for ( $i = $returnIndex['s']; $i < strlen( $str ); $i++ ) {
+                       $char = $str[$i];
+                       if ( $ignorenext ) {
+                               $ignorenext = false;
+                       } else {
+                               //search for a close } that is not in quotes or escaped
+                               switch( $char ) {
+                                       case '"':
+                                               $inquote = !$inquote;
+                                               break;
+                                       case '}':
+                                               if( ! $inquote){
+                                                       $returnIndex['e'] =$i;
+                                                       return $returnIndex;
+                                               }
+                                               break;
+                                       case '\\':
+                                               if ( $inquote ) $ignorenext = true;
+                                               break;
+                               }
+                       }
+               }
+       }
+
+       function getInlineLoadGMFromClass( $class ){
+               $jsmsg = $this->getMsgKeysFromClass( $class );
+               if( $jsmsg ){
+                       self::getMsgKeys ( $jsmsg );
+                       return 'loadGM(' . FormatJson::encode( $jsmsg ) . ');';
+               }else{
+                       //if could not parse return empty string:
+                       return '';
+               }
+       }
+       function getMsgKeysFromClass( $class ){
+               $file_path = self::getJsPathFromClass( $class );
+               $str = $this->getScriptText($class,  $file_path);
+
+               $inx = self::getLoadGmIndex( $str );
+               if(!$inx)
+               return '';
+               return FormatJson::decode( '{' . substr($str, $inx['s'], ($inx['e']-$inx['s'])) . '}', true);
+       }
+
+       static public function getMsgKeys(& $jmsg, $langCode = false){
+               global $wgContLanguageCode;
+               //check the langCode
+               if(!$langCode)
+                       $langCode = $wgContLanguageCode;
+
+               // Get the msg keys for the a json array
+               foreach ( $jmsg as $msgKey => $default_en_value ) {
+                       $jmsg[$msgKey] = wfMsgGetKey( $msgKey, true, $langCode, false );
+               }
+       }
+       function languageMsgReplace( $json_str ) {
+               $jmsg = FormatJson::decode( '{' . $json_str . '}', true );
+               // Do the language lookup
+               if ( $jmsg ) {
+                       //see if any msgKey has the PLURAL template tag
+                       //package in PLURAL mapping
+                       self::getMsgKeys($jmsg, $this->langCode);
+
+                       // Return the updated loadGM JSON with updated msgs:
+                       return FormatJson::encode( $jmsg );
+               } else {
+                       // Could not parse JSON return error: (maybe a alert?)
+                       //we just make a note in the code, visitors will get the fallback language,
+                       //developers will read the js source when its not behaving as expected.
+                       return "\n/*
+* Could not parse JSON language messages in this file,
+* Please check that loadGM call contains valid JSON (not javascript)
+*/\n\n" . $json_str; //include the original fallback loadGM
+
+               }
+       }
+}
+
+// A simple version of HTMLFileCache (@@todo abstract shared pieces)
+class simpleFileCache {
+       var $mFileCache;
+       var $filename = null;
+       var $rKey = null;
+
+       public function __construct( &$rKey ) {
+               $this->rKey = $rKey;
+               $this->getCacheFileName();
+       }
+
+       public function getCacheFileName() {
+               global $wgUseGzip, $wgScriptCacheDirectory;
+
+               $hash = md5( $this->rKey );
+               # Avoid extension confusion
+               $key = str_replace( '.', '%2E', urlencode( $this->rKey ) );
+
+               $hash1 = substr( $hash, 0, 1 );
+               $hash2 = substr( $hash, 0, 2 );
+               $this->filename = "{$wgScriptCacheDirectory}/{$hash1}/{$hash2}/{$this->rKey}.js";
+
+               // Check for defined files::
+               if( is_file( $this->filename ) )
+               return $this->filename;
+
+               if( is_file(  $this->filename .'.gz') ){
+                       $this->filename.='.gz';
+                       return $this->filename;
+               }
+               //check the update the name based on the $wgUseGzip config var
+               if ( isset($wgUseGzip) && $wgUseGzip )
+               $this->filename.='.gz';
+       }
+
+       public function isFileCached() {
+               return file_exists( $this->filename );
+       }
+
+       public function outputFromFileCache() {
+               if ( $this->clientAcceptsGzip() && substr( $this->filename, -3 ) == '.gz'  ) {
+                       header( 'Content-Encoding: gzip' );
+                       readfile( $this->filename );
+                       return true;
+               }
+               // Output without gzip:
+               if ( substr( $this->filename, -3 ) == '.gz' ) {
+                       readgzfile( $this->filename );
+               } else {
+                       readfile( $this->filename );
+               }
+               return true;
+       }
+       public function clientAcceptsGzip(){
+               $m = array();
+               if ( preg_match(
+                       '/\bgzip(?:;(q)=([0-9]+(?:\.[0-9]+)))?\b/',
+               $_SERVER['HTTP_ACCEPT_ENCODING'],
+               $m ) ) {
+                       if ( isset( $m[2] ) && ( $m[1] == 'q' ) && ( $m[2] == 0 ) )
+                       return false;
+
+                       return true;
+               }
+               return false;
+       }
+       public function saveToFileCache( &$text ) {
+               global $wgUseFileCache, $wgUseGzip;
+               if ( !$wgUseFileCache ) {
+                       return 'Error: Called saveToFileCache with $wgUseFileCache off';
+               }
+               if ( strcmp( $text, '' ) == 0 )
+               return 'saveToFileCache: empty output file';
+
+               if ( $wgUseGzip ) {
+                       $outputText = gzencode( trim( $text ) );
+               } else {
+                       $outputText = trim( $text );
+               }
+
+               // Check the directories. If we could not create them, error out.
+               $status = $this->checkCacheDirs();
+
+               if ( $status !== true )
+               return $status;
+               $f = fopen( $this->filename, 'w' );
+               if ( $f ) {
+                       fwrite( $f, $outputText );
+                       fclose( $f );
+               } else {
+                       return 'Could not open file for writing. Check your cache directory permissions?';
+               }
+               return true;
+       }
+
+       protected function checkCacheDirs() {
+               $mydir2 = substr( $this->filename, 0, strrpos( $this->filename, '/' ) ); # subdirectory level 2
+               $mydir1 = substr( $mydir2, 0, strrpos( $mydir2, '/' ) ); # subdirectory level 1
+
+               if ( wfMkdirParents( $mydir1 ) === false || wfMkdirParents( $mydir2 ) === false ) {
+                       return 'Could not create cache directory. Check your cache directory permissions?';
+               } else {
+                       return true;
+               }
+       }
+}
diff --git a/js2/mwEmbed/libAddMedia/dragDropFile.js b/js2/mwEmbed/libAddMedia/dragDropFile.js
new file mode 100644 (file)
index 0000000..85201a6
--- /dev/null
@@ -0,0 +1,101 @@
+/* firefox 3.6 drag-drop uploading
+*
+* Note: this file is still under development
+*/
+loadGM( {
+       "mwe-upload-multi" : "Upload {{PLURAL:$1|file|files}}",
+       "mwe-review-upload": "Review file {{PLURAL:$1|upload|uploads}}"
+} );
+
+( function( $ ) {
+       $.fn.dragDropFile = function () {
+               js_log( "drag drop: " + this.selector );
+               // setup drag binding and highlight
+               var dC = $j( this.selector ).get( 0 );
+               dC.addEventListener( "dragenter",
+                       function( event ) {
+                               $j( dC ).css( 'border', 'solid red' );
+                               event.stopPropagation();
+                               event.preventDefault();
+                       }, false );
+               dC.addEventListener( "dragleave",
+                       function( event ) {
+                               // default textbox css (should be an easy way to do this)
+                               $j( dC ).css( 'border', '' );
+                               event.stopPropagation();
+                               event.preventDefault();
+                       }, false );
+               dC.addEventListener( "dragover",
+                       function( event ) {
+                               event.stopPropagation();
+                               event.preventDefault();
+                       }, false );
+               dC.addEventListener( "drop",
+                       function( event ) {
+                               doDrop( event );
+                               // handle the drop loader and call event
+                       }, false );
+               function doDrop( event ) {
+                       var dt = event.dataTransfer,
+                               files = dt.files,
+                               fileCount = files.length;
+
+                       event.stopPropagation();
+                       event.preventDefault();
+
+                       $j( '#multiple_file_input' ).remove();
+
+                       $j( 'body' ).append( '<div title="' + gM( 'mwe-upload-multi', fileCount ) + '" ' +
+                               'style="position:absolute;bottom:5em;top:3em;right:0px;left:0px" ' +
+                               'id="multiple_file_input">' +
+                               '</div>'
+                       );
+
+
+                       var buttons = { };
+                       buttons[ gM( 'mwe-cancel' ) ] = function() {
+                               $j( this ).dialog( 'close' );
+                       }
+                       buttons[ gM( 'mwe-upload-multi', fileCount ) ] = function() {
+                               alert( 'do multiple file upload' );
+                       }
+                       // open up the dialog
+                       $j( '#multiple_file_input' ).dialog( {
+                               bgiframe: true,
+                               autoOpen: true,
+                               modal: true,
+                               draggable:false,
+                               resizable:false,
+                               buttons : buttons
+                       } );
+                       $j( '#multiple_file_input' ).dialogFitWindow();
+                       $j( window ).resize( function() {
+                               $j( '#multiple_file_input' ).dialogFitWindow();
+                       } );
+                       // add the inital table / title:
+                       $j( '#multiple_file_input' ).html( '<h3>' + gM( 'mwe-review-upload' ) + '</h3>' +
+                               '<table width="100%" border="1" class="table_list" style="border:none;"></table>' );
+                       $j.each( files, function( i, file ) {
+                               if ( file.fileSize < 64048576 ) {
+                                       $j( '#multiple_file_input .table_list' ).append(
+                                               '<tr>' +
+                                                       '<td width="300" style="padding:5px"><img width="250" src="' + file.getAsDataURL() + '">' + '</td>' +
+                                                       '<td valign="top">' +
+                                                               'File Name: <input name="file[' + i + '][title]" value="' + file.name + '"><br>' +
+                                                               'File Desc: <textarea style="width:300px;" name="file[' + i + '][desc]"></textarea><br>' +
+                                                       '</td>' +
+                                               '</tr>'
+                                       );
+                                       /*$j.addDialog( "upload this image", '<img width="300" src="' + files[i].getAsDataURL() + '">' +
+                                               '<br>name: ' + files[i].name + '</br>' +
+                                               '<br>size: ' + files[i].fileSize + '</br>' +
+                                               '<br>mime: ' + files[i].mediaType + '</br>');
+                                       */
+                                       // do the add-media-wizard with the upload tab
+                               } else {
+                                       alert( "file is too big, needs to be below 64mb" );
+                               }
+                       } );
+               }
+       }
+} )( jQuery );
diff --git a/js2/mwEmbed/libAddMedia/mvAdvFirefogg.js b/js2/mwEmbed/libAddMedia/mvAdvFirefogg.js
new file mode 100644 (file)
index 0000000..f1f88ba
--- /dev/null
@@ -0,0 +1,981 @@
+/*
+ * Advanced Firefogg support. Lets you control many aspects of video encoding.
+ */
+
+loadGM({
+       "fogg-help-sticky" : "Help (click to stick)",
+       "fogg-cg-preset" : "Preset: <strong>$1<\/strong>",
+       "fogg-cg-quality" : "Basic quality and resolution control",
+       "fogg-cg-meta" : "Metadata for the clip",
+       "fogg-cg-range" : "Encoding range",
+       "fogg-cg-advVideo" : "Advanced video encoding controls",
+       "fogg-cg-advAudio" : "Advanced audio encoding controls",
+       "fogg-preset-custom" : "Custom settings",
+       "fogg-webvideo-desc" : "Web video Theora, Vorbis 400 kbit\/s and 400px maximum width",
+       "fogg-savebandwidth-desc" : "Low bandwidth Theora, Vorbis 164 kbit\/s and 200px maximum width",
+       "fogg-highquality-desc" : "High quality Theora, Vorbis 1080px maximum width",
+       "fogg-videoQuality-title" : "Video quality",
+       "fogg-videoQuality-help" : "Used to set the <i>visual quality<\/i> of the encoded video (not used if you set bitrate in advanced controls below).",
+       "fogg-starttime-title" : "Start second",
+       "fogg-starttime-help" : "Only encode from time in seconds",
+       "fogg-endtime-title" : "End second",
+       "fogg-endtime-help" : "Only encode to time in seconds",
+       "fogg-audioQuality-title" : "Audio quality",
+       "fogg-audioQuality-help" : "Used to set the <i>acoustic quality<\/i> of the encoded audio (not used if you set bitrate in advanced controls below).",
+       "fogg-videoCodec-title" : "Video codec",
+       "fogg-videoCodec-help" : "Used to select the clip video codec. Presently only Theora is supported. More about the <a target=\"_new\" href=\"http:\/\/en.wikipedia.org\/wiki\/Theora\">Theora codec<\/a>.",
+       "fogg-audioCodec-title" : "Audio codec",
+       "fogg-audioCodec-help" : "Used to set the clip audio codec. Presently only Vorbis is supported. More about the <a target=\"_new\" href=\"http:\/\/en.wikipedia.org\/wiki\/Vorbis\">Vorbis codec<\/a>",
+       "fogg-width-title" : "Video width",
+       "fogg-width-help" : "Resize to given width.",
+       "fogg-height-title" : "Video height",
+       "fogg-height-help" : "Resize to given height.",
+       "fogg-videoBitrate-title" : "Video bitrate",
+       "fogg-videoBitrate-help" : "Video bitrate sets the encoding bitrate for video in (kb\/s)",
+       "fogg-twopass-title" : "Two pass encoding",
+       "fogg-twopass-help" : "Two pass encoding enables more constant quality by making two passes over the video file",
+       "fogg-framerate-title" : "Frame rate",
+       "fogg-framerate-help" : "The video frame rate. More about <a target=\"_new\" href=\"http:\/\/en.wikipedia.org\/wiki\/Frame_rate\">frame rate<\/a>.",
+       "fogg-aspect-title" : "Aspect ratio",
+       "fogg-aspect-help" : "The video aspect ratio can be 4:3 or 16:9. More about <a target=\"_new\" href=\"http:\/\/en.wikipedia.org\/wiki\/Aspect_ratio_%28image%29\">aspect ratios<\/a>.",
+       "fogg-keyframeInterval-title" : "Key frame interval",
+       "fogg-keyframeInterval-help" : "The keyframe interval in frames. Note: Most codecs force keyframes if the difference between frames is greater than keyframe encode size. More about <a href=\"http:\/\/en.wikipedia.org\/wiki\/I-frame\">keyframes<\/a>.",
+       "fogg-denoise-title" : "Denoise filter",
+       "fogg-denoise-help" : "Denoise input video. More about <a href=\"http:\/\/en.wikipedia.org\/wiki\/Video_denoising\">denoise<\/a>.",
+       "fogg-novideo-title" : "No video",
+       "fogg-novideo-help" : "disable video in the output",
+       "fogg-audioBitrate-title" : "Audio bitrate",
+       "fogg-samplerate-title" : "Audio sampling rate",
+       "fogg-samplerate-help" : "set output sample rate (in Hz).",
+       "fogg-noaudio-title" : "No audio",
+       "fogg-noaudio-help" : "disable audio in the output",
+       "fogg-title-title" : "Title",
+       "fogg-title-help" : "A title for your clip",
+       "fogg-artist-title" : "Creator name",
+       "fogg-artist-help" : "The creator of this clip",
+       "fogg-date-title" : "Date",
+       "fogg-date-help" : "The date the footage was created or released",
+       "fogg-location-title" : "Location",
+       "fogg-location-help" : "The location of the footage",
+       "fogg-organization-title" : "Organization",
+       "fogg-organization-help" : "Name of organization (studio)",
+       "fogg-copyright-title" : "Copyright",
+       "fogg-copyright-help" : "The copyright of the clip",
+       "fogg-license-title" : "License",
+       "fogg-license-help" : "The license of the clip (preferably a Creative Commons URL).",
+       "fogg-contact-title" : "Contact",
+       "fogg-contact-help" : "Contact link"
+});
+
+var mvAdvFirefogg = function( iObj ) {
+       return this.init( iObj );
+}
+var default_mvAdvFirefogg_config = {
+       // Config groups to include
+       'config_groups': [ 'preset', 'range', 'quality', 'meta', 'advVideo', 'advAudio' ],
+
+       // If you want to load any custom presets must follow the mvAdvFirefogg.presetConf json outline below
+       'custom_presets': {},
+
+       // Any Firefog config properties that may need to be excluded from options
+       'exclude_settings': [],
+
+       // The control container
+       'target_control_container': false
+}
+
+mvAdvFirefogg.prototype = {
+       // The configuration group names
+       config_groups: [ 'preset', 'range', 'quality', 'meta', 'advVideo', 'advAudio' ],
+
+       // Default configuration for this class
+       default_local_settings: {
+               'default': 'webvideo',
+               'type': 'select',
+               'selectVal': ['webvideo'],
+               'group': "preset",
+               'presets': {
+                       'custom': {
+                               'descKey': 'fogg-preset-custom',
+                               'conf': {}
+                       },
+                       'webvideo': {
+                               'desc': gM( 'fogg-webvideo-desc' ),
+                               'conf': {
+                                       'maxSize'      : 400,
+                                       'videoBitrate' : 544,
+                                       'audioBitrate' : 96,
+                                       'noUpscaling'  : true,
+                               }
+                       },
+                       'savebandwidth': {
+                               'desc': gM( 'fogg-savebandwidth-desc' ),
+                               'conf': {
+                                       'maxSize'       : 200,
+                                       'videoBitrate'  : 164,
+                                       'audioBitrate'  : 32,
+                                       'samplerate'    : 22050,
+                                       'framerate'     : 15,
+                                       'channels'      : 1,
+                                       'noUpscaling'   : true
+                               }
+                       },
+                       'hqstream': {
+                               'desc': gM( 'fogg-highquality-desc' ),
+                               'conf': {
+                                       'maxSize'      : 1080,
+                                       'videoQuality' : 6,
+                                       'audioQuality' : 3,
+                                       'noUpscaling'  : true,
+                               }
+                       },
+               }
+       },
+
+       // Customised configuration hashtable
+       local_settings: {},
+
+       // Core Firefogg default encoder configuration
+       // See encoder options here: http://www.firefogg.org/dev/index.html
+       default_encoder_config: {
+               // Base quality settings
+               'videoQuality': {
+                       'default'   : 5,
+                       'range'     : { 'min': 0,'max': 10 },
+                       'type'      : 'slider',
+                       'group'     : 'quality'
+               },
+               'starttime': {
+                       'type'      : "float",
+                       'group'     : "range"
+               },
+               'endtime': {
+                       'type'      : "float",
+                       'group'     : "range"
+               },
+               'audioQuality': {
+                       'default'   : 1,
+                       'range'     : { 'min': -1, 'max': 10 },
+                       'type'      : 'slider',
+                       'group'     : 'quality',
+               },
+               'videoCodec': {
+                       'default'   : "theora",
+                       'selectVal' : [ 'theora' ],
+                       'type'      : "select",
+                       'group'     : "quality"
+               },
+               'audioCodec': {
+                       'default'   : "vorbis",
+                       'selectVal' : [ 'vorbis' ],
+                       'type'      : "select",
+                       'group'     : "quality"
+               },
+               'width': {
+                       'range'     : { 'min': 0, 'max': 1080 },
+                       'step'      : 4,
+                       'type'      : 'slider',
+                       'group'     : "quality"
+               },
+               'height': {
+                       'range'     : { 'min': 0, 'max' : 1080 },
+                       'step'      : 4,
+                       'type'      : "slider",
+                       'group'     : "quality"
+               },
+
+               // Advanced video control
+               'videoBitrate': {
+                       'range'     : { 'min' : 1, 'max' : 16778 },
+                       'type'      : "slider",
+                       'group'     : "advVideo",
+               } ,
+               'twopass': {
+                       'type'      : "boolean",
+                       'group'     : "advVideo"
+               },
+               'framerate': {
+                       'default'   : '24',
+                       'selectVal' : [ '12', '16', { '24000:1001' : '23.97' }, '24', '25', 
+                               { '30000:1001' : '29.97' }, '30' ],
+                       'type'      : "select",
+                       'group'     : "advVideo"
+               },
+               'aspect': {
+                       'default'   : '4:3',
+                       'type'      : "select",
+                       'selectVal' : [ '4:3', '16:9' ],
+                       'group'     : "advVideo"
+               },
+               'keyframeInterval': {
+                       'default'   : '64',
+                       'range'     : { 'min': 0, 'max': 65536 },
+                       'numberType': 'force keyframe every $1 frames',
+                       'type'      : 'int',
+                       'group'     : 'advVideo'
+               },
+               'denoise': {
+                       'type'      : "boolean",
+                       'group'     : 'advVideo'
+               },
+               'novideo': {
+                       'type'      : "boolean",
+                       'group'     : 'advVideo'
+               },
+
+               // Advanced audio control
+               'audioBitrate': {
+                       'range'     : { 'min': 32, 'max': 500 },
+                       'numberType': '$1 kbs',
+                       'type'      : 'slider'
+               },
+               'samplerate': {
+                       'type'      : 'select',
+                       'selectVal' : [ { '22050': '22 kHz' }, { '44100': '44 khz' }, { '48000': '48 khz' } ],
+                       'formatSelect' : function( val ) {
+                               return ( Math.round( val / 100 ) * 10 ) + ' Hz';
+                       }
+               },
+               'noaudio': {
+                       'type'      : 'boolean',
+                       'group'     : 'advAudio'
+               },
+
+               // Meta tags
+               'title': {
+                       'type'      : 'string',
+                       'group'     : 'meta'
+               },
+               'artist': {
+                       'type'      : 'string',
+                       'group'     : 'meta'
+               },
+               'date': {
+                       'group'     : 'meta',
+                       'type'      : 'date'
+               },
+               'location': {
+                       'type'      : 'string',
+                       'group'     : 'meta'
+               },
+               'organization': {
+                       'type'      : 'string',
+                       'group'     : 'meta'
+               },
+               'copyright':  {
+                       'type'      : 'string',
+                       'group'     : 'meta'
+               },
+               'license': {
+                       'type'      : 'string',
+               },
+               'contact': {
+                       'type'      : 'string',
+                       'group'     : 'meta'
+               }
+       },
+
+       /**
+        * Initialise this object
+        */
+       init: function( options ) {
+               // Set up a supported object:
+               for ( var key in options ) {
+                       if ( typeof default_mvAdvFirefogg_config[key] != 'undefined' ) {
+                               this[key] = options[key];
+                       }
+               }
+               // Inherit the base mvFirefogg class:
+               var baseFirefogg = new mvFirefogg( options );
+               for ( var key in baseFirefogg ) {
+                       if ( typeof this[key] != 'undefined' ) {
+                               this[ 'basefogg_' + key ] = baseFirefogg[ key ];
+                       } else {
+                               this[ key ] = baseFirefogg[ key ];
+                       }
+               }
+       },
+
+       setupForm: function() {
+               basefogg_setupForm();
+               this.createControls();
+               this.bindControls();
+       },
+
+       createControls: function() {
+               js_log( "adv createControls" );
+               var _this = this;
+               // Load presets from the cookie
+               this.loadEncSettings();
+
+               // Add the base control buttons
+               this.basefogg_createControls();
+
+               // Build the config group output
+               var gdout = '';
+               $j.each( this.config_groups, function( inx, group_key ) {
+                       gdout += '<div> ' +
+                               '<h3><a href="#" class="gd_' + group_key + '" >' + 
+                               gM( 'fogg-cg-' + group_key ) + '</a></h3>' +
+                               '<div>';
+                       // Output this group's control options:
+                       gdout += '<table width="' + ( $j( _this.selector ).width() - 60 ) + '" >' + 
+                               '<tr><td width="35%"></td><td width="65%"></td></tr>';
+                       // If this is the preset group, output the preset control
+                       if ( group_key == 'preset' ) {
+                               gdout += _this.getPresetControlHtml();
+                       }
+                       // Output the encoder config controls
+                       for ( var configKey in _this.default_encoder_config ) {
+                               var confEntry = _this.default_encoder_config[ configKey ];
+                               if( confEntry.group == group_key ) {
+                                       gdout += _this.getConfigControlHtml( configKey );
+                               }
+                       }
+                       gdout += '</table></div></div>';
+               });
+               // Add the control container
+               if( !this.target_control_container ) {
+                       this.target_control_container = this.selector + ' .control_container';
+                       $j( this.selector ).append( '<p><div class="control_container"></div>' );
+               }
+               // Hide the container and add the output
+               $j( this.target_control_container ).hide();
+               $j( this.target_control_container ).html( gdout );
+       },
+
+       // Custom advanced target rewrites
+       getControlHtml: function( target ) {
+               switch ( target ) {
+                       case 'target_btn_select_file':
+                       case 'target_btn_select_new_file':
+                       case 'target_btn_save_local_file':
+                               var icon;
+                               if ( target == 'target_btn_save_local_file' ) {
+                                       icon = 'ui-icon-video'
+                               } else {
+                                       icon = 'ui-icon-folder-open';
+                               }
+                               var linkText = gM( target.replace( /^target_btn_/, 'fogg-' ) );
+                               return '<a class="ui-state-default ui-corner-all ui-icon_link ' +
+                                                       target + '" href="#"><span class="ui-icon ' + icon + '"/>' +
+                                                       linkText +
+                                               '</a>';
+                       case 'target_btn_select_url':
+                               return $j.btnHtml( gM( 'fogg-select_url' ), target,  'link' );
+                       case 'target_use_latest_firefox':
+                       case 'target_please_install':
+                       case 'target_passthrough_mode':
+                               var text = gM( target.replace( '/^target_', 'fogg-' ) );
+                               return 
+                                       '<div ' + 
+                                               'style="margin-top:1em;padding: 0pt 0.7em;" ' + 
+                                               'class="ui-state-error ui-corner-all ' +
+                                               target + '">' +
+                                       '<p>' + 
+                                       '<span style="float: left; margin-right: 0.3em;" ' + 
+                                               'class="ui-icon ui-icon-alert"/>' +
+                                       text + 
+                                       '</p>' +
+                                       '</div>';
+                       case 'target_input_file_name':
+                               var text = gM( 'fogg-input_file_name' );
+                               return '<br><br><input style="" ' + 
+                                       'class="text ui-widget-content ui-corner-all ' + target + '" ' +
+                                       'type="text" value="' + text + '" size="60" /> ';
+                       default:
+                               js_log( 'call : basefogg_getTargetHtml' );
+                               return this.basefogg_getTargetHtml( target );
+               }
+       },
+
+       getPresetControlHtml: function() {
+               var out = '';
+               var _this = this;
+               js_log( 'getPresetControlHtml::' );
+               if ( typeof this.local_settings.presets != 'undefined' ) {
+                       out += '<select class="_preset_select">';
+                       $j.each( this.local_settings.presets, function( presetKey, preset ) {
+                               var presetDesc = preset.descKey ? gM( preset.descKey ) : preset.desc;
+                               var sel = ( _this.local_settings['default'] == presetKey ) ? ' selected' : '';
+                               out += '<option value="' + presetKey + '" ' + sel + '>' + presetDesc + '</option>';
+                       });
+                       out += '</select>';
+               }
+               return out;
+       },
+
+       getConfigControlHtml : function( configKey ) {
+               var configEntry = this.default_encoder_config[configKey];
+               var out = '';
+               out += '<tr><td valign="top">' +
+                       '<label for="_' + configKey + '">' +
+                       gM( 'fogg-' + configKey + '-title' ) + ':' +
+                       '<span title="' + gM( 'fogg-help-sticky' ) + '" ' + 
+                               'class="help_' + configKey + ' ui-icon ui-icon-info" style="float:left">' + 
+                       '</span>' +
+                       '</label></td><td valign="top">';
+               // Get the default value (or an empty string if there is no default)
+
+               var defaultValue = this.default_encoder_config[configKey]['default'];
+               if ( !defaultValue ) {
+                       defaultValue = '';
+               }
+               var type = configEntry.type; // shortcut
+
+               // Switch on the config type
+               switch( type ) {
+                       case 'string':
+                       case 'date':
+                       case 'int':
+                       case 'float':
+                               var size = ( type == 'string' || type == 'date' ) ? '14' : '4';
+                               out += '<input ' + 
+                                       'size="' + size + '" ' + 
+                                       'type="text" ' + 
+                                       'class="_' + configKey + ' text ui-widget-content ui-corner-all" ' + 
+                                       'value="' + defaultValue + '" >';
+                               break;
+                       case 'boolean':
+                               var checked_attr = ( defaultValue === true ) ? ' checked="true"' : '';
+                               out += '<input ' + 
+                                       'type="checkbox" ' + 
+                                       'class="_' + configKey + ' ui-widget-content ui-corner-all" ' + 
+                                       checked_attr + '>';
+                               break;
+                       case 'slider':
+                               var strMax = this.default_encoder_config[ configKey ].range.max + '';
+                               maxDigits = strMax.length + 1;
+                               out += '<input ' + 
+                                       'type="text" ' + 
+                                       'maxlength="' + maxDigits + '" ' + 
+                                       'size="' + maxDigits + '" ' +
+                                       'class="_' + configKey + ' text ui-widget-content ui-corner-all" ' + 
+                                       'style="display:inline;border:0; color:#f6931f; font-weight:bold;" ' +
+                                       'value="' + defaultValue + '" >' +
+                                       '<div class="slider_' + configKey + '"></div>';
+                               break;
+                       case 'select':
+                               out += '<select class="_' + configKey + '">' +
+                                               '<option value=""> </option>';
+                               for ( var i in configEntry.selectVal ) {
+                                       var val = configEntry.selectVal[i];
+                                       if ( typeof val == 'string' ) {
+                                               var sel = ( configEntry.selectVal[i] == val ) ? ' selected' : '';
+                                               out += '<option value="' + val + '"'+sel+'>' + val + '</option>';
+                                       } else if ( typeof val == 'object' ) {
+                                               for ( var key in val ) {
+                                                       hr_val = val[key];
+                                               }
+                                               var sel = ( configEntry.selectVal[i] == key ) ? ' selected' : '';
+
+                                               out += '<option value="' + key + '"' + sel + '>' + hr_val + '</option>';
+                                       }
+                               }
+                               out += '</select>';
+                               break;
+               }
+               // output the help row:
+               out += '<div class="helpRow_' + configKey + '">' +
+                               '<span class="helpClose_' + configKey + ' ui-icon ui-icon-circle-close" ' +
+                               'title="Close Help"' +
+                               'style="float:left"/>' +
+                               gM( 'fogg-'+ configKey + '-help' ) +
+                               '</div>';
+               out += '</td></tr><tr><td colspan="2" height="10"></td></tr>';
+               return out;
+       },
+
+       /**
+        * Show a dialog box asking the user to select a source URL.
+        * FIXME: half-written, doesn't work at all. 
+        */
+       selectSourceUrl: function() {
+               // FIXME: i18n
+               var url = prompt( "Please enter the source media url you would like " + 
+                               "to transcode from.", "http://" );
+               if ( !url ) {
+                       return;
+               }
+
+               // update the mode:
+               this.sourceMode = 'url';
+               this.sourceUrl = url;
+               this.clearSourceInfoCache();
+               this.updateSourceFileUI();
+               // update the input target
+               $j( this.target_input_file_name ) 
+                       .unbind()
+                       .val( url )
+                       .removeAttr( 'readonly' );
+       },
+
+       bindControls: function() {
+               var _this = this;
+               _this.basefogg_bindControls();
+
+               // Show the select by URL if present
+               /*$j( this.target_btn_select_url ).unbind()
+                       .attr( 'disabled', false )
+                       .css( { 'display': 'inline' } )
+                       .click( function() {
+                               _this.selectSourceUrl();
+                       });
+               */
+
+               // Hide the base advanced controls until a file is selected:
+               $j( this.target_control_container ).hide();
+
+               var helpState = {};
+               // Do some display tweaks
+               js_log( 'tw:' + $j( this.selector ).width() +
+                       ' ssf:' + $j( this.target_btn_select_new_file ).width() +
+                       ' sf:' + $j( this.target_btn_save_local_file ).width() );
+
+               // Set width to 250
+               $j( this.target_input_file_name ).width( 250 );
+
+               // Special preset action
+               $j( this.selector + ' ._preset_select' ).change( function() {
+                       _this.updatePresetSelection( $j( this ).val() );
+               });
+
+               // Bind control actions
+               for ( var configKey in this.default_encoder_config ) {
+                       var confEntry =  this.default_encoder_config[configKey];
+
+                       // Initial state is hidden
+                       $j( this.selector + ' .helpRow_' + configKey ).hide();
+
+                       $j( this.selector + ' .help_' + configKey )
+                               .click(
+                                       function() {
+                                               // Get the config key (assume it's the last class)
+                                               var configKey = _this.getClassId( this, 'help_' );
+
+                                               if ( helpState[configKey] ) {
+                                                       $j( _this.selector + ' .helpRow_' + configKey ).hide( 'slow' );
+                                                       helpState[configKey] = false;
+                                               } else {
+                                                       $j( _this.selector + ' .helpRow_' + configKey ).show( 'slow' );
+                                                       helpState[configKey] = true;
+                                               }
+                                               return false;
+                                       }
+                               )
+                               .hover(
+                                       function() {
+                                               // get the config key (assume it's the last class)
+                                               var configKey = _this.getClassId( this, 'help_' );
+                                               $j( _this.selector + ' .helpRow_' + configKey ).show( 'slow' );
+                                       },
+                                       function() {
+                                               var configKey = _this.getClassId( this, 'help_' );
+                                               if( !helpState[configKey] )
+                                                       $j( _this.selector + ' .helpRow_' + configKey ).hide( 'slow' )
+                                       }
+                               );
+
+                       $j( this.selector + ' .helpClose_' + configKey )
+                               .click(
+                                       function() {
+                                               js_log( "close help: " + configKey );
+                                               // get the config key (assume it's the last class)
+                                               var configKey = _this.getClassId( this, 'helpClose_' );
+                                               $j( _this.selector + ' .helpRow_' + configKey ).hide( 'slow' );
+                                               helpState[configKey] = false;
+                                               return false;
+                                       }
+                               )
+                               .css( 'cursor', 'pointer' );
+
+                       // Set up bindings for the change events (validate input)
+
+                       switch ( confEntry.type ) {
+                               case 'boolean':
+                                       $j( this.selector + ' ._' + configKey)
+                                               .click( function() {
+                                                       _this.updateLocalValue( _this.getClassId( this ), 
+                                                               $j( this ).is( ":checked" ) );
+                                                       _this.updatePresetSelection( 'custom' );
+                                               });
+                                       break;
+                               case 'select':
+                               case 'string':
+                               case 'int':
+                               case 'float':
+                                       //@@check if we have a validate function on the string
+                                       $j( this.selector + ' ._' + configKey ).change( function() {
+                                               $j( this ).val( _this.updateLocalValue(
+                                                       _this.getClassId( this ),
+                                                       $j( this ).val() ) );
+                                               _this.updatePresetSelection( 'custom' );
+                                       })
+                                       break;
+                               case 'date':
+                                       $j( this.selector + ' ._' + configKey ).datepicker({
+                                                       changeMonth: true,
+                                                       changeYear: true,
+                                                       dateFormat: 'd MM, yy',
+                                                       onSelect: function( dateText ) {
+                                                               _this.updateInterfaceValue( _this.getClassId( this ), dateText );
+                                                       }
+                                       });
+                                       break;
+                               case 'slider':
+                                       var sliderId = _this.getClassId( this, 'slider_' );
+                                       $j( this.selector + ' .slider_' + configKey ).slider({
+                                               range: "min",
+                                               animate: true,
+                                               step: confEntry.step ? confEntry.step : 1,
+                                               value: $j( this.selector + ' ._' + configKey ).val(),
+                                               min: this.default_encoder_config[ configKey ].range.min,
+                                               max: this.default_encoder_config[ configKey ].range.max,
+                                               slide: function( event, ui ) {
+                                                       $j( _this.selector + ' ._' + sliderId ).val( ui.value );
+
+                                                       // Maintain source video aspect ratio
+                                                       if ( sliderId == 'width' ) {
+                                                               var sourceHeight = _this.sourceFileInfo.video[0]['height'];
+                                                               var sourceWidth = _this.sourceFileInfo.video[0]['width'];
+                                                               var newHeight = parseInt( sourceHeight / sourceWidth * ui.value );
+                                                               // Reject the update if the new height is above the maximum
+                                                               if ( newHeight > _this.updateInterfaceValue( 'height', newHeight ) )
+                                                                       return false;
+                                                       }
+                                                       if ( sliderId == 'height' ) {
+                                                               var sourceHeight = _this.sourceFileInfo.video[0]['height'];
+                                                               var sourceWidth = _this.sourceFileInfo.video[0]['width'];
+                                                               var newWidth = parseInt( sourceWidth / sourceHeight * ui.value );
+                                                               // Reject the update if the new width is above the maximum
+                                                               if ( newWidth > _this.updateInterfaceValue( 'width', wv ) )
+                                                                       return false;
+                                                       }
+                                               },
+                                               change: function( event, ui ) {
+                                                       _this.updateLocalValue( sliderId, ui.value );
+                                                       _this.updatePresetSelection( 'custom' );
+                                               }
+                                       });
+
+                                       $j( this.selector + ' ._' + configKey ).change( function() {
+                                               var classId = _this.getClassId( this );
+                                               var validValue = _this.updateLocalValue( classId.substr( 1 ), 
+                                                       $j( this ).val() );
+                                               _this.updatePresetSelection( 'custom' );
+                                               // Change it to the validated value
+                                               $j( this ).val( validValue );
+                                               // update the slider
+                                               js_log( "update: " + _this.selector + ' .slider' + classId );
+                                               $j( _this.selector + ' .slider' + classId )
+                                                       .slider( 'option', 'value', validValue );
+                                       });
+                                       break;
+                       }
+               }
+
+               $j( this.target_control_container ).accordion({
+                       header: "h3",
+                       collapsible: true,
+                       active: false,
+                       fillSpace: true
+               });
+
+               // Do the config value updates if there are any
+               this.updateValuesInHtml();
+       },
+
+       /**
+        * Update the UI due to a change in preset
+        */
+       updatePresetSelection: function( presetKey ) {
+               // Update the local configuration
+               this.local_settings['default'] = presetKey;
+               // js_log( 'update preset desc: ' + presetKey );
+               var presetDesc = '';
+               if ( this.local_settings.presets[presetKey].desc ) {
+                       presetDesc = this.local_settings.presets[presetKey].desc;
+               } else {
+                       presetDesc = gM( 'fogg-preset-' + presetKey );
+               }
+               // Update the preset title
+               $j( this.selector + ' .gd_preset' )
+                       .html( gM( 'fogg-cg-preset', presetDesc ) );
+               // update the selector
+               $j( this.selector + ' ._preset_select' ).val( presetKey );
+       },
+
+       /*
+        * Update the interface due to a change in a particular config key
+        */
+       updateInterfaceValue: function( confKey, val ) {
+               var _this = this;
+               if ( !val ) {
+                       return;
+               }
+               // Look up the type
+               if ( typeof this.default_encoder_config[confKey] == 'undefined' ) {
+                       js_error( 'error: missing default key: ' + confKey );
+                       return false;
+               }
+
+               // Update the local value (if it's not already up-to-date)
+               if ( this.local_settings.presets['custom']['conf'][confKey] != val ) {
+                       val = this.updateLocalValue( confKey, val );
+               }
+               // Update the text field
+               $j( _this.selector + ' ._' + confKey ).val( val );
+               // Update the interface widget
+               switch ( this.default_encoder_config[confKey].type ) {
+                       case 'slider':
+                               $j( _this.selector + ' .slider_' + confKey )
+                                       .slider( 'option', 'value', $j( _this.selector + ' ._' + confKey ).val() );
+                               break;
+               }
+               return val;
+       },
+
+       /**
+        * Validate the new config setting, fixing its type and bounding it within a 
+        * range if required. Update the configuration with the validated value and 
+        * return it.
+        */
+       updateLocalValue: function( confKey, value ) {
+               if ( typeof this.default_encoder_config[confKey] == 'undefined' ) {
+                       js_log( "Error: could not update conf key: " + confKey )
+                       return value;
+               }
+               var confEntry = this.default_encoder_config[confKey];
+               var range = confEntry.range;
+               if ( range ) {
+                       value = parseInt( value );
+                       var min = ( range.local_min ) ? range.local_min : range.min;
+                       if ( value < min )
+                               value = min;
+                       var max = ( range.local_max ) ? range.local_max : range.max;
+                       if (value > max )
+                               value = max;
+               }
+               if ( confEntry.type == 'int' )
+                       value = parseInt( value );
+
+               // step value:
+               /* if( confEntry.step ) {
+                       if ( ( value % confEntry.step ) != 0 ) {
+                               value = value - (value % confEntry.step);
+                       }
+               }*/
+
+               js_log( 'update:local_settings:custom:conf:' + confKey + ' = ' + value );
+               this.local_settings.presets['custom']['conf'][confKey] = value;
+
+               return value;
+       },
+
+       /**
+        * Get a local config value from the custom preset
+        */
+       getLocalValue: function( confKey ) {
+               return this.local_settings.presets['custom']['conf'][confKey];
+       },
+
+       /**
+        * Given an element or selector, get its primary class, and strip a given 
+        * prefix from it.
+        *
+        * If no prefix is given, "_" is assumed.
+        */
+       getClassId: function( element, prefix ) {
+               var eltClass = $j( element ).attr( "class" ).split( ' ' ).slice( 0, 1 ).toString();
+
+               if ( !prefix ) {
+                       prefix = '_';
+               }
+               if ( eltClass.substr( 0, prefix.length ) == prefix ) {
+                       eltClass = eltClass.substr( prefix.length );
+               }
+               return eltClass;
+       },
+
+       /**
+        * Get the appropriate encoder settings for the current Firefogg object, 
+        * into which a video has already been selected. Overrides the base method.
+        */
+       getEncoderSettings: function() {
+               if ( this.current_encoder_settings != null ) {
+                       return this.current_encoder_settings;
+               }
+
+               // Call the base function
+               // Note that settings will be a reference and can be modified
+               var settings = this.basefogg_getEncoderSettings();
+
+               // Allow re-encoding of files that are already ogg (unlike in the base class)
+               if ( this.isOggFormat() ) {
+                       settings['passthrough'] = false;
+               }
+       },
+
+       /**
+        * Do the necessary UI updates due to the source file changing.
+        * Overrides the parent method.
+        */
+       updateSourceFileUI: function() {
+               var _this = this;
+
+               // Call the parent
+               _this.basefogg_updateSourceFileUI();
+
+               var settings = this.getEncoderSettings();
+               var fileInfo = this.getSourceFileInfo();
+
+               // In passthrough mode, hide encoder controls
+               if ( settings['passthrough'] ) {
+                       js_log( "in passthrough mode (hide control)" );
+                       $j( this.target_control_container ).hide( 'slow' );
+                       $j( this.target_passthrough_mode ).show( 'slow' );
+                       return;
+               }
+
+               // Show encoder controls
+               $j( this.target_control_container ).show( 'slow' );
+               $j( this.target_passthrough_mode ).hide( 'slow' );
+
+               // do set up settings based on local_settings /default_encoder_config with sourceFileInfo
+               // see: http://firefogg.org/dev/sourceInfo_example.html
+               var setValues = function( k, val, maxVal ) {
+                       if ( k !== false ) {
+                               // update the value if unset:
+                               _this.updateLocalValue( k, val );
+                       }
+                       if ( maxVal ) {
+                               // update the local range:
+                               if ( _this.default_encoder_config[k].range ) {
+                                       _this.default_encoder_config[k].range.local_max = maxVal;
+                               }
+                       }
+               }
+               // container level settings
+               for ( var i in fileInfo ) {
+                       var val = fileInfo[i];
+                       var k = false;
+                       var maxVal = false;
+                       switch ( i ) {
+                               // do nothing with these:
+                               case 'bitrate':
+                                       k = 'videoBitrate';
+                                       if ( val * 2 > this.default_encoder_config[k] ) {
+                                               maxVal = this.default_encoder_config[k];
+                                       } else {
+                                               maxVal = val * 2;
+                                       }
+                                       break;
+                       }
+                       setValues( k, val, maxVal );
+               }
+               // video stream settings
+               for ( var i in fileInfo.video[0] ) {
+                       var val = fileInfo.video[0][i];
+                       var k = false;
+                       var maxVal= false;
+                       switch( i ) {
+                               case 'width':
+                               case 'height':
+                                       k = i;
+                                       maxVal = val;
+                                       break;
+                       }
+                       setValues( k, val, maxVal );
+               }
+               // audio stream settings, assumes for now thare is only one stream
+               for ( var i in fileInfo.audio[0] ) {
+                       var val = fileInfo.audio[0][i];
+                       var k = false;
+                       var maxVal = false;
+                       switch ( i ) {
+                               case 'bitrate':
+                                       k = 'audioBitrate';
+                                       if ( val * 2 > this.default_encoder_config[k] ) {
+                                               maxVal = this.default_encoder_config[k];
+                                       } else {
+                                               maxVal = val * 2;
+                                       }
+                                       break;
+                       }
+                       setValues( k, val, maxVal );
+               }
+
+               // set all values to new default ranges & update slider:
+               $j.each( this.default_encoder_config, function( inx, val ) {
+                       if ( $j( _this.selector + ' ._' + inx ).length != 0 ) {
+                               if ( typeof val.range != 'undefined' ) {
+                                       // update slider range
+                                       var new_max = (val.range.local_max) ? val.range.local_max : val.range.max
+                                       $j( _this.selector + ' .slider_' + inx ).slider( 'option', 'max', new_max );
+
+                                       // update slider/input value:
+                                       _this.updateInterfaceValue( inx, 
+                                               _this.local_settings.presets['custom']['conf'][inx] );
+                               }
+                       }
+               });
+               // update values
+               this.updateValuesInHtml();
+       },
+
+       doEncode: function() {
+               // update the encoder settings (from local settings)
+               pKey = this.local_settings['default'];
+               this.encoder_settings = this.local_settings.presets[ pKey ].conf;
+               this.basefogg_doEncode();
+       },
+
+       /**
+        * Set the HTML control values to whatever is currently present in this.local_settings
+        */
+       updateValuesInHtml: function() {
+               js_log( 'updateValuesInHtml::' );
+               var _this = this;
+               var pKey = this.local_settings['default'];
+               this.updatePresetSelection( pKey );
+
+               // set the actual HTML & widgets based on any local settings values:
+               $j.each( _this.local_settings.presets['custom']['conf'], function( inx, val ) {
+                       if ( $j( _this.selector + ' ._' + inx ).length != 0 ) {
+                               $j( _this.selector + ' ._' + inx ).val( val );
+                       }
+               });
+       },
+
+       /**
+        * Restore settings from a cookie (if available)
+        */
+       loadEncSettings: function( force ) {
+               if ( $j.cookie( 'fogg_encoder_config' ) ) {
+                       js_log( "load:fogg_encoder_config from cookie " );
+                       this.local_settings = JSON.parse( $j.cookie( 'fogg_settings' ) );
+               }
+               // set to default if not loaded yet:
+               if ( this.local_settings && this.local_settings.presets 
+                       && this.local_settings.presets['custom']['conf'] ) 
+               {
+                       js_log( 'local settings already populated' );
+               } else {
+                       this.local_settings = this.default_local_settings;
+               }
+       },
+
+       /**
+        * Clear preset settings
+        * FIXME: not called, does nothing
+        */
+       clearSettings: function( force ) {
+       },
+
+       /**
+        * Save the current encoder settings to a cookie.
+        */
+       saveEncSettings: function() {
+               $j.cookie( 'fogg_settings', JSON.stringify( this.local_settings ) );
+       }
+};
diff --git a/js2/mwEmbed/libAddMedia/mvBaseUploadInterface.js b/js2/mwEmbed/libAddMedia/mvBaseUploadInterface.js
new file mode 100644 (file)
index 0000000..5dbb6c3
--- /dev/null
@@ -0,0 +1,1039 @@
+/**
+ * The base upload interface.
+ *
+ * This base upload class is optionally extended by Firefogg
+ *
+ */
+loadGM({
+       "mwe-upload-transcode-in-progress" : "Transcode and upload in progress (do not close this window)",
+       "mwe-upload-in-progress" : "Upload in progress (do not close this window)",
+       "mwe-upload-transcoded-status" : "Transcoded",
+       "mwe-uploaded-status" : "Uploaded",
+       "mwe-upload-stats-fileprogress" : "$1 of $2",
+       "mwe-upload_completed" : "Your upload is complete",
+       "mwe-upload_done" : "<a href=\"$1\">Your upload <i>should be<\/i> accessible<\/a>.",
+       "mwe-upload-unknown-size" : "Unknown size",
+       "mwe-cancel-confim" : "Are you sure you want to cancel?",
+       "mwe-successfulupload" : "Upload successful",
+       "mwe-uploaderror" : "Upload error",
+       "mwe-uploadwarning" : "Upload warning",
+       "mwe-unknown-error" : "Unknown error:",
+       "mwe-return-to-form" : "Return to form",
+       "mwe-file-exists-duplicate" : "This file is a duplicate of the following file:",
+       "mwe-fileexists" : "A file with this name exists already. Please check <b><tt>$1<\/tt><\/b> if you are not sure if you want to change it.",
+       "mwe-fileexists-thumb" : "<center><b>Existing file<\/b><\/center>",
+       "mwe-ignorewarning" : "Ignore warning and save file anyway",
+       "mwe-file-thumbnail-no" : "The filename begins with <b><tt>$1<\/tt><\/b>",
+       "mwe-go-to-resource" : "Go to resource page",
+       "mwe-upload-misc-error" : "Unknown upload error",
+       "mwe-wgfogg_warning_bad_extension" : "You have selected a file with an unsuported extension (<a href=\"http:\/\/commons.wikimedia.org\/wiki\/Commons:Firefogg#Supported_File_Types\">more information<\/a>)."
+});
+
+var default_bui_options = {
+       'api_url': null,
+       'parent_uploader': null,
+       'form': null,
+       'done_upload_cb': null,
+       'form_selector': null,
+
+       // Default upload mode is 'api'
+       'upload_mode': 'api'
+
+}
+var mvBaseUploadInterface = function( options ) {
+       return this.init( options );
+}
+
+mvBaseUploadInterface.prototype = {
+       parent_uploader: false,
+       formData: {}, // The form data to be submitted
+       warnings_sessionkey: null,
+       chunks_supported: true,
+       form_post_override: false,
+       http_copy_upload : null,
+       action_done: false,
+       editToken: false,
+
+       // The DOM node for the upload form
+       form: false,
+
+       /**
+        * Object initialisation
+        */
+       init: function( options ) {
+               if ( !options )
+                       options = {};
+               $j.extend( this, default_bui_options, options );
+               js_log( "init mvBaseUploadInterface:: " + this.api_url );
+       },
+
+       /**
+        * Set up the upload form, register onsubmit handler.
+        * May remap it to use the API field names.
+        */
+       setupForm: function() {
+               js_log( "Base::setupForm::" );
+               var _this = this;
+               // Set up the local pointer to the edit form:
+               this.form = this.getForm();
+               if ( !this.form ) {
+                       js_log( "Upload form not found!" );
+                       return;
+               }
+
+               // If we're in API mode, re-map the upload form to API.
+               if ( this.upload_mode == 'api' ) {
+                       this.remapFormToApi();
+               }
+
+               // Set up the orig_onsubmit if not set:
+               if ( typeof( this.orig_onsubmit ) == 'undefined' && this.form.onsubmit ) {
+                       this.orig_onsubmit = this.form.onsubmit;
+               }
+
+               // Set up the submit action:
+               $j( this.form ).submit( function() {
+                       return _this.onSubmit();
+               } );
+       },
+
+       /**
+        * onsubmit handler for the upload form
+        */
+       onSubmit: function() {
+               var _this = this;
+               js_log( 'Base::onSubmit:' );
+               // Run the original onsubmit (if not run yet set flag to avoid excessive chaining)
+               if ( typeof( this.orig_onsubmit ) == 'function' ) {
+                       if ( ! this.orig_onsubmit() ) {
+                               //error in orig submit return false;
+                               return false;
+                       }
+               }
+               // Check for post action override
+               if ( this.form_post_override ) {
+                       js_log( 'form_post_override is true, do ordinary form submit' );
+                       return true;
+               }
+
+               // Get the input form data into an array
+               js_log( 'update formData::' );
+               var data = $j( this.form ).serializeArray();
+               this.formData = {};
+               for ( var i = 0; i < data.length; i++ ) {
+                       if ( data[i]['name'] )
+                               this.formData[ data[i]['name'] ] = data[i]['value'];
+               }               
+               // Put into a try catch so we are sure to return false:
+               try {
+                       
+                       // Display a progress dialog
+                       _this.displayProgressOverlay();
+
+                       // For some unknown reason we have to drop down the #p-search z-index:
+                       $j( '#p-search' ).css( 'z-index', 1 );
+
+                       var _this = this;
+                       _this.detectUploadMode( function( mode ) {
+                               _this.upload_mode = mode;
+                               _this.doUpload();
+                       } );
+               } catch( e ) {
+                       js_log( '::error in displayProgressOverlay or doUpload' );
+               }
+
+               // Don't submit the form we will do the post in ajax
+               return false;
+       },
+
+       /**
+        * Determine the correct upload mode.
+        *
+        * If this.upload_mode is autodetect, this runs an API call to find out if MW
+        * supports uploading. It then sets the upload mode when this call returns.
+        *
+        * When done detecting, or if detecting is unnecessary, it calls the callback 
+        * with the upload mode as the first parameter.
+        */
+       detectUploadMode: function( callback ) {
+               var _this = this;
+               js_log( 'detectUploadMode::' +  _this.upload_mode );
+               // Check the upload mode
+               if ( _this.upload_mode == 'detect_in_progress' ) {
+                       // Don't send another request, wait for the pending one.
+               } else if ( !_this.isCopyUpload() ) {
+                       callback( 'post' );
+               } else if ( _this.upload_mode == 'autodetect' ) {
+                       js_log( 'detectUploadMode::' + _this.upload_mode + ' api:' + _this.api_url );
+                       if( !_this.api_url ) {
+                               js_error( 'Error: can\'t autodetect mode without api url' );
+                               return;
+                       }
+
+                       // Don't send multiple requests
+                       _this.upload_mode = 'detect_in_progress';
+
+                       // FIXME: move this to configuration and avoid this API request
+                       do_api_req(
+                               {
+                                       'data': { 'action' : 'paraminfo', 'modules' : 'upload' },
+                                       'url' : _this.api_url
+                               },
+                               function( data ) {
+                                       if ( typeof data.paraminfo == 'undefined'
+                                               || typeof data.paraminfo.modules == 'undefined' )
+                                       {
+                                               return js_error( 'Error: bad api results' );
+                                       }
+                                       if ( typeof data.paraminfo.modules[0].classname == 'undefined' ) {
+                                               js_log( 'Autodetect Upload Mode: \'post\' ' );
+                                               _this.upload_mode = 'post';
+                                               callback( 'post' );
+                                       } else {
+                                               js_log( 'Autodetect Upload Mode: api ' );
+                                               _this.upload_mode = 'api';
+                                               // Check to see if chunks are supported
+                                               for ( var i in data.paraminfo.modules[0].parameters ) {
+                                                       var pname = data.paraminfo.modules[0].parameters[i].name;
+                                                       if( pname == 'enablechunks' ) {
+                                                               js_log( 'this.chunks_supported = true' );
+                                                               _this.chunks_supported = true;
+                                                               break;
+                                                       }
+                                               }
+                                               callback( 'api' );
+                                       }
+                               }
+                       );
+               } else if ( _this.upload_mode == 'api' ) {
+                       callback( 'api' );
+               } else if ( _this.upload_mode == 'post' ) {
+                       callback( 'post' );
+               } else {
+                       js_error( 'Error: unrecongized upload mode: ' + _this.upload_mode );
+               }
+       },
+
+       /**
+        * Do an upload, with the mode given by this.upload_mode
+        */
+       doUpload: function() {
+               if ( this.upload_mode == 'api' ) {
+                       this.doApiCopyUpload();
+               } else if ( this.upload_mode == 'post' ) {
+                       this.doPostUpload();
+               } else {
+                       js_error( 'Error: unrecongized upload mode: ' + this.upload_mode );
+               }
+       },
+
+       /**
+        * Change the upload form so that when submitted, it sends a request to
+        * the MW API.
+        *
+        * This is rather ugly, but solutions are constrained by the fact that 
+        * file inputs can't be moved around or recreated after the user has 
+        * selected a file in them, which they may well do before DOM ready.
+        */
+       remapFormToApi: function() {
+               var _this = this;
+               if ( !this.api_url )
+                       return false;
+
+               var form = $j( this.form );
+
+               // Set the form action
+               form.attr('action', _this.api_url);
+
+               // Add API action
+               if ( form.find( "[name='action']" ).length == 0 )
+                       form.append( '<input type="hidden" name="action" value="upload">' );
+
+               // Add JSON format
+               if ( form.find( "[name='format']" ).length == 0 )
+                       form.append( '<input type="hidden" name="format" value="jsonfm">' );
+
+               // Map a new hidden form
+               form.find( "[name='wpUploadFile']" ).attr( 'name', 'file' );
+               form.find( "[name='wpDestFile']" ).attr( 'name', 'filename' );
+               form.find( "[name='wpUploadDescription']" ).attr( 'name', 'comment' );
+               form.find( "[name='wpEditToken']" ).attr( 'name', 'token' );
+               form.find( "[name='wpIgnoreWarning']" ).attr( 'name', 'ignorewarnings' );
+               form.find( "[name='wpWatchthis']" ).attr( 'name', 'watch' );
+       },
+
+       /**
+        * Returns true if the current form has copy upload selected, false otherwise.
+        */
+       isCopyUpload: function() {      
+               if ( $j( '#wpSourceTypeFile' ).length ==  0
+                       || $j( '#wpSourceTypeFile' ).get( 0 ).checked )
+               {
+                       this.http_copy_upload = false;
+               } else if ( $j('#wpSourceTypeURL').get( 0 ).checked ) {
+                       this.http_copy_upload = true;
+               }
+               return this.http_copy_upload;
+       },
+
+       /**
+        * Do an upload by submitting the form
+        */
+       doPostUpload: function() {
+               var _this = this;
+               var form = $j( _this.form );
+               js_log( 'mvBaseUploadInterface.doPostUpload' );
+
+               // Issue a normal post request
+               // Get the token from the page
+               _this.editToken = $j( "#wpEditToken" ).val();
+
+               //@@TODO check for sendAsBinary to support Firefox/HTML5 progress on upload
+
+
+               // Add the iframe
+               _this.iframeId = 'f_' + ( $j( 'iframe' ).length + 1 );
+               $j( "body" ).append( '<iframe src="javascript:false;" id="' + _this.iframeId + '" ' +
+                       'name="' + _this.iframeId + '" style="display:none;" ></iframe>' );
+
+               // Set the form target to the iframe
+               form.attr( 'target', _this.iframeId );
+
+               // Set up the completion callback
+               $j( '#' + _this.iframeId ).load( function() {
+                       _this.processIframeResult( $j( this ).get( 0 ) );
+               });
+
+               // Set the action to the API URL:
+               form.attr( 'action', _this.api_url );
+
+               js_log( 'Do iframe form submit to: ' +  form.attr( 'target' ) );
+               js_log( ' destName:' + form.find( "[name='filename']" ).val() );
+
+               // Do post override
+               _this.form_post_override = true;
+               // Reset the done with action flag
+               _this.action_done = false;
+
+               form.submit();
+       },
+
+       /**
+        * Do an upload by submitting an API request
+        */
+       doApiCopyUpload: function() {
+               js_log( 'mvBaseUploadInterface.doApiCopyUpload' );
+               js_log( 'doHttpUpload (no form submit) ' );
+               var httpUpConf = {
+                       'url'       : $j( '#wpUploadFileURL' ).val(),
+                       'filename'  : $j( '#wpDestFile' ).val(),
+                       'comment'   : $j( '#wpUploadDescription' ).val(),
+                       'watch'     : ( $j( '#wpWatchthis' ).is( ':checked' ) ) ? 'true' : 'false',
+                       'ignorewarnings': ($j('#wpIgnoreWarning' ).is( ':checked' ) ) ? 'true' : 'false'
+               }
+               //check for editToken
+               this.editToken = $j( "#wpEditToken" ).val();
+               this.doHttpUpload( httpUpConf );
+       },
+
+       /**
+        * Process the result of the form submission, returned to an iframe.
+        * This is the iframe's onload event.
+        */
+       processIframeResult: function( iframe ) {
+               var _this = this;
+               var doc = iframe.contentDocument ? iframe.contentDocument : frames[iframe.id].document;
+               // Fix for Opera 9.26
+               if ( doc.readyState && doc.readyState != 'complete' ) {
+                       return;
+               }
+               // Fix for Opera 9.64
+               if ( doc.body && doc.body.innerHTML == "false" ) {
+                       return;
+               }
+               var response;
+               if ( doc.XMLDocument ) {
+                       // The response is a document property in IE
+                       response = doc.XMLDocument;
+               } else if ( doc.body ) {
+                       // Get the json string
+                       json = $j( doc.body ).find( 'pre' ).text();
+                       //js_log( 'iframe:json::' + json_str + "\nbody:" + $j( doc.body ).html() );
+                       if ( json ) {
+                               response = window["eval"]( "(" + json + ")" );
+                       } else {
+                               response = {};
+                       }
+               } else {
+                       // response is a xml document
+                       response = doc;
+               }
+               // Process the API result
+               _this.processApiResult( response );
+       },
+
+       /**
+        * Do a generic action=upload API request and monitor its progress
+        */
+       doHttpUpload: function( params ) {
+               var _this = this;
+               // Display the progress overlay (again)
+               _this.displayProgressOverlay();
+
+               // Set the HTTP box to "loading", in case we don't get an update for some time
+               $j( '#dlbox-centered' ).html( '<h5>' + _this.getProgressTitle() + '</h5>' +
+                       mv_get_loading_img( 'left:40%;top:20%' )
+               );
+
+               // Set up the request
+               var request = {
+                       'action'        : 'upload',
+                       'asyncdownload' : true // Do async download
+               };
+
+               // Add any parameters specified by the caller
+               for ( key in params ) {
+                       if ( !request[key] ) {
+                               request[key] = params[key];
+                       }
+               }
+
+               // Add the edit token (if available)
+               if( !_this.editToken && _this.api_url ) {
+                       js_log( 'Error:doHttpUpload: missing token' );
+               } else {
+                       request['token'] =_this.editToken;
+               }
+
+               // Reset the done with action flag
+               _this.action_done = false;
+
+               //do the api request
+               do_api_req({
+                       'data': request,
+                       'url' : _this.api_url
+               }, function( data ) {
+                       _this.processApiResult( data );
+               });
+       },
+
+       /**
+        * Start periodic checks of the upload status using XHR
+        */
+       doAjaxUploadStatus: function() {
+               var _this = this;
+
+               //set up the progress display for status updates:
+               this.displayProgressOverlay();
+               this.upload_status_request = {
+                       'action'     : 'upload',
+                       'httpstatus' : 'true',
+                       'sessionkey' : _this.upload_session_key
+               };
+               // Add token if present
+               if ( this.editToken )
+                       this.upload_status_request['token'] = this.editToken;
+
+               // Trigger an initial request (subsequent ones will be done by a timer)
+               this.onAjaxUploadStatusTimer();
+       },
+
+       /**
+        * This is called when the timer which separates XHR requests elapses.
+        * It starts a new request.
+        */
+       onAjaxUploadStatusTimer: function() {
+               var _this = this;
+               //do the api request:
+               do_api_req(
+                       {
+                               'data': this.upload_status_request,
+                               'url' : this.api_url
+                       },
+                       function ( data ) {
+                               _this.onAjaxUploadStatusResponse( data );
+                       }
+               );
+       },
+
+       /**
+        * Called when a response to an upload status query is available.
+        * Starts the timer for the next upload status check.
+        */
+       onAjaxUploadStatusResponse: function( data ) {
+               var _this = this;
+               //@@check if we are done
+               if ( data.upload['apiUploadResult'] ) {
+                       //update status to 100%
+                       _this.updateProgress( 1 );
+                       //see if we need JSON
+                       mvJsLoader.doLoad( [
+                               'JSON'
+                       ], function() {
+                               var apiResult = {};
+                               try {
+                                       apiResult = JSON.parse( data.upload['apiUploadResult'] ) ;
+                               } catch ( e ) {
+                                       //could not parse api result
+                                       js_log( 'errro: could not parse apiUploadResult' )
+                               }
+                               _this.processApiResult( apiResult );
+                       });
+                       return ;
+               }
+
+               //@@ else update status:
+               if ( data.upload['content_length'] && data.upload['loaded'] ) {
+                       //we have content length we can show percentage done:
+                       var fraction = data.upload['loaded'] / data.upload['content_length'];
+                       //update the status:
+                       _this.updateProgress( fraction );
+                       //special case update the file progress where we have data size:
+                       $j( '#up-status-container' ).html(
+                               gM( 'mwe-upload-stats-fileprogress',
+                                       [
+                                               mw.lang.formatSize( data.upload['loaded'] ),
+                                               mw.lang.formatSize( data.upload['content_length'] )
+                                       ]
+                               )
+                       );
+               } else if( data.upload['loaded'] ) {
+                       _this.updateProgress( 1 );
+                       js_log( 'just have loaded (no cotent length: ' + data.upload['loaded'] );
+                       //for lack of content-length requests:
+                       $j( '#up-status-container' ).html(
+                               gM( 'mwe-upload-stats-fileprogress',
+                                       [
+                                               mw.lang.formatSize( data.upload['loaded'] ),
+                                               gM( 'mwe-upload-unknown-size' )
+                                       ]
+                               )
+                       );
+               }
+               if ( _this.api_url == 'proxy' ) {
+                       // Do the updates a bit less often: every 4.2 seconds
+                       var timeout = 4200;
+               } else {
+                       // We got a result: set timeout to 100ms + your server update
+                       // interval (in our case 2s)
+                       var timeout = 2100;
+               }
+               setTimeout(
+                       function() {
+                               _this.onAjaxUploadStatusTimer();
+                       },
+                       timeout );
+       },
+
+       /**
+        * Returns true if an action=upload API result was successful, false otherwise
+        */
+       isApiSuccess: function( apiRes ) {
+               if ( apiRes.error || ( apiRes.upload && apiRes.upload.result == "Failure" ) ) {
+                       return false;
+               }
+               if ( apiRes.upload && apiRes.upload.error ) {
+                       return false;
+               }
+               if ( apiRes.upload && apiRes.upload.warnings ) {
+                       return false;
+               }
+               return true;
+       },
+
+       /**
+        * Given the result of an action=upload API request, display the error message
+        * to the user.
+        */
+       showApiError: function( apiRes ) {
+               var _this = this;
+               if ( apiRes.error || ( apiRes.upload && apiRes.upload.result == "Failure" ) ) {
+                       // Generate the error button
+                       var buttons = {};
+                       buttons[ gM( 'mwe-return-to-form' ) ] = function() {
+                               _this.form_post_override = false;
+                               $j( this ).dialog( 'close' );
+                       };
+
+                       //@@TODO should be refactored to more specialUpload page type error handling
+
+                       // Check a few places for the error code
+                       var error_code = 0;
+                       var errorReplaceArg = '';
+                       if ( apiRes.error && apiRes.error.code ) {
+                               error_code = apiRes.error.code;
+                       } else if ( apiRes.upload.code ) {
+                               if ( typeof apiRes.upload.code == 'object' ) {
+                                       if ( apiRes.upload.code[0] ) {
+                                               error_code = apiRes.upload.code[0];
+                                       }
+                                       if ( apiRes.upload.code['status'] ) {
+                                               error_code = apiRes.upload.code['status'];
+                                               if ( apiRes.upload.code['filtered'] )
+                                                       errorReplaceArg = apiRes.upload.code['filtered'];
+                                       }
+                               } else {
+                                       apiRes.upload.code;
+                               }
+                       }
+
+                       var error_msg = '';
+                       if ( typeof apiRes.error == 'string' )
+                               error_msg = apiRes.error;
+
+                       // There are many possible error messages here, so we don't load all
+                       // message text in advance, instead we use gMsgLoadRemote() for some.
+                       //
+                       // This code is similar to the error handling code formerly in
+                       // SpecialUpload::processUpload()
+                       var error_msg_key = {
+                               '2' : 'largefileserver',
+                               '3' : 'emptyfile',
+                               '4' : 'minlength1',
+                               '5' : 'illegalfilename'
+                       };
+
+                       //@@todo: handle these error types
+                       var error_onlykey = {
+                               '1': 'BEFORE_PROCESSING',
+                               '6': 'PROTECTED_PAGE',
+                               '7': 'OVERWRITE_EXISTING_FILE',
+                               '8': 'FILETYPE_MISSING',
+                               '9': 'FILETYPE_BADTYPE',
+                               '10': 'VERIFICATION_ERROR',
+                               '11': 'UPLOAD_VERIFICATION_ERROR',
+                               '12': 'UPLOAD_WARNING',
+                               '13': 'INTERNAL_ERROR',
+                               '14': 'MIN_LENGTH_PARTNAME'
+                       }
+
+                       if ( !error_code || error_code == 'unknown-error' ) {
+                               if ( typeof JSON != 'undefined' ) {
+                                       js_log( 'Error: apiRes: ' + JSON.stringify( apiRes ) );
+                               }
+                               if ( apiRes.upload.error == 'internal-error' ) {
+                                       // Do a remote message load
+                                       errorKey = apiRes.upload.details[0];
+                                       gMsgLoadRemote( errorKey, function() {
+                                               _this.updateProgressWin( gM( 'mwe-uploaderror' ), gM( errorKey ), buttons );
+
+                                       });
+                                       return false;
+                               }
+
+                               _this.updateProgressWin(
+                                               gM('mwe-uploaderror'),
+                                               gM('mwe-unknown-error') + '<br>' + error_msg,
+                                               buttons );
+                               return false;
+                       }
+
+                       if ( apiRes.error && apiRes.error.info ) {
+                               _this.updateProgressWin( gM( 'mwe-uploaderror' ), apiRes.error.info, buttons );
+                               return false;
+                       }
+
+                       if ( typeof error_code == 'number'
+                               && typeof error_msg_key[error_code] == 'undefined' )
+                       {
+                               if ( apiRes.upload.code.finalExt ) {
+                                       _this.updateProgressWin(
+                                               gM( 'mwe-uploaderror' ),
+                                               gM( 'mwe-wgfogg_warning_bad_extension', apiRes.upload.code.finalExt ),
+                                               buttons );
+                               } else {
+                                       _this.updateProgressWin(
+                                               gM( 'mwe-uploaderror' ),
+                                               gM( 'mwe-unknown-error' ) + ' : ' + error_code,
+                                               buttons );
+                               }
+                               return false;
+                       }
+
+                       js_log( 'get key: ' + error_msg_key[ error_code ] )
+                       gMsgLoadRemote( error_msg_key[ error_code ], function() {
+                               _this.updateProgressWin(
+                                       gM( 'mwe-uploaderror' ),
+                                       gM( error_msg_key[ error_code ], errorReplaceArg ),
+                                       buttons );
+                       });
+                       js_log( "api.error" );
+                       return false;
+               }
+
+               // Check upload.error
+               if ( apiRes.upload && apiRes.upload.error ) {
+                       js_log( ' apiRes.upload.error: ' +  apiRes.upload.error );
+                       _this.updateProgressWin(
+                               gM( 'mwe-uploaderror' ),
+                               gM( 'mwe-unknown-error' ) + '<br>',
+                               buttons );
+                       return false;
+               }
+
+               // Check for warnings:
+               if ( apiRes.upload && apiRes.upload.warnings ) {
+                       var wmsg = '<ul>';
+                       for ( var wtype in apiRes.upload.warnings ) {
+                               var winfo = apiRes.upload.warnings[wtype]
+                               wmsg += '<li>';
+                               switch ( wtype ) {
+                                       case 'duplicate':
+                                       case 'exists':
+                                               if ( winfo[1] && winfo[1].title && winfo[1].title.mTextform ) {
+                                                       wmsg += gM( 'mwe-file-exists-duplicate' ) + ' ' +
+                                                               '<b>' + winfo[1].title.mTextform + '</b>';
+                                               } else {
+                                                       //misc error (weird that winfo[1] not present
+                                                       wmsg += gM( 'mwe-upload-misc-error' ) + ' ' + wtype;
+                                               }
+                                               break;
+                                       case 'file-thumbnail-no':
+                                               wmsg += gM( 'mwe-file-thumbnail-no', winfo );
+                                               break;
+                                       default:
+                                               wmsg += gM( 'mwe-upload-misc-error' ) + ' ' + wtype;
+                                               break;
+                               }
+                               wmsg += '</li>';
+                       }
+                       wmsg += '</ul>';
+                       if ( apiRes.upload.sessionkey )
+                               _this.warnings_sessionkey = apiRes.upload.sessionkey;
+
+                       // Create the "ignore warning" button
+                       var buttons = {};
+                       buttons[ gM( 'mwe-ignorewarning' ) ] = function() {
+                               //check if we have a stashed key:
+                               if ( _this.warnings_sessionkey ) {
+                                       //set to "loading"
+                                       $j( '#upProgressDialog' ).html( mv_get_loading_img() );
+                                       //setup loading:
+                                       var req = {
+                                               'action': 'upload',
+                                               'sessionkey': _this.warnings_sessionkey,
+                                               'ignorewarnings': 1,
+                                               'filename': $j( '#wpDestFile' ).val(),
+                                               'token' :  _this.editToken
+                                       };
+                                       //run the upload from stash request
+                                       do_api_req(
+                                               {
+                                                       'data': req,
+                                                       'url' : _this.api_url
+                                               },
+                                               function( data ) {
+                                                       _this.processApiResult( data );
+                                               }
+                                       );
+                               } else {
+                                       js_log( 'No session key re-sending upload' )
+                                       //do a stashed upload
+                                       $j( '#wpIgnoreWarning' ).attr( 'checked', true );
+                                       $j( _this.editForm ).submit();
+                               }
+                       };
+                       // Create the "return to form" button
+                       buttons[ gM( 'mwe-return-to-form' ) ] = function() {
+                               $j( this ).dialog( 'close' );
+                               _this.form_post_override = false;
+                       }
+                       // Show warning
+                       _this.updateProgressWin(
+                               gM( 'mwe-uploadwarning' ),
+                               '<h3>' + gM( 'mwe-uploadwarning' ) + '</h3>' + wmsg + '<p>',
+                               buttons );
+                       return false;
+               }
+               // No error!
+               return true;
+       },
+
+       /**
+        * Process the result of an action=upload API request. Display the result
+        * to the user.
+        */
+       processApiResult: function( apiRes ) {
+               var _this = this;
+               js_log( 'processApiResult::' );
+               if ( !_this.isApiSuccess( apiRes ) ) {
+                       // Error detected, show it to the user
+                       _this.showApiError( apiRes );
+                       return false;
+               }
+               if ( apiRes.upload && apiRes.upload.upload_session_key ) {
+                       // Async upload, do AJAX status polling
+                       _this.upload_session_key = apiRes.upload.upload_session_key;
+                       _this.doAjaxUploadStatus();
+                       js_log( "set upload_session_key: " + _this.upload_session_key );
+                       return;
+               }
+
+               if ( apiRes.upload.imageinfo && apiRes.upload.imageinfo.descriptionurl ) {
+                       var url = apiRes.upload.imageinfo.descriptionurl;
+
+                       // Upload complete.
+                       // Call the completion callback if available.
+                       if ( _this.done_upload_cb && typeof _this.done_upload_cb == 'function' ) {
+                               js_log( "call done_upload_cb" );
+                               // This overrides our normal completion handling so we close the
+                               // dialog immediately.
+                               $j( '#upProgressDialog' ).dialog( 'destroy' ).remove();
+                               _this.done_upload_cb( apiRes.upload );
+                               return false;
+                       }
+
+                       var buttons = {};
+                       // "Return" button
+                       buttons[ gM( 'mwe-return-to-form' ) ] = function() {
+                               $j( this ).dialog( 'destroy' ).remove();
+                               _this.form_post_override = false;
+                       }
+                       // "Go to resource" button
+                       buttons[ gM('mwe-go-to-resource') ] = function() {
+                               window.location = url;
+                       };
+                       _this.action_done = true;
+                       _this.updateProgressWin(
+                                       gM( 'mwe-successfulupload' ),
+                                       gM( 'mwe-upload_done', url),
+                                       buttons );
+                       js_log( 'apiRes.upload.imageinfo::' + url );
+                       return true;
+               }
+       },
+
+       /**
+        * Update the progress window to display a given message, with a given
+        * list of buttons below it.
+        * @param title_txt Plain text
+        * @param msg HTML
+        * @param buttons See http://docs.jquery.com/UI/Dialog#option-buttons
+        */
+       updateProgressWin: function( title_txt, msg, buttons ) {
+               var _this = this;
+
+               if ( !title_txt )
+                       title_txt = _this.getProgressTitle();
+
+               if ( !msg )
+                       msg = mv_get_loading_img( 'left:40%;top:40px;' );
+
+               if ( !buttons ) {
+                       // If no buttons are specified, add a close button
+                       buttons = {};
+                       buttons[ gM( 'mwe-ok' ) ] =  function() {
+                               $j( this ).dialog( 'close' );
+                       };
+               }
+
+               $j( '#upProgressDialog' ).dialog( 'option', 'title',  title_txt );
+               $j( '#upProgressDialog' ).html( msg );
+               $j( '#upProgressDialog' ).dialog( 'option', 'buttons', buttons );
+       },
+
+       /**
+        * Get the default title of the progress window
+        */
+       getProgressTitle: function() {
+               return gM( 'mwe-upload-in-progress' );
+       },
+
+       /**
+        * Get the DOMNode of the form element we are rewriting.
+        * Returns false if it can't be found.
+        */
+       getForm: function() {
+               if ( this.form_selector && $j( this.form_selector ).length != 0 ) {
+                       return $j( this.form_selector ).get( 0 );
+               } else {
+                       js_log( "mvBaseUploadInterface.getForm(): no form_selector" );
+                       return false;
+               }
+       },
+
+       /**
+        * Update the progress bar to a given completion fraction (between 0 and 1)
+        */
+       updateProgress: function( fraction ) {
+               //js_log('update progress: ' + fraction);
+               $j( '#up-progressbar' ).progressbar( 'value', parseInt( fraction * 100 ) );
+               $j( '#up-pstatus' ).html( parseInt( fraction * 100 ) + '% - ' );
+       },
+
+       /**
+        * Show a dialog box reporting upload progress and status
+        */
+       displayProgressOverlay: function() {
+               var _this = this;
+               // Remove the old instance if present
+               if( $j( '#upProgressDialog' ).length != 0 ) {
+                       $j( '#upProgressDialog' ).dialog( 'destroy' ).remove();
+               }
+               // Add a new one
+               $j( 'body' ).append( '<div id="upProgressDialog" ></div>' );
+
+               $j( '#upProgressDialog' ).dialog( {
+                       title: _this.getProgressTitle(),
+                       bgiframe: true,
+                       modal: true,
+                       draggable: true,
+                       width: 400,
+                       heigh: 200,
+                       beforeclose: function( event, ui ) {
+                               // If the upload is not complete, ask the user if they want to cancel
+                               if ( event.button == 0 && _this.action_done === false ) {
+                                       _this.onCancel();
+                                       return false;
+                               } else {
+                                       // Complete already, allow close
+                                       return true;
+                               }
+                       },
+                       buttons: _this.getCancelButton()
+               } );
+               $j( '#upProgressDialog' ).html(
+                       '<div id="up-pbar-container" style="width:90%;height:15px;" >' +
+                       '<div id="up-progressbar" style="height:15px;"></div>' +
+                               '<div id="up-status-container">' +
+                                       '<span id="up-pstatus">0% - </span> ' +
+                                       '<span id="up-status-state">' + gM( 'mwe-uploaded-status' ) + '</span> ' +
+                               '</div>'+
+                       '</div>'
+               );
+               // Open the empty progress window
+               $j( '#upProgressDialog' ).dialog( 'open' );
+
+               // Create progress bar
+               $j( '#up-progressbar' ).progressbar({
+                       value: 0
+               });
+       },
+
+       /**
+        * Get a standard cancel button in the jQuery.ui dialog format
+        */
+       getCancelButton: function() {
+               var _this = this;
+               var cancelBtn = new Array();
+               cancelBtn[ gM( 'mwe-cancel' ) ] = function() {
+                       return _this.onCancel( this )
+               };
+               return cancelBtn;
+       },
+
+       /**
+        * UI cancel button handler.
+        * Show a dialog box asking the user whether they want to cancel an upload.
+        * FIXME: doesn't work at all.
+        */
+       onCancel: function( dlElm ) {
+               //confirm:
+               if ( confirm( gM( 'mwe-cancel-confim' ) ) ) {
+                       //@@todo (cancel the encode / upload)
+                       $j( this ).dialog( 'close' );
+               }
+       }
+};
+
+// jQuery plugins
+
+( function( $ ) {
+       /**
+        * Check the upload destination filename for conflicts and show a conflict
+        * error message if there is one
+        */
+       $.fn.doDestCheck = function( opt ) {
+               var _this = this;
+               js_log( 'doDestCheck::' + _this.selector );
+
+               // Set up option defaults
+               if ( !opt.warn_target )
+                       opt.warn_target = '#wpDestFile-warning';
+
+               // Add the wpDestFile-warning row
+               if ( $j( '#wpDestFile-warning' ).length == 0 ) {
+                       $j( '#mw-htmlform-options tr:last' )
+                               .after( '<tr><td></td><td id="wpDestFile-warning"></td></tr>' );
+               }
+
+               // Remove any existing warning
+               $j( opt.warn_target ).empty();
+
+               // Show the AJAX spinner
+               $j( _this.selector )
+                       .append( '<img id="mw-spinner-wpDestFile" ' +
+                               'src ="' + stylepath + '/common/images/spinner.gif" />' );
+
+               // Do the destination check
+               do_api_req(
+                       {
+                               'data': {
+                                       //@@todo we may need a more clever way to get a the filename
+                                       'titles': 'File:' + $j( _this.selector ).val(),
+                                       'prop':  'imageinfo',
+                                       'iiprop': 'url|mime|size',
+                                       'iiurlwidth': 150
+                               }
+                       },
+                       function( data ) {
+                               // Remove spinner
+                               $j( '#mw-spinner-wpDestFile' ).remove();
+
+                               if ( !data || !data.query || !data.query.pages ) {
+                                       // Ignore a null result
+                                       return;
+                               }
+
+                               if ( data.query.pages[-1] ) {
+                                       // No conflict found
+                                       return;
+                               }
+                               for ( var page_id in data.query.pages ) {
+                                       if ( !data.query.pages[ page_id ].imageinfo ) {
+                                               continue;
+                                       }
+
+                                       // Conflict found, show warning
+                                       if ( data.query.normalized ) {
+                                               var ntitle = data.query.normalized[0].to;
+                                       } else {
+                                               var ntitle = data.query.pages[ page_id ].title
+                                       }
+                                       var img = data.query.pages[ page_id ].imageinfo[0];
+                                       $j( '#wpDestFile-warning' ).html(
+                                               gM( 'mwe-fileexists', ntitle ) +
+                                               '<div class="thumb tright">' +
+                                               '<div ' +
+                                                       'style="width: ' + ( parseInt( img.thumbwidth ) + 2 ) + 'px;" ' +
+                                                       'class="thumbinner">' +
+                                               '<a ' +
+                                                       'title="' + ntitle + '" ' +
+                                                       'class="image" ' +
+                                                       'href="' + img.descriptionurl + '">' +
+                                               '<img ' +
+                                                       'width="' + img.thumbwidth + '" ' +
+                                                       'height="' + img.thumbheight + '" ' +
+                                                       'border="0" ' +
+                                                       'class="thumbimage" ' +
+                                                       'src="' + img.thumburl + '" ' +
+                                                       'alt="' + ntitle + '"/>' +
+                                               '</a>' +
+                                               '<div class="thumbcaption">' +
+                                               '<div class="magnify">' +
+                                               '<a title="' + gM('thumbnail-more') + '" class="internal" ' +
+                                                       'href="' + img.descriptionurl +'">' +
+                                               '<img width="15" height="11" alt="" ' +
+                                                       'src="' + stylepath + "/common/images/magnify-clip.png\" />" +
+                                               '</a>' +
+                                               '</div>' +
+                                               gM( 'mwe-fileexists-thumb' ) +
+                                               '</div>' +
+                                               '</div>' +
+                                               '</div>'
+                                       );
+                               }
+                       }
+               );
+       }
+})( jQuery );
diff --git a/js2/mwEmbed/libAddMedia/mvFirefogg.js b/js2/mwEmbed/libAddMedia/mvFirefogg.js
new file mode 100644 (file)
index 0000000..1add58b
--- /dev/null
@@ -0,0 +1,1080 @@
+/* Firefogg support.
+ * autodetects: new upload api or old http POST.
+ */
+
+loadGM({
+       "fogg-select_file" : "Select file",
+       "fogg-select_new_file" : "Select new file",
+       "fogg-select_url" : "Select URL",
+       "fogg-save_local_file" : "Save Ogg",
+       "fogg-check_for_firefogg" : "Checking for Firefogg...",
+       "fogg-installed" : "Firefogg is installed",
+       "fogg-for_improved_uploads" : "For improved uploads:",
+       "fogg-please_install" : "<a href=\"$1\">Install Firefogg<\/a>. More <a href=\"http:\/\/commons.wikimedia.org\/wiki\/Commons:Firefogg\">about Firefogg<\/a>.",
+       "fogg-use_latest_firefox" : "Please first install <a href=\"http:\/\/www.mozilla.com\/en-US\/firefox\/upgrade.html?from=firefogg\">Firefox 3.5<\/a> (or later). <i>Then revisit this page to install the <b>Firefogg<\/b> extension.<\/i>",
+       "fogg-passthrough_mode" : "Your selected file is already Ogg or not a video file",
+       "fogg-transcoding" : "Encoding video to Ogg...",
+       "fogg-encoding-done" : "Encoding complete",
+       "fogg-badtoken" : "Token is not valid",
+       "fogg-preview" : "Preview video",
+       "fogg-hidepreview" : "Hide preview"
+});
+
+var firefogg_install_links = {
+       'macosx': 'http://firefogg.org/macosx/Firefogg.xpi',
+       'win32': 'http://firefogg.org/win32/Firefogg.xpi',
+       'linux': 'http://firefogg.org/linux/Firefogg.xpi'
+};
+
+var default_firefogg_options = {
+       // Callback for upload completion
+       'done_upload_cb': false,        
+
+       // The API URL to upload to
+       'api_url': null,
+
+       // True when a file is uploaded without re-encoding
+       'passthrough': false,
+
+       // True if we will be showing the encoder interface
+       'encoder_interface': false,
+
+       // True if we want to limit the library functionality to "only firefogg" 
+       // (no upload or progress bars)
+       'only_firefogg': false,
+
+       // Callback which is called when the source name changes
+       'new_source_cb': false,
+
+       // CSS selector identifying the target control container or form (can't be left null)
+       'selector': '',
+
+       // May be "upload" to if we are rewriting an upload form, or "local" if we are encoding a local file    
+       'form_type': 'local',
+
+       // CSS selector for the select file button
+       'target_btn_select_file': false,
+
+       // CSS selector for the select new file button
+       'target_btn_select_new_file': false,
+
+       // CSS selector for the save local file button
+       'target_btn_save_local_file': false,
+
+       // CSS selector for the input file name button
+       'target_input_file_name': false,
+
+       // CSS selector for the "checking for firefogg..." message div
+       'target_check_for_firefogg': false,
+
+       // CSS selector for the "firefogg is installed" message div
+       'target_installed': false,
+
+       // CSS selector for the "please install firefogg" message div
+       'target_please_install': false,
+
+       // CSS selector for the "please use Firefox 3.5" message div
+       'target_use_latest_firefox': false,
+
+       // CSS selector for the message div warning that passthrough mode is enabled
+       'target_passthrough_mode': false,
+
+       // True if firefogg should take over the form submit action
+       'firefogg_form_action': true,
+
+       // True if we should show a preview of the encoding progress
+       'show_preview': true,
+       
+       //If we should enable chunk uploads ( mediaWiki api supports chunk uploads) 
+       'enable_chunks' : false
+};
+
+
+var mvFirefogg = function( options ) {
+       return this.init( options );
+};
+
+mvFirefogg.prototype = { // extends mvBaseUploadInterface
+       min_firefogg_version: '0.9.9.5',
+       default_encoder_settings: { // @@todo allow the server to set these
+               'maxSize'        : '400',
+        'videoBitrate'   : '544',
+        'audioBitrate'   : '96',
+        'noUpscaling'    : true
+       },
+       have_firefogg: null, // lazy initialised, use getFirefogg()
+       current_encoder_settings: null, // lazy initialised, use getEncoderSettings()
+       sourceFileInfo: null, // lazy initialised, use getSourceFileInfo()
+       ogg_extensions: [ 'ogg', 'ogv', 'oga' ],
+       video_extensions: [ 'avi', 'mov', 'mp4', 'mp2', 'mpeg', 'mpeg2', 'mpeg4', 'dv', 'wmv' ],
+
+       passthrough: false,
+       sourceMode: 'file',
+
+       /**
+        * Object initialisation
+        */
+       init: function( options ) {
+               if ( !options )
+                       options = {};
+
+               // If we have no api_url, set upload mode to "post"
+               if ( !options.api_url )
+                       options.upload_mode = 'post';
+
+               // Set options
+               for ( var i in default_firefogg_options ) {
+                       if ( options[i] ) {
+                               this[i] = options[i];
+                       } else {
+                               this[i] = default_firefogg_options[i];
+                       }
+               }
+
+               // Inherit from mvBaseUploadInterface (unless we're in only_firefogg mode)
+               if ( !this.only_firefogg ) {
+                       var myBUI = new mvBaseUploadInterface( options );
+
+                       // Prefix conflicting members with pe_
+                       for ( var i in myBUI ) {
+                               if ( this[i] ) {
+                                       this['pe_'+ i] = myBUI[i];
+                               } else {
+                                       this[i] =  myBUI[i];
+                               }
+                       }
+               }
+
+               if ( !this.selector ) {
+                       js_log('firefogg: missing selector ');
+               }
+       },
+
+       /**
+        * Rewrite the upload form, or create our own upload controls for local transcoding.
+        * Called from $j.firefogg(), in mv_embed.js.
+        */
+       doRewrite: function( callback ) {
+               var _this = this;
+               js_log( 'sel len: ' + this.selector + '::' + $j( this.selector ).length + 
+                               ' tag:' + $j( this.selector ).get( 0 ).tagName );
+               if ( $j( this.selector ).length >= 0 ) {
+                       if ( $j( this.selector ).get( 0 ).tagName.toLowerCase() == 'input' ) {
+                               _this.form_type = 'upload';
+                       }
+               }
+               if ( this.form_type == 'upload' ) {
+                       // Initialise existing upload form
+                       this.setupForm();
+               } else {
+                       // Create our own form controls
+                       this.createControls();
+                       this.bindControls();
+               }
+
+               if ( callback )
+                       callback();
+       },
+
+       /**
+        * Create controls for local transcoding and add them to the page
+        */
+       createControls: function() {
+               var _this = this;
+               var out = '';
+               $j.each( default_firefogg_options, function( target, na ) {
+                       if ( /^target/.test( target ) ) {
+                               // Create the control if it doesn't already exist
+                               if( _this[target] === false ) {
+                                       out += _this.getControlHtml(target) + ' ';
+                                       // Update the target selector
+                                       _this[target] = _this.selector + ' .' + target;
+                               }
+                       }
+               });
+               $j( this.selector ).append( out ).hide();
+       },
+
+       /**
+        * Get the HTML for the control with a particular name
+        */
+       getControlHtml: function( target ) {
+               if ( /^target_btn_/.test( target ) ) {
+                       // Button
+                       var msg = gM( target.replace( /^target_btn_/, 'fogg-' ) );
+                       return '<input style="" ' + 
+                               'class="' + target + '" ' + 
+                               'type="button" ' + 
+                               'value="' + msg + '"/> ';
+               } else if ( /^target_input_/.test( target ) ) {
+                       // Text input
+                       var msg = gM( target.replace( /^target_input_/, 'fogg-' ) );
+                       return '<input style="" ' + 
+                               'class="' + target + '" ' + 
+                               'type="text" ' + 
+                               'value="' + msg + '"/> ';
+               } else if ( /^target_/.test( target ) ) {
+                       // Message
+                       var msg = gM( target.replace( '/^target_/', 'fogg-' ) );
+                       return '<div style="" class="' + target + '" >' + msg + '</div> ';
+               } else {
+                       js_error( 'Invalid target: ' + target );
+                       return '';
+               }
+       },
+
+       /**
+        * Set up events for the controls which were created with createControls()
+        */
+       bindControls: function() {
+               var _this = this;
+
+               // Hide all controls
+               var hide_target_list = '';
+               var comma = '';
+               $j.each( default_firefogg_options, function( target, na ) {
+                       if ( /^target/.test( target ) ) {
+                               hide_target_list += comma + _this[target];
+                               comma = ',';
+                       }
+               });
+               $j( hide_target_list ).hide();
+
+               // Now show the form
+               $j( _this.selector ).show();
+               if ( _this.getFirefogg() ) {
+                       // Firefogg enabled
+                       // If we're in upload mode, show the input filename
+                       if ( _this.form_type == 'upload' )
+                               $j( _this.target_input_file_name ).show();
+
+                       // Show the select file button
+                       $j( this.target_btn_select_file )
+                               .unbind()
+                               .attr( 'disabled', false )
+                               .css( { 'display': 'inline' } )
+                               .click( function() {
+                                       _this.selectSourceFile();
+                               } );
+
+                       // Set up the click handler for the filename box
+                       $j( this.target_input_file_name )
+                               .unbind()
+                               .attr( 'readonly', 'readonly' )
+                               .click( function() {
+                                       _this.selectSourceFile();
+                               });
+               } else {
+                       // Firefogg disabled
+                       // FIXME: move this elsewhere. None of this is related to binding.
+
+                       // Show the "use latest Firefox" message if necessary
+                       if ( !( $j.browser.mozilla && $j.browser.version >= '1.9.1' ) ) {
+                               js_log( 'show use latest::' + _this.target_use_latest_firefox );
+                               if ( _this.target_use_latest_firefox ) {
+                                       if ( _this.form_type == 'upload' )
+                                               $j( _this.target_use_latest_firefox )
+                                                       .prepend( gM( 'fogg-for_improved_uploads' ) );
+
+                                       $j( _this.target_use_latest_firefox ).show();
+                               }
+                               return;
+                       }
+
+                       // Otherwise show the "install Firefogg" message                        
+                       var upMsg = ( _this.form_type == 'upload' ) ? gM( 'fogg-for_improved_uploads' ) : '';
+                       var firefoggUrl = _this.getFirefoggInstallUrl();
+                       if( firefoggUrl ){
+                               $j( _this.target_please_install )
+                                       .html( upMsg + gM( 'fogg-please_install', firefoggUrl ) )
+                                       .css( 'padding', '10px' )
+                                       .show();
+                       }
+               }
+
+               // Set up the click handler for the "save local file" button
+               if( _this.target_btn_save_local_file ){
+                       $j( _this.target_btn_save_local_file )
+                       .unbind()
+                       .click( function() {
+                               _this.doLocalEncodeAndSave();
+                       } );
+               }
+       },
+
+       /*
+        * Get the URL for installing firefogg on the client OS
+        */
+       getFirefoggInstallUrl: function() {
+               var os_link = false;
+               if ( navigator.oscpu ) {
+                       if ( navigator.oscpu.search( 'Linux' ) >= 0 )
+                               os_link = firefogg_install_links['linux'];
+                       else if ( navigator.oscpu.search( 'Mac' ) >= 0 )
+                               os_link = firefogg_install_links['macosx'];
+                       else if (navigator.oscpu.search( 'Win' ) >= 0 )
+                               os_link = firefogg_install_links['win32'];
+               }
+               return os_link;
+       },
+
+       /**
+        * Get the Firefogg instance (or false if firefogg is unavailable)
+        */
+       getFirefogg: function() {
+               if ( this.have_firefogg == null ) {
+                       if ( typeof( Firefogg ) != 'undefined' 
+                               && Firefogg().version >= this.min_firefogg_version ) 
+                       {
+                               this.have_firefogg = true;
+                               this.fogg = new Firefogg();
+                       } else {
+                               this.have_firefogg = false;
+                               this.fogg = false;
+                       }
+               }
+               return this.fogg;
+       },
+
+       /**
+        * Set up the upload form
+        */
+       setupForm: function() {
+               js_log( 'firefogg::setupForm::' );
+
+               // Set up the parent if we are in upload mode
+               if ( this.form_type == 'upload' ) {
+                       this.pe_setupForm();
+               }
+
+               // If Firefogg is not available, just show a "please install" message
+               if ( !this.getFirefogg() ) {
+                       if ( !this.target_please_install ) {
+                               $j( this.selector ).after( this.getControlHtml( 'target_please_install' ) );
+                               this.target_please_install = this.selector + ' ~ .target_please_install';
+                       }
+                       if ( !this.target_use_latest_firefox ) {
+                               $j( this.selector ).after( this.getControlHtml( 'target_use_latest_firefox' ) );
+                               this.target_use_latest_firefox = this.selector + ' ~ .target_use_latest_firefox';
+                       }
+                       // Show download link
+                       this.bindControls();
+                       return;
+               }
+
+               // Change the file browser to type text. We can't simply change the attribute so 
+               // we have to delete and recreate.
+               var inputTag = '<input ';
+               $j.each( $j( this.selector ).get( 0 ).attributes, function( i, attr ) {
+                       var val = attr.value;
+                       if ( attr.name == 'type' )
+                               val = 'text';
+                       inputTag += attr.name + '="' + val + '" ';
+               } );
+               if ( !$j( this.selector ).attr( 'style' ) )
+                       inputTag += 'style="display:inline" ';
+
+               var id = $j( this.selector ).attr( 'name' ) + '_firefogg-control';
+               inputTag += '/><span id="' + id + '"></span>';
+
+               js_log( 'set input: ' + inputTag );
+               $j( this.selector ).replaceWith( inputTag );
+
+               this.target_input_file_name = 'input[name=' + $j( this.selector ).attr( 'name' ) + ']';
+
+               // Point the selector at the span we just created
+               this.selector = '#' + id;
+
+               // Create controls for local transcoding
+               this.createControls();
+               this.bindControls();
+       },
+
+       /**
+        * Display an upload progress overlay. Overrides the function in mvBaseUploadInterface.
+        */
+       displayProgressOverlay: function() {
+               this.pe_displayProgressOverlay();               
+               // If we are uploading video (not in passthrough mode), show preview button
+               if( this.getFirefogg() 
+                       && !this.isCopyUpload() 
+                       && !this.getEncoderSettings()['passthrough']  ) 
+               {
+                       this.createPreviewControls();
+               }
+       },
+
+       /**
+        * Create controls for showing a transcode/crop/resize preview
+        */
+       createPreviewControls: function() {
+               var _this = this;
+               
+               // Set the initial button html: 
+               var buttonHtml = '';
+               if( _this.show_preview == true ){
+                       buttonHtml = $j.btnHtml( gM( 'fogg-hidepreview' ), 'fogg_preview', 'triangle-1-s' );                    
+               } else {
+                       buttonHtml = $j.btnHtml( gM( 'fogg-preview' ), 'fogg_preview', 'triangle-1-e' );
+               }
+               
+               // Add the preview button and canvas
+               $j( '#upProgressDialog' ).append(
+                       '<div style="clear:both;height:3em"/>' +
+                       buttonHtml +
+                       '<div style="padding:10px;">' +
+                               '<canvas style="margin:auto;" id="fogg_preview_canvas" />' +
+                       '</div>'
+               );
+
+               // Set the initial state
+               if ( _this.show_preview == true ) {
+                       $j( '#fogg_preview_canvas' ).show();
+               }
+
+               // Bind the preview button
+               $j( '#upProgressDialog .fogg_preview' ).btnBind().click( function() {
+                       return _this.onPreviewClick( this );
+               });
+       },
+
+       /**
+        * onclick handler for the hide/show preview button
+        */
+       onPreviewClick: function( sourceNode ) {
+               var button = $j( sourceNode );
+               var icon = button.children( '.ui-icon' );
+               js_log( "click .fogg_preview" + icon.attr( 'class' ) );
+
+               if ( icon.hasClass( 'ui-icon-triangle-1-e' ) ) {
+                       // Show preview
+                       // Toggle button class and set button text to "hide".
+                       this.show_preview = true;
+                       icon.removeClass( 'ui-icon-triangle-1-e' ).addClass( 'ui-icon-triangle-1-s' );
+                       button.children( '.btnText' ).text( gM( 'fogg-hidepreview' ) );
+                       $j( '#fogg_preview_canvas' ).show( 'fast' );
+               } else {
+                       // Hide preview
+                       // Toggle button class and set button text to "show".
+                       this.show_preview = false;
+                       icon.removeClass( 'ui-icon-triangle-1-s' ).addClass( 'ui-icon-triangle-1-e' );
+                       button.children( '.btnText' ).text( gM( 'fogg-preview' ) );
+                       $j( '#fogg_preview_canvas' ).hide( 'slow' );
+               }
+               // Don't follow the # link
+               return false;
+       },
+
+       /**
+        * Render the preview frame (asynchronously)
+        */
+       renderPreview: function() {
+               var _this = this;
+               // Set up the hidden video to pull frames from
+               if( $j( '#fogg_preview_vid' ).length == 0 )
+                       $j( 'body' ).append( '<video id="fogg_preview_vid" style="display:none"></video>' );
+               var v = $j( '#fogg_preview_vid' ).get( 0 );
+
+               function seekToEnd() {
+                       var v = $j( '#fogg_preview_vid' ).get( 0 );
+                       // TODO: document arbitrary 0.4s constant
+                       v.currentTime = v.duration - 0.4;
+               }
+               function renderFrame() {
+                       var v = $j( '#fogg_preview_vid' ).get( 0 );
+                       var canvas = $j( '#fogg_preview_canvas' ).get( 0 );
+                       if ( canvas ) {
+                               canvas.width = 160;
+                               canvas.height = canvas.width * v.videoHeight / v.videoWidth;
+                               var ctx = canvas.getContext( "2d" );
+                               ctx.drawImage( v, 0, 0, canvas.width, canvas.height );
+                       }
+               }
+               function preview() {
+                       // Initialize the video if it is not set up already
+                       var v = $j( '#fogg_preview_vid' ).get( 0 );
+                       if ( v.src != _this.fogg.previewUrl ) {
+                               js_log( 'init preview with url:' + _this.fogg.previewUrl );
+                               v.src = _this.fogg.previewUrl;
+
+                               // Once it's loaded, seek to the end
+                               v.removeEventListener( "loadedmetadata", seekToEnd, true );
+                               v.addEventListener( "loadedmetadata", seekToEnd, true );
+
+                               // When the seek is done, render a frame
+                               v.removeEventListener( "seeked", renderFrame, true );
+                               v.addEventListener( "seeked", renderFrame, true );
+
+                               // Refresh the video duration and metadata
+                               var previewTimer = setInterval( function() {
+                                       if ( _this.fogg.status() != "encoding" ) {
+                                               clearInterval( previewTimer );
+                                               _this.show_preview == false;
+                                       }
+                                       if ( _this.show_preview == true ) {
+                                               v.load();
+                                       }
+                               }, 1000 );
+                       }
+               }
+               preview();
+       },
+
+       /**
+        * Get the DOMNode of the form element we are rewriting.
+        * Returns false if it can't be found.
+        * Overrides mvBaseUploadInterface.getForm().
+        */
+       getForm: function() {
+               if ( this.form_selector ) {
+                       return this.pe_getForm();
+               } else {
+                       // No configured form selector
+                       // Use the first form descendant of the current container
+                       return $j( this.selector ).parents( 'form:first' ).get( 0 );
+               }
+       },
+
+       /**
+        * Show a dialog box allowing the user to select the source file of the 
+        * encode/upload operation. The filename is stored by Firefogg until the 
+        * next encode/upload call.
+        *
+        * After a successful select, the UI is updated accordingly.
+        */
+       selectSourceFile: function() {
+               var _this = this;
+               if( !_this.fogg.selectVideo() ) {
+                       // User clicked "cancel"
+                       return;
+               }
+               _this.clearSourceInfoCache();
+               _this.updateSourceFileUI();
+       },
+
+       /**
+        * Update the UI due to the source file changing
+        */
+       updateSourceFileUI: function() {
+               js_log( 'videoSelectReady' );
+               var _this = this;
+               if ( !_this.fogg.sourceInfo || !_this.fogg.sourceFilename ) {
+                       // Something wrong with the source file?
+                       js_log( 'selectSourceFile: sourceInfo/sourceFilename missing' );
+                       return;
+               }
+
+               // Hide the "select file" button and show "select new"
+               $j( _this.target_btn_select_file ).hide();
+               $j( _this.target_btn_select_new_file)
+                       .show()
+                       .unbind()
+                       .click( function() {
+                               _this.fogg = new Firefogg();
+                               _this.selectSourceFile();
+                       } );
+
+               var settings = this.getEncoderSettings();
+
+               // If we're in passthrough mode, update the interface (if not a form)
+               if ( settings['passthrough'] == true && _this.form_type == 'local' ) {
+                       $j( _this.target_passthrough_mode ).show();
+               } else {
+                       $j( _this.target_passthrough_mode ).hide();
+                       // Show the "save file" button if this is a local form
+                       if ( _this.form_type == 'local' ) {
+                               $j( _this.target_btn_save_local_file ).show();
+                       } // else the upload will be done on form submit
+               }
+
+               // Update the input file name box and show it
+               js_log( " should update: " + _this.target_input_file_name + 
+                               ' to: ' + _this.fogg.sourceFilename );
+               $j( _this.target_input_file_name )
+                       .val( _this.fogg.sourceFilename )
+                       .show();
+
+
+               // Notify callback new_source_cb
+               if ( _this.new_source_cb ) {
+                       if ( settings['passthrough'] ) {
+                               var fName = _this.fogg.sourceFilename;
+                       } else {
+                               var oggExt = _this.isSourceAudio() ? 'oga' : 'ogg';
+                               oggExt = _this.isSourceVideo() ? 'ogv' : oggExt;
+                               oggExt = _this.isUnknown() ? 'ogg' : oggExt;
+                               oggName = _this.fogg.sourceFilename.substr( 0,
+                                       _this.fogg.sourceFilename.lastIndexOf( '.' ) );
+                               var fName = oggName + '.' + oggExt;
+                       }
+                       _this.new_source_cb( _this.fogg.sourceFilename, fName );
+               }
+       },
+
+       /**
+        * Get the source file info for the current file selected into this.fogg
+        */
+       getSourceFileInfo: function() {
+               if ( this.sourceFileInfo == null ) {
+                       if ( !this.fogg.sourceInfo ) {
+                               js_error( 'No firefogg source info is available' );
+                               return false;
+                       }
+                       try {
+                               this.sourceFileInfo = JSON.parse( this.fogg.sourceInfo );
+                       } catch ( e ) {
+                               js_error( 'error could not parse fogg sourceInfo' );
+                               return false;
+                       }
+               }
+               return this.sourceFileInfo;
+       },
+
+       /**
+        * Clear the cache of the source file info, presumably due to a new file
+        * being selected into this.fogg
+        */
+       clearSourceInfoCache: function() {
+               this.sourceFileInfo = null;
+               this.current_encoder_settings = null;
+       },
+
+       /**
+        * Save the result of the transcode as a local file
+        */
+       doLocalEncodeAndSave: function() {
+               var _this = this;
+               if ( !this.fogg ) {
+                       js_error( 'doLocalEncodeAndSave: no Firefogg object!' );
+                       return false;
+               }
+
+               // Set up the target location
+               // Firefogg shows the "save as" dialog box, and sets the path chosen as 
+               // the destination for a later encode() call.
+               if ( !this.fogg.saveVideoAs() ) {
+                       // User clicked "cancel"
+                       return false;
+               }
+
+               // We have a source file, now do the encode
+               this.doEncode(
+                       function /* onProgress */ ( progress ) {
+                               _this.updateProgress( progress );
+                       },
+                       function /* onDone */ () {
+                               js_log( "done with encoding (no upload) " );
+                               // Set status to 100% for one second
+                               // FIXME: this is either a hack or a waste of time, not sure which
+                               _this.updateProgress( 1 );
+                               setTimeout( function() {
+                                       _this.onLocalEncodeDone();
+                               });
+                       }
+               );
+       },
+
+       /**
+        * This is called when a local encode operation has completed. It updates the UI.
+        */
+       onLocalEncodeDone: function() {
+               var _this = this;
+               _this.updateProgressWin( gM( 'fogg-encoding-done' ),
+                       gM( 'fogg-encoding-done' ) + '<br>' +
+                       //show the video at full resolution upto 720px wide
+                       '<video controls="true" style="margin:auto" id="fogg_final_vid" src="' +
+                               _this.fogg.previewUrl + '"></video>'
+               );
+               //load the video and set a callback:
+               var v = $j( '#fogg_final_vid' ).get( 0 );
+               function resizeVid() {
+                       var v = $j( '#fogg_final_vid' ).get(0);
+                       if ( v.videoWidth > 720 ) {
+                               var vW = 720;
+                               var vH = 720 * v.videoHeight / v.videoWidth;
+                       } else {
+                               var vW = v.videoWidth;
+                               var vH = v.videoHeight;
+                       }
+                       //reize the video:
+                       $j( v ).css({
+                               'width': vW,
+                               'height': vH
+                       });
+                       //if large video resize the dialog box:
+                       if( vW + 5 > 400 ) {
+                               //also resize the dialog box
+                               $j( '#upProgressDialog' ).dialog( 'option', 'width', vW + 20 );
+                               $j( '#upProgressDialog' ).dialog( 'option', 'height', vH + 120 );
+
+                               //also position the dialog container
+                               $j( '#upProgressDialog') .dialog( 'option', 'position', 'center' );
+                       }
+               }
+               v.removeEventListener( "loadedmetadata", resizeVid, true );
+               v.addEventListener( "loadedmetadata", resizeVid, true );
+               v.load();
+       },
+
+       /**
+        * Get the appropriate encoder settings for the current Firefogg object, 
+        * into which a video has already been selected.
+        */
+       getEncoderSettings: function() {
+               if ( this.current_encoder_settings == null ) {
+                       // Clone the default settings
+                       var defaults = function () { };
+                       defaults.prototype = this.default_encoder_settings;
+                       var settings = new defaults();
+
+                       // Grab the extension
+                       var sf = this.fogg.sourceFilename;
+                       if ( !sf ) {
+                               js_error( 'getEncoderSettings(): No Firefogg source filename is available!' );
+                               return false;
+                       }
+                       var ext = '';
+                       if ( sf.lastIndexOf('.') != -1 )
+                               ext = sf.substring( sf.lastIndexOf( '.' ) + 1 ).toLowerCase();
+
+                       // Determine passthrough mode
+                       if ( this.isOggFormat() ) {
+                               // Already Ogg, no need to encode
+                               settings['passthrough'] = true;
+                       } else if ( this.isSourceAudio() || this.isSourceVideo() ) {
+                               // OK to encode
+                               settings['passthrough'] = false;
+                       } else {
+                               // Not audio or video, can't encode
+                               settings['passthrough'] = true;
+                       }
+
+                       js_log( 'base setupAutoEncoder::' + this.getSourceFileInfo().contentType  +
+                               ' passthrough:' + settings['passthrough'] );
+                       this.current_encoder_settings = settings;
+               }
+               return this.current_encoder_settings;
+       },
+
+       isUnknown: function() {
+               return ( this.getSourceFileInfo().contentType.indexOf("unknown") != -1 );
+       },
+
+       isSourceAudio: function() {
+               return ( this.getSourceFileInfo().contentType.indexOf("audio/") != -1 );
+       },
+
+       isSourceVideo: function() {
+               return ( this.getSourceFileInfo().contentType.indexOf("video/") != -1 );
+       },
+
+       isOggFormat: function() {
+               var contentType = this.getSourceFileInfo().contentType;
+               return ( contentType.indexOf("video/ogg") != -1 
+                       || contentType.indexOf("application/ogg") != -1 );
+       },
+
+       /**
+        * Get the default title of the progress window
+        */
+       getProgressTitle: function() {
+               js_log( "fogg:getProgressTitle f:" +  ( this.getFirefogg() ? 'on' : 'off' ) + 
+                       ' mode:' + this.form_type );
+               // Return the parent's title if we don't have Firefogg turned on
+               if ( !this.getFirefogg() || !this.firefogg_form_action ) {
+                       return this.pe_getProgressTitle();
+               } else if ( this.form_type == 'local' ) {
+                       return gM( 'fogg-transcoding' );
+               } else {
+                       return gM( 'mwe-upload-transcode-in-progress' );
+               }
+       },
+
+       /**
+        * Do an upload, with the mode given by this.upload_mode
+        */
+       doUpload: function() {
+               var _this = this;
+               js_log( "firefogg: doUpload:: " + 
+                       ( this.getFirefogg() ? 'on' : 'off' ) + 
+                       ' up mode:' + _this.upload_mode );
+                                       
+               // If Firefogg is disabled or doing an copyByUrl upload, just invoke the parent method
+               if( !this.getFirefogg() || this.isCopyUpload() ) {
+                       _this.pe_doUpload();
+                       return;
+               }
+               // We can do a chunk upload
+               if(  _this.upload_mode == 'post'  && _this.enable_chunks ){
+                       _this.doChunkUpload();
+               } else if ( _this.upload_mode == 'post' ) {             
+                       // Encode and then do a post upload
+                       _this.doEncode(
+                               function /* onProgress */ ( progress ) {
+                                       _this.updateProgress( progress );
+                               },
+                               function /* onDone */ () {
+                                       js_log( 'done with encoding do POST upload:' + _this.form.action );
+                                       // ignore warnings & set source type
+                                       //_this.formData[ 'wpIgnoreWarning' ]='true';
+                                       _this.formData['wpSourceType'] = 'upload';
+                                       _this.formData['action'] = 'submit';
+                                       
+                                       // wpUploadFile is set by firefogg
+                                       delete _this.formData['file'];
+
+                                       _this.fogg.post( _this.editForm.action, 'wpUploadFile', 
+                                               JSON.stringify( _this.formData ) );
+                                       _this.doUploadStatus();
+                               }
+                       );
+               } else {
+                       js_error( 'Error: unrecongized upload mode: ' + _this.upload_mode );
+               }
+       },
+
+       /**
+        * Do both uploading and encoding at the same time. Uploads 1MB chunks as 
+        * they become ready.
+        */
+       doChunkUpload : function() {
+               js_log( 'firefogg::doChunkUpload' );
+               var _this = this;
+               _this.action_done = false;
+
+               if ( !_this.getEncoderSettings()['passthrough'] ) {
+                       // We are transcoding to Ogg. Fix the destination extension, it 
+                       // must be ogg/ogv/oga.
+                       var fileName = _this.formData['filename'];
+                       var ext = '';
+                       var dotPos = fileName.lastIndexOf( '.' );
+                       if ( dotPos != -1 ) {
+                               ext = fileName.substring( dotPos ).toLowerCase();
+                       }
+                       if ( $j.inArray( ext.substr( 1 ), _this.ogg_extensions ) == -1  ) {                     
+                               var extreg = new RegExp( ext + '$', 'i' );
+                               _this.formData['filename'] = fileName.replace( extreg, '.ogg' );
+                       }
+               }
+
+               // Get the edit token from formData if it's not set already
+               if ( !_this.editToken && _this.formData['token'] ) {
+                       _this.editToken = _this.formData['token'];
+               }
+
+               if( _this.editToken ) {
+                       js_log( 'we already have an edit token: ' + _this.editToken );
+                       _this.doChunkUploadWithFormData();
+                       return;
+               }
+
+               // No edit token. Fetch it asynchronously and then do the upload.
+               get_mw_token(
+                       'File:'+ _this.formData['filename'],
+                       _this.api_url,
+                       function( editToken ) {
+                               if( !editToken || editToken == '+\\' ) {
+                                       _this.updateProgressWin( gM( 'fogg-badtoken' ), gM( 'fogg-badtoken' ) );
+                                       return false;
+                               }
+                               _this.editToken = editToken;
+                               _this.doChunkUploadWithFormData();
+                       }
+               );
+       },
+
+       /**
+        * Internal function called from doChunkUpload() when the edit token is available
+        */
+       doChunkUploadWithFormData: function() {
+               var _this = this;
+               js_log( "firefogg::doChunkUploadWithFormData"  + _this.editToken );
+               // Build the API URL
+               var aReq = {
+                       'action': 'upload',
+                       'format': 'json',
+                       'filename': _this.formData['filename'],
+                       'comment': _this.formData['comment'],
+                       'enablechunks': 'true'
+               };
+
+               if ( _this.editToken )
+                       aReq['token'] = this.editToken;
+
+               if ( _this.formData['watch'] )
+                       aReq['watch'] = _this.formData['watch'];
+
+               if ( _this.formData['ignorewarnings'] )
+                       aReq['ignorewarnings'] = _this.formData['ignorewarnings'];
+
+               var encoderSettings = this.getEncoderSettings();
+               js_log( 'do fogg upload/encode call: ' + _this.api_url + ' :: ' + JSON.stringify( aReq ) );
+               js_log( 'foggEncode: ' + JSON.stringify( encoderSettings ) );
+               _this.fogg.upload( JSON.stringify( encoderSettings ), _this.api_url, 
+                       JSON.stringify( aReq ) );
+
+               // Start polling the upload status
+               _this.doUploadStatus();
+       },
+
+       /**
+        * Encode the video and monitor progress.
+        *
+        * Calls progressCallback() regularly with a number between 0 and 1 indicating progress.
+        * Calls doneCallback() when the encode is finished.
+        *
+        * Asynchronous, returns immediately.
+        */
+       doEncode : function( progressCallback, doneCallback ) {
+               var _this = this;
+               _this.action_done = false;
+               _this.displayProgressOverlay();
+               var encoderSettings = this.getEncoderSettings();
+               js_log( 'doEncode: with: ' +  JSON.stringify( encoderSettings ) );
+               _this.fogg.encode( JSON.stringify( encoderSettings ) );
+
+               //show transcode status:
+               $j( '#up-status-state' ).html( gM( 'mwe-upload-transcoded-status' ) );
+
+               //setup a local function for timed callback:
+               var encodingStatus = function() {
+                       var status = _this.fogg.status();
+
+                       if ( _this.show_preview == true && _this.fogg.state == 'encoding' ) {
+                               _this.renderPreview();
+                       }
+
+                       // Update progress
+                       progressCallback( _this.fogg.progress() );
+
+                       //loop to get new status if still encoding
+                       if ( _this.fogg.state == 'encoding' ) {
+                               setTimeout( encodingStatus, 500 );
+                       } else if ( _this.fogg.state == 'encoding done' ) {
+                               _this.action_done = true;
+                               progressCallback( 1 );
+                               doneCallback();
+                       } else if ( _this.fogg.state == 'encoding fail' ) {
+                               //@@todo error handling:
+                               js_error( 'encoding failed' );
+                       }
+               }
+               encodingStatus();
+       },
+
+       /**
+        * Poll the upload progress and update the UI regularly until the upload is complete. 
+        *
+        * Asynchronous, returns immediately.
+        */
+       doUploadStatus: function() {
+               var _this = this;
+               $j( '#up-status-state' ).html( gM( 'mwe-uploaded-status' ) );
+
+               _this.oldResponseText = '';
+
+               // Create a local function for timed callback
+               var uploadStatus = function() {
+                       var response_text = _this.fogg.responseText;
+                       if ( !response_text ) {
+                               try {
+                                       var pstatus = JSON.parse( _this.fogg.uploadstatus() );
+                                       response_text = pstatus["responseText"];
+                               } catch( e ) {
+                                       js_log( "could not parse uploadstatus / could not get responseText" );
+                               }
+                       }
+
+                       if ( _this.oldResponseText != response_text ) {
+                               js_log( 'new result text:' + response_text + ' state:' + _this.fogg.state );
+                               _this.oldResponseText = response_text;
+                               // Parse the response text and check for errors
+                               try {
+                                       var apiResult = JSON.parse( response_text );
+                               } catch( e ) {
+                                       js_log( "could not parse response_text::" + response_text + 
+                                               ' ...for now try with eval...' );
+                                       try {
+                                               var apiResult = eval( response_text );
+                                       } catch( e ) {
+                                               var apiResult = null;
+                                       }
+                               }
+                               if ( apiResult && !_this.isApiSuccess( apiResult ) ) {
+                                       // Show the error and stop the upload
+                                       _this.showApiError( apiResult );
+                                       _this.action_done = true;
+                                       _this.fogg.cancel();
+                                       return false;
+                               }
+                       }
+                       if ( _this.show_preview == true ) {
+                               if ( _this.fogg.state == 'encoding' ) {
+                                       _this.renderPreview();
+                               }
+                       }
+
+                       // Update the progress bar
+                       _this.updateProgress( _this.fogg.progress() );
+
+                       // If we're still uploading or encoding, continue to poll the status
+                       if ( _this.fogg.state == 'encoding' || _this.fogg.state == 'uploading' ) {
+                               setTimeout( uploadStatus, 100 );
+                               return;
+                       }
+
+                       // Upload done?
+                       if ( -1 == $j.inArray( _this.fogg.state, [ 'upload done', 'done', 'encoding done' ] ) ) {
+                               js_log( 'Error:firefogg upload error: ' + _this.fogg.state );
+                               return;
+                       }
+                       if ( apiResult && apiResult.resultUrl ) {
+                               var buttons = {};
+                               buttons[ gM( 'mwe-go-to-resource' ) ] =  function() {
+                                       window.location = apiResult.resultUrl;
+                               }
+                               var go_to_url_txt = gM( 'mwe-go-to-resource' );
+                               var showMessage = true;
+                               if ( typeof _this.done_upload_cb == 'function' ) {
+                                       // Call the callback
+                                       // It will return false if it doesn't want us to show our own "done" message
+                                       showMessage = _this.done_upload_cb( _this.formData );
+                               }
+                               if ( showMessage ) {
+                                       _this.updateProgressWin( gM( 'mwe-successfulupload' ), 
+                                               gM( 'mwe-upload_done', apiResult.resultUrl ), buttons );
+                               } else {
+                                       this.action_done = true;
+                                       $j( '#upProgressDialog' ).empty().dialog( 'close' );
+                               }
+                       } else {
+                               // Done state with error? Not really possible given how firefogg works...
+                               js_log( " Upload done in chunks mode, but no resultUrl!" );
+                       }
+                       
+               }
+               uploadStatus();
+       },
+
+       /**
+        * This is the cancel button handler, referenced by getCancelButton() in the parent.
+        */
+       onCancel: function( dlElm ) {
+               if ( !this.have_firefogg ) {
+                       return this.pe_cancel_action();
+               }
+               js_log( 'firefogg:cancel' )
+               if ( confirm( gM( 'mwe-cancel-confim' ) ) ) {
+                       // FIXME: sillyness ( upstream firefogg cancel fix needed ) 
+                       if ( navigator.oscpu && navigator.oscpu.search( 'Win' ) >= 0 ) {
+                               alert( 'sorry we do not yet support cancel on windows' );
+                       } else {
+                               this.action_done = true;
+                               this.fogg.cancel();
+                               $j( dlElm ).empty().dialog( 'close' );
+                       }
+               }
+               // Don't follow the # link:
+               return false;
+       }
+};
diff --git a/js2/mwEmbed/libAddMedia/remoteSearchDriver.js b/js2/mwEmbed/libAddMedia/remoteSearchDriver.js
new file mode 100644 (file)
index 0000000..c0d4cc7
--- /dev/null
@@ -0,0 +1,2196 @@
+/*
+ * remoteSearchDriver
+ * Provides a base interface for the Add-Media-Wizard
+ * supporting remote searching of http archives for free images/audio/video assets
+ */
+
+loadGM( {
+       "mwe-add_media_wizard" : "Add media wizard",
+       "mwe-media_search" : "Media search",
+       "rsd_box_layout" : "Box layout",
+       "rsd_list_layout" : "List layout",
+       "rsd_results_desc" : "Results $1 to $2",
+       "rsd_results_desc_total" : "Results $1 to $2 of $3",
+       "rsd_results_next" : "next",
+       "rsd_results_prev" : "previous",
+       "rsd_no_results" : "No search results for <b>$1<\/b>",
+       "mwe-upload_tab" : "Upload",
+       "rsd_layout" : "Layout:",
+       "rsd_resource_edit" : "Edit resource: $1",
+       "mwe-resource_description_page" : "Resource description page",
+       "mwe-link" : "link",
+       "rsd_local_resource_title" : "Local resource title",
+       "rsd_do_insert" : "Do insert",
+       "mwe-cc_title" : "Creative Commons",
+       "mwe-cc_by_title" : "Attribution",
+       "mwe-cc_nc_title" : "Noncommercial",
+       "mwe-cc_nd_title" : "No Derivative Works",
+       "mwe-cc_sa_title" : "Share Alike",
+       "mwe-cc_pd_title" : "Public Domain",
+       "mwe-unknown_license" : "Unknown license",
+       "mwe-no_import_by_url" : "This user or wiki <b>cannot<\/b> import assets from remote URLs.<p>Do you need to login?<\/p><p>Is upload_by_url permission set for you?<br \/>Does the wiki have <a href=\"http:\/\/www.mediawiki.org\/wiki\/Manual:$wgAllowCopyUploads\">$wgAllowCopyUploads<\/a> enabled?<\/p>",
+       "mwe-results_from" : "Results from <a href=\"$1\" target=\"_new\" >$2<\/a>",
+       "mwe-missing_desc_see_source" : "This asset is missing a description. Please see the [$1 original source] and help describe it.",
+       "rsd_config_error" : "Add media wizard configuration error: $1",
+       "mwe-your_recent_uploads" : "Your recent uploads to $1",
+       "mwe-upload_a_file" : "Upload a new file to $1",
+       "mwe-resource_page_desc" : "Resource page description:",
+       "mwe-edit_resource_desc" : "Edit wiki text resource description:",
+       "mwe-local_resource_title" : "Local resource title:",
+       "mwe-watch_this_page" : "Watch this page",
+       "mwe-do_import_resource" : "Import resource",
+       "mwe-update_preview" : "Update resource page preview",
+       "mwe-cancel_import" : "Cancel import",
+       "mwe-importing_asset" : "Importing asset",
+       "mwe-preview_insert_resource" : "Preview insert of resource: $1",
+       "mwe-checking-resource" : "Checking for resource",
+       "mwe-resource-needs-import" : "Resource $1 needs to be imported to $2",
+       "mwe-ftype-svg" : "SVG vector file",
+       "mwe-ftype-jpg" : "JPEG image file",
+       "mwe-ftype-png" : "PNG image file",
+       "mwe-ftype-oga" : "Ogg audio file",
+       "mwe-ftype-ogg" : "Ogg video file",
+       "mwe-ftype-unk" : "Unknown file format",
+
+       "rsd-wiki_commons-title": "Wikimedia Commons",
+       "rsd-wiki_commons": "Wikimedia Commons, an archive of freely-licensed educational media content (images, sound and video clips)",
+
+       "rsd-this_wiki-title" : "This wiki",
+       "rsd-this_wiki-desc" : "The local wiki install",
+
+       "rsd-archive_org-title": "Archive.org",
+       "rsd-archive_org-desc" : "The Internet Archive, a digital library of cultural artifacts",
+
+       "rsd-flickr-title" : "Flickr.com",
+       "rsd-flickr-desc" : "Flickr.com, a online photo sharing site",
+       "rsd-metavid-title" : "Metavid.org",
+       "rsd-metavid-desc" : "Metavid.org, a community archive of US House and Senate floor proceedings"
+
+} );
+
+var default_remote_search_options = {
+       'profile': 'mediawiki_edit',
+       'target_container': null, // the div that will hold the search interface
+
+       'target_invoke_button': null, // the button or link that will invoke the search interface
+
+       'default_provider_id': 'all', // all or one of the content_providers ids
+
+       'local_wiki_api_url': null,
+
+       // Can be 'api', 'autodetect', 'remote_link'
+       'import_url_mode': 'api',
+
+       'target_title': null,
+
+       // Edit tools (can be an array of tools or keyword 'all')
+       'enabled_tools': 'all',
+
+
+       'target_textbox': null,
+       'target_render_area': null, // where output render should go:
+       'instance_name': null, // a globally accessible callback instance name
+       'default_query': null, // default search query
+
+       // Specific to sequence profile
+       'p_seq': null,
+       'cFileNS': 'File', // What is the canonical namespace prefix for images
+                          // @@todo (should get that from the api or in-page vars)
+
+       'upload_api_target': 'local', // can be local or the url or remote
+       'upload_api_name': null,
+       'upload_api_proxy_frame': null, // a page that will request mw.proxy.server
+
+       'enabled_providers': 'all', // can be keyword 'all' or an array of enabled content provider keys
+
+       'currentProvider': null // sets the default display item:
+}
+
+if ( typeof wgServer == 'undefined' )
+       wgServer = '';
+if ( typeof wgScriptPath == 'undefined' )
+       wgScriptPath = '';
+if ( typeof stylepath == 'undefined' )
+       stylepath = '';
+
+/*
+ * Base remoteSearch Driver interface
+ */
+var remoteSearchDriver = function( iObj ) {
+       return this.init( iObj );
+}
+
+remoteSearchDriver.prototype = {
+       results_cleared: false,
+       
+       caretPos: null, // lazy initialised
+       textboxValue: null, // lazy initialised
+
+       // here we define the set of possible media content providers:
+       // FIXME: unused
+       main_search_options: {
+               'selprovider': {
+                       'title': 'Select Providers'
+               },
+               'advanced_search': {
+                       'title': 'Advanced Options'
+               }
+       },
+
+       /** the default content providers list.
+        *
+        * (should be note that special tabs like "upload" and "combined" don't go into the content providers list:
+        * @note do not use double underscore in content providers names (used for id lookup)
+        *
+        * @@todo we will want to load more per user-preference and per category lookup
+        */
+       content_providers: {
+               /*content_providers documentation:
+                *  @@todo we should move the bulk of the configuration to each file
+                *
+
+                       @enabled: whether the search provider can be selected
+                       @checked: whether the search provider will show up as selectable tab
+                       @default: default: if the current cp should be displayed (only one should be the default)
+                       @title: the title of the search provider
+                       @desc: can use html
+                       @api_url: the url to query against given the library type:
+                       @lib: the search library to use corresponding to the
+                           search object ie: 'mediaWiki' = new mediaWikiSearchSearch()
+                       @tab_img: the tab image (if set to false use title text)
+                           if === "true" use standard location skin/images/{cp_id}_tab.png
+                           if === string use as url for image
+
+                       @linkback_icon default is: /wiki/skins/common/images/magnify-clip.png
+
+                       //domain insert: two modes: simple config or domain list:
+                       @local : if the content provider assets need to be imported or not.
+                       @local_domains : sets of domains for which the content is local
+                       //@@todo should query wgForeignFileRepos setting maybe interwikimap from the api
+                */
+
+               'this_wiki': {
+                       'enabled': 1,
+                       'checked': 1,
+                       'api_url':  ( wgServer && wgScriptPath ) ? 
+                               wgServer + wgScriptPath + '/api.php' : null,
+                       'lib': 'mediaWiki',
+                       'local': true,
+                       'tab_img': false
+               },
+               'wiki_commons': {
+                       'enabled': 1,
+                       'checked': 1,
+                       'homepage': 'http://commons.wikimedia.org/wiki/Main_Page',
+                       'api_url': 'http://commons.wikimedia.org/w/api.php',
+                       'lib': 'mediaWiki',
+                       'resource_prefix': 'WC_', // prefix on imported resources (not applicable if the repository is local)
+
+                       // if we should check for shared repository asset ( generally only applicable to commons )
+                       'check_shared': true,
+
+                       // list all the domains where commons is local?
+                       // probably should set this some other way by doing an api query
+                       // or by seeding this config when calling the remote search?
+                       'local_domains': [ 'wikimedia', 'wikipedia', 'wikibooks' ],
+                       // specific to wiki commons config:
+                       'search_title': false, // disable title search
+                       'tab_img': true
+               },
+               'archive_org': {
+                       'enabled': 1,
+                       'checked': 1,
+                       'homepage': 'http://www.archive.org/about/about.php',
+
+                       'api_url': 'http://homeserver7.us.archive.org:8983/solr/select',
+                       'lib': 'archiveOrg',
+                       'local': false,
+                       'resource_prefix': 'AO_',
+                       'tab_img': true
+               },
+               'flickr': {
+                       'enabled': 1,
+                       'checked': 1,
+                       'homepage': 'http://www.flickr.com/about/',
+
+                       'api_url': 'http://www.flickr.com/services/rest/',
+                       'lib': 'flickr',
+                       'local': false,
+                       // Just prefix with Flickr_ for now.
+                       'resource_prefix': 'Flickr_',
+                       'tab_img': true
+               },
+               'metavid': {
+                       'enabled': 1,
+                       'checked': 1,
+                       'homepage': 'http://metavid.org/wiki/Metavid_Overview',
+                       'api_url': 'http://metavid.org/w/index.php?title=Special:MvExportSearch',
+                       'lib': 'metavid',
+                       'local': false, // if local set to true we can use local
+                       'resource_prefix': 'MV_', // what prefix to use on imported resources
+
+                       'local_domains': ['metavid'], // if the domain name contains metavid
+                                                     // no need to import metavid content to metavid sites
+
+                       'stream_import_key': 'mv_ogg_low_quality', // which stream to import, could be mv_ogg_high_quality
+                                                                  // or flash stream, see ROE xml for keys
+
+                       'remote_embed_ext': false, // if running the remoteEmbed extension no need to copy local
+                                                  // syntax will be [remoteEmbed:roe_url link title]
+                       'tab_img': true
+               },
+               // special cp "upload"
+               'upload': {
+                       'enabled': 1,
+                       'checked': 1,
+                       'title': 'Upload'
+               }
+       },
+
+       // define the licenses
+       // ... this will get complicated quick...
+       // (just look at complexity for creative commons without excessive "duplicate data")
+       // ie cc_by could be "by/3.0/us/" or "by/2.1/jp/" to infinitum...
+       // some complexity should be negated by license equivalences.
+
+       // but we will have to abstract into another class let content providers provide license urls
+       // and we have to clone the license object and allow local overrides
+
+       licenses: {
+               // for now only support creative commons type licenses
+               // used page: http://creativecommons.org/licenses/
+               'cc': {
+                       'base_img_url':'http://upload.wikimedia.org/wikipedia/commons/thumb/',
+                       'base_license_url': 'http://creativecommons.org/licenses/',
+                       'licenses': [
+                               'by',
+                               'by-sa',
+                               'by-nc-nd',
+                               'by-nc',
+                               'by-nd',
+                               'by-nc-sa',
+                               'by-sa',
+                               'pd'
+                       ],
+                       'license_images': {
+                               'by': {
+                                       'image_url': '1/11/Cc-by_new_white.svg/20px-Cc-by_new_white.svg.png'
+                               },
+                               'nc': {
+                                       'image_url': '2/2f/Cc-nc_white.svg/20px-Cc-nc_white.svg.png'
+                               },
+                               'nd': {
+                                       'image_url': 'b/b3/Cc-nd_white.svg/20px-Cc-nd_white.svg.png'
+                               },
+                               'sa': {
+                                       'image_url': 'd/df/Cc-sa_white.svg/20px-Cc-sa_white.svg.png'
+                               },
+                               'pd': {
+                                       'image_url': '5/51/Cc-pd-new_white.svg/20px-Cc-pd-new_white.svg.png'
+                               }
+                       }
+               }
+       },
+
+       // some default layout values:
+       thumb_width: 80,
+       image_edit_width: 400,
+       video_edit_width: 400,
+       insert_text_pos: 0, // insert at the start (will be overwritten by the user cursor pos)
+       displayMode : 'box', // box or list
+
+       cUpLoader: null,
+       clipEdit: null,
+       proxySetupDone: null,
+       dmodalCss: {},
+
+       init: function( options ) {
+               var _this = this;
+               js_log( 'remoteSearchDriver:init' );
+               // Add in a local "id" reference to each provider
+               for ( var cp_id in this.content_providers ) {
+                       this.content_providers[ cp_id ].id = cp_id;
+               }
+
+               // Merge in the options
+               // @@todo for cleaner config we should set _this.opt to the provided options
+               $j.extend( _this, default_remote_search_options, options );
+
+               // Quick fix for cases where people put ['all'] instead of 'all' for enabled_providers
+               if ( _this.enabled_providers.length == 1 && _this.enabled_providers[0] == 'all' )
+                       _this.enabled_providers = 'all';
+
+               // Set up content_providers
+               for ( var provider in this.content_providers ) {
+                       if ( _this.enabled_providers == 'all' && !this.currentProvider  ) {
+                               this.currentProvider = provider;
+                               break;
+                       } else {
+                               if ( $j.inArray( provider, _this.enabled_providers ) != -1 ) {
+                                       // This provider is enabled
+                                       this.content_providers[provider].enabled = true;
+                                       // Set the current provider to the first enabled one
+                                       if ( !this.currentProvider ) {
+                                               this.currentProvider = provider;
+                                       }
+                               } else {
+                                       // This provider is disabled
+                                       if ( _this.enabled_providers != 'all' ) {
+                                               this.content_providers[provider].enabled = false;
+                                       }
+                               }
+                       }
+               }
+
+               // Set the upload target name if unset
+               if ( _this.upload_api_target == 'local' 
+                       && ! _this.upload_api_name 
+                       && typeof wgSiteName != 'undefined' )
+               {
+                       _this.upload_api_name =  wgSiteName;
+               }
+
+               // Set the target to "proxy" if a proxy frame is configured
+               if ( _this.upload_api_proxy_frame )
+                       _this.upload_api_target = 'proxy';
+
+               // Set up the local API upload URL
+               if ( _this.upload_api_target == 'local' ) {
+                       if ( ! _this.local_wiki_api_url ) {
+                               $j( '#tab-upload' ).html( gM( 'rsd_config_error', 'missing_local_api_url' ) );
+                               return false;
+                       } else {
+                               _this.upload_api_target = _this.local_wiki_api_url;
+                       }
+               }
+
+               // Set up the "add media wizard" button, which invokes this object
+               if ( $j( this.target_invoke_button ).length == 0 ) {
+                       js_log( "RemoteSearchDriver:: no target invocation provided " + 
+                               "(will have to run your own createUI() )" );
+               } else {
+                       if ( this.target_invoke_button ) {
+                               $j( this.target_invoke_button )
+                                       .css( 'cursor', 'pointer' )
+                                       .attr( 'title', gM( 'mwe-add_media_wizard' ) )
+                                       .click( function() {
+                                               _this.createUI();
+                                       } );
+                       }
+               }
+       },
+
+       /*
+        * getLicenseIconHtml
+        * @param license_key  the license key (ie "by-sa" or "by-nc-sa" etc)
+        */
+       getLicenseIconHtml: function( licenseObj ) {
+               // js_log('output images: '+ imgs);
+               return '<div class="rsd_license" title="' + licenseObj.title + '" >' +
+                       '<a target="_new" href="' + licenseObj.lurl + '" ' +
+                       'title="' + licenseObj.title + '">' +
+                       licenseObj.img_html +
+                       '</a>' +
+                       '</div>';
+       },
+
+       /*
+        * getLicenseKeyFromKey
+        * @param license_key the key of the license (must be defined in: this.licenses.cc.licenses)
+        */
+       getLicenseFromKey: function( license_key, force_url ) {
+               // set the current license pointer:
+               var cl = this.licenses.cc;
+               var title = gM( 'mwe-cc_title' );
+               var imgs = '';
+               var license_set = license_key.split( '-' );
+               for ( var i = 0; i < license_set.length; i++ ) {
+                       var lkey = license_set[i];
+                       if ( !cl.license_images[ lkey ] ) {
+                               js_log( "MISSING::" + lkey );
+                       }
+
+                       title += ' ' + gM( 'mwe-cc_' + lkey + '_title' );
+                       imgs += '<img class="license_desc" width="20" src="' +
+                               cl.base_img_url + cl.license_images[ lkey ].image_url + '">';
+               }
+               var url = ( force_url ) ? force_url : cl.base_license_url + cl.licenses[ license_key ];
+               return {
+                       'title': title,
+                       'img_html': imgs,
+                       'key': license_key,
+                       'lurl': url
+               };
+       },
+
+       /*
+        * getLicenseKeyFromUrl
+        * @param license_url the url of the license
+        */
+       getLicenseFromUrl: function( license_url ) {
+               // check for some pre-defined url types:
+               if ( license_url == 'http://www.usa.gov/copyright.shtml' ||
+                       license_url == 'http://creativecommons.org/licenses/publicdomain' )
+                       return this.getLicenseFromKey( 'pd' , license_url );
+
+
+               // js_log("getLicenseFromUrl::" + license_url);
+               // first do a direct lookup check:
+               for ( var j = 0; j < this.licenses.cc.licenses.length; j++ ) {
+                       var jL = this.licenses.cc.licenses[ j ];
+                       // special 'pd' case:
+                       if ( jL == 'pd' ) {
+                               var keyCheck = 'publicdomain';
+                       } else {
+                               var keyCheck = jL;
+                       }
+                       if ( mw.parseUri( license_url ).path.indexOf( '/' + keyCheck + '/' ) != -1 ) {
+                               return this.getLicenseFromKey( jL , license_url );
+                       }
+               }
+               // Could not find it return mwe-unknown_license
+               return {
+                       'title': gM( 'mwe-unknown_license' ),
+                       'img_html': '<span>' + gM( 'mwe-unknown_license' ) + '</span>',
+                       'lurl': license_url
+               };
+       },
+
+       /**
+       * getTypeIcon
+       * @param str mime type of the requested file
+       */
+       getTypeIcon: function( mimetype ) {
+               var typestr = 'unk';
+               switch ( mimetype ) {
+                       case 'image/svg+xml':
+                               typestr = 'svg';
+                               break;
+                       case 'image/jpeg':
+                               typestr = 'jpg'
+                               break;
+                       case 'image/png':
+                               typestr = 'png';
+                               break;
+                       case 'audio/ogg':
+                               typestr = 'oga';
+                       case 'video/ogg':
+                       case 'application/ogg':
+                               typestr = 'ogg';
+                               break;
+               }
+
+               if ( typestr == 'unk' ) {
+                       js_log( "unkown ftype: " + mimetype );
+                       return '';
+               }
+
+               return '<div ' + 
+                       'class="rsd_file_type ui-corner-all ui-state-default ui-widget-content" ' + 
+                       'title="' + gM( 'mwe-ftype-' + typestr ) + '">' +
+                       typestr  +
+                       '</div>';
+       },
+
+       createUI: function() {
+               var _this = this;
+
+               this.clearTextboxCache();
+               // setup the parent container:
+               this.createDialogContainer();
+               // fill in the html:
+               this.initDialog();
+               // bind actions:
+               this.add_interface_bindings();
+
+               // update the target binding to just un-hide the dialog:
+               if ( this.target_invoke_button ) {
+                       $j( this.target_invoke_button )
+                               .unbind()
+                               .click( function() {
+                                       js_log( "createUI:target_invoke_button: click showDialog" );
+                                        _this.showDialog();
+                                } );
+               }
+       },
+
+       showDialog: function() {
+               var _this = this;
+               js_log( "showDialog::" );
+               _this.clearTextboxCache();
+               var query = _this.getDefaultQuery();
+               if ( query !=  $j( '#rsd_q' ).val() ) {
+                       $j( '#rsd_q' ).val( query );
+                       _this.showCurrentTab();
+               }
+               // $j(_this.target_container).dialog("open");
+               $j( _this.target_container ).parents( '.ui-dialog' ).fadeIn( 'slow' );
+               // re-center the dialog:
+               $j( _this.target_container ).dialog( 'option', 'position', 'center' );
+       },
+
+       clearTextboxCache: function() {
+               this.caretPos = null;
+               this.textboxValue = null;
+               this.default_query = null;
+       },
+
+       getCaretPos: function() {
+               if ( this.caretPos == null ) {
+                       if ( this.target_textbox ) {
+                               this.caretPos = $j( this.target_textbox ).getCaretPosition();
+                       } else {
+                               this.caretPos = false;
+                       }
+               }
+               return this.caretPos;
+       },
+
+       getTextboxValue: function() {
+               if ( this.textboxValue == null ) {
+                       if ( this.target_textbox ) {
+                               this.textboxValue = $j( this.target_textbox ).val();
+                       } else {
+                               this.textboxValue = '';
+                       }
+               }
+               return this.textboxValue;
+       },
+
+       getDefaultQuery: function() {
+               if ( this.default_query == null ) {
+                       if ( this.target_textbox ) {
+                               var ts = $j( this.target_textbox ).textSelection();
+                               if ( ts != '' ) {
+                                       this.default_query = ts;
+                               } else {
+                                       this.default_query = '';
+                               }
+                       }
+               }
+               return this.default_query;
+       },
+
+       createDialogContainer: function() {
+               js_log( "createDialogContainer" );
+               var _this = this;
+               // add the parent target_container if not provided or missing
+               if ( _this.target_container && $j( _this.target_container ).length != 0 ) {
+                       js_log(  'dialog already exists' );
+                       return;
+               }
+
+               _this.target_container = '#rsd_modal_target';
+               $j( 'body' ).append(
+                       '<div ' + 
+                               'id="rsd_modal_target" ' + 
+                               'style="position:absolute;top:3em;left:0px;bottom:3em;right:0px;" ' + 
+                               'title="' + gM( 'mwe-add_media_wizard' ) + '" >' + 
+                       '</div>' );
+               // js_log('appended: #rsd_modal_target' + $j(_this.target_container).attr('id'));
+               // js_log('added target id:' + $j(_this.target_container).attr('id'));
+               // get layout
+               js_log( 'width: ' + $j( window ).width() +  ' height: ' + $j( window ).height() );
+               var cBtn = {};
+               cBtn[ gM( 'mwe-cancel' ) ] = function() {
+                       _this.onCancelClipEdit();
+               }
+
+               $j( _this.target_container ).dialog( {
+                       bgiframe: true,
+                       autoOpen: true,
+                       modal: true,
+                       draggable: false,
+                       resizable: false,
+                       buttons: cBtn,
+                       close: function() {
+                               // if we are 'editing' a item close that
+                               // @@todo maybe prompt the user?
+                               _this.onCancelClipEdit();
+                               $j( this ).parents( '.ui-dialog' ).fadeOut( 'slow' );
+                       }
+               } );
+               $j( _this.target_container ).dialogFitWindow();
+               $j( window ).resize( function() {
+                       $j( _this.target_container ).dialogFitWindow();
+               } );
+
+               // add cancel callback and updated button with icon
+               _this.onCancelClipEdit();
+       },
+
+       // sets up the initial html interface
+       initDialog: function() {
+               js_log( 'initDialog' );
+               var _this = this;
+               js_log( 'f::initDialog' );
+
+               var o = '<div class="rsd_control_container" style="width:100%">' +
+                       '<form id="rsd_form" action="javascript:return false;" method="GET">' +
+                       '<input ' + 
+                               'class="ui-widget-content ui-corner-all" ' + 
+                               'type="text" ' + 
+                               'tabindex="1" ' + 
+                               'value="' + this.getDefaultQuery() + '" ' + 
+                               'maxlength="512" ' + 
+                               'id="rsd_q" ' + 
+                               'name="rsd_q" ' +
+                               'size="20" ' + 
+                               'autocomplete="off" />' +
+                       $j.btnHtml( gM( 'mwe-media_search' ), 'rms_search_button', 'search' ) +
+                       '</form>';
+               // close up the control container:
+               o += '</div>';
+
+               // search provider tabs based on "checked" and "enabled" and "combined tab"
+               o += '<div ' + 
+                               'id="rsd_results_container" ' + 
+                               'style="top:0px;bottom:0px;left:0px;right:0px;">' + 
+                       '</div>';
+               $j( this.target_container ).html( o );
+               // add simple styles:
+               $j( this.target_container + ' .rms_search_button' ).btnBind().click( function() {
+                       _this.showCurrentTab();
+               } );
+
+               // draw the tabs:
+               this.createTabs();
+               // run the default search:
+               if ( this.getDefaultQuery() )
+                       this.showCurrentTab();
+
+               // Add bindings
+               $j( '#mso_selprovider,#mso_selprovider_close' )
+                       .unbind()
+                       .click( function() {
+                               if ( $j( '#rsd_options_bar:hidden' ).length != 0 ) {
+                                       $j( '#rsd_options_bar' ).animate( {
+                                               'height': '110px',
+                                               'opacity': 1
+                                       }, "normal" );
+                               } else {
+                                       $j( '#rsd_options_bar' ).animate( {
+                                               'height': '0px',
+                                               'opacity': 0
+                                       }, "normal", function() {
+                                               $j( this ).hide();
+                                       } );
+                               }
+                       } );
+               // set form bindings
+               $j( '#rsd_form' )
+                       .unbind()
+                       .submit( function() {
+                               _this.showCurrentTab();
+                               // don't submit the form
+                               return false;
+                       } );
+       },
+
+       showUploadTab: function() {
+               js_log( "showUploadTab::" );
+               var _this = this;
+               // set it to loading:
+               mv_set_loading( '#tab-upload' );
+               // do things async to keep interface snappy
+               setTimeout(
+                       function() {
+                               // check if we need to setup the proxy::
+                               if ( _this.upload_api_target == 'proxy' ) {
+                                       _this.setupProxy( function() {
+                                               _this.showUploadForm();
+                                       } );
+                               } else {
+                                       _this.showUploadForm();
+                               }
+                       }, 
+                       1 );
+       },
+
+       showUploadForm: function() {
+               var _this = this;
+               mvJsLoader.doLoad( ['$j.fn.simpleUploadForm'], function() {
+                       // get extends info about the file
+                       var provider = _this.content_providers['this_wiki'];
+
+                       // check for "this_wiki" enabled
+                       /*if(!provider.enabled){
+                               $j('#tab-upload')
+                                       .html('error this_wiki not enabled (can\'t get uploaded file info)');
+                               return false;
+                       }*/
+
+                       // load  this_wiki search system to grab the resource
+                       _this.loadSearchLib( provider, function() {
+                               _this.showUploadForm_internal( provider );
+                       } );
+               } );
+       },
+
+       showUploadForm_internal: function( provider ) {
+               var _this = this;
+               var uploadMsg = gM( 'mwe-upload_a_file', _this.upload_api_name );
+               var recentUploadsMsg = gM( 'mwe-your_recent_uploads', _this.upload_api_name );
+               // do basic layout form on left upload "bin" on right
+               $j( '#tab-upload' ).html( 
+                       '<table>' +
+                       '<tr>' +
+                       '<td valign="top" style="width:350px; padding-right: 12px;">' +
+                       '<h4>' + uploadMsg + '</h4>' +
+                       '<div id="upload_form">' +
+                       mv_get_loading_img() +
+                       '</div>' +
+                       '</td>' +
+                       '<td valign="top" id="upload_bin_cnt">' +
+                       '<h4>' + recentUploadsMsg + '</h4>' +
+                       '<div id="upload_bin">' +
+                       mv_get_loading_img() +
+                       '</div>' +
+                       '</td>' +
+                       '</tr>' +
+                       '</table>' );
+
+
+               // fill in the user page:
+               if ( typeof wgUserName != 'undefined' && wgUserName ) {
+                       // load the upload bin with anything the current user has uploaded
+                       provider.sObj.getUserRecentUploads( wgUserName, function() {
+                               _this.showResults();
+                       } );
+               } else {
+                       $j( '#upload_bin_cnt' ).empty();
+               }
+
+               // deal with the api form upload form directly:
+               $j( '#upload_form' ).simpleUploadForm( {
+                       "api_target" : _this.upload_api_target,
+                       "ondone_cb": function( resultData ) {
+                               var wTitle = resultData['filename'];
+                               // add a loading div
+                               _this.addResourceEditLoader();
+                               // @@note: we have most of what we need in resultData imageinfo
+                               provider.sObj.addByTitle( wTitle, function( resource ) {
+                                       // Redraw ( with added result if new )
+                                       _this.showResults();
+                                       // Pull up resource editor:
+                                       _this.showResourceEditor( resource, $j( '#res_upload__' + resource.id ).get( 0 ) );
+                               } );
+                               // Return false to close progress window:
+                               return false;
+                       }
+               } );
+       },
+
+       showCurrentTab: function() {
+               if ( this.currentProvider == 'upload' ) {
+                       this.showUploadTab();
+               } else {
+                       this.showSearchTab( this.currentProvider, false );
+               }
+       }
+
+       showSearchTab: function( providerName, resetPaging ) {
+               js_log( "f:showSearchTab::" + providerName );
+
+               var draw_direct_flag = true;
+
+               // else do showSearchTab
+               var provider = this.content_providers[providerName];
+
+               // check if we need to update:
+               if ( typeof provider.sObj != 'undefined' ) {
+                       if ( provider.sObj.last_query == $j( '#rsd_q' ).val() 
+                               && provider.sObj.last_offset == provider.offset ) 
+                       {
+                               js_log( 'last query is: ' + provider.sObj.last_query + 
+                                       ' matches: ' +  $j( '#rsd_q' ).val() );
+                       } else {
+                               js_log( 'last query is: ' + provider.sObj.last_query + 
+                                       ' not match: ' +  $j( '#rsd_q' ).val() );
+                               draw_direct_flag = false;
+                       }
+               } else {
+                       draw_direct_flag = false;
+               }
+               if ( !draw_direct_flag ) {
+                       // see if we should reset the paging
+                       if ( resetPaging ) {
+                               provider.sObj.offset = provider.offset = 0;
+                       }
+
+                       // set the content to loading while we do the search:
+                       $j( '#tab-' + providerName ).html( mv_get_loading_img() );
+
+                       // Make sure the search library is loaded and issue the search request
+                       this.getLibSearchResults( provider );
+               }
+       },
+
+       // Issue a api request & cache the result
+       // this check can be avoided by setting the 
+       // this.import_url_mode = 'api' | 'form' | instead of 'autodetect' or 'none'
+       checkForCopyURLSupport: function ( callback ) {
+               var _this = this;
+               js_log( 'checkForCopyURLSupport:: ' );
+
+               // See if we already have the import mode:
+               if ( this.import_url_mode != 'autodetect' ) {
+                       js_log( 'import mode: ' + _this.import_url_mode );
+                       callback();
+               }
+               // If we don't have the local wiki api defined we can't auto-detect use "link"
+               if ( ! _this.upload_api_target ) {
+                       js_log( 'import mode: remote link (no import_wiki_api_url)' );
+                       _this.import_url_mode = 'remote_link';
+                       callback();
+               }
+               if ( this.import_url_mode == 'autodetect' ) {
+                       do_api_req( 
+                               {
+                                       'url': _this.upload_api_target,
+                                       'data': {
+                                               'action': 'paraminfo',
+                                               'modules': 'upload'
+                                       }
+                               }, function( data ) {
+                                       // jump right into api checks:
+                                       for ( var i in data.paraminfo.modules[0].parameters ) {
+                                               var pname = data.paraminfo.modules[0].parameters[i].name;
+                                               if ( pname == 'url' ) {
+                                                       js_log( 'Autodetect Upload Mode: api: copy by url:: ' );
+                                                       // check permission  too:
+                                                       _this.checkForCopyURLPermission( function( canCopyUrl ) {
+                                                               if ( canCopyUrl ) {
+                                                                       _this.import_url_mode = 'api';
+                                                                       js_log( 'import mode: ' + _this.import_url_mode );
+                                                                       callback();
+                                                               } else {
+                                                                       _this.import_url_mode = 'none';
+                                                                       js_log( 'import mode: ' + _this.import_url_mode );
+                                                                       callback();
+                                                               }
+                                                       } );
+                                                       break;
+                                               }
+                                       }
+                               }
+                       );
+               }
+       },
+
+       /*
+        * checkForCopyURLPermission:
+        * not really necessary the api request to upload will return appropriate error 
+        * if the user lacks permission. or $wgAllowCopyUploads is set to false
+        * (use this function if we want to issue a warning up front)
+        */
+       checkForCopyURLPermission: function( callback ) {
+               var _this = this;
+               // do api check:
+               do_api_req( 
+                       {
+                               'data': { 'action' : 'query', 'meta' : 'userinfo', 'uiprop' : 'rights' },
+                               'url': _this.upload_api_target,
+                               'userinfo' : true
+                       }, function( data ) {
+                               for ( var i in data.query.userinfo.rights ) {
+                                       var right = data.query.userinfo.rights[i];
+                                       // js_log('checking: ' + right ) ;
+                                       if ( right == 'upload_by_url' ) {
+                                               callback( true );
+                                               return true; // break out of the function
+                                       }
+                               }
+                               callback( false );
+                       } 
+               );
+       },
+
+       getLibSearchResults: function( provider ) {
+               var _this = this;
+
+               // first check if we should even run the search at all (can we import / insert 
+               // into the page? )
+               if ( !this.isProviderLocal( provider ) && this.import_url_mode == 'autodetect' ) {
+                       // provider is not local check if we can support the import mode:
+                       this.checkForCopyURLSupport( function() {
+                               _this.getLibSearchResults( provider );
+                       } );
+                       return false;
+               } else if ( !this.isProviderLocal( provider ) && this.import_url_mode == 'none' ) {
+                       if (  this.currentProvider == 'combined' ) {
+                               // combined results are harder to error handle just ignore that repo
+                               provider.sObj.loading = false;
+                       } else {
+                               $j( '#tab-' + this.currentProvider ).html( 
+                                       '<div style="padding:10px">' + 
+                                       gM( 'mwe-no_import_by_url' ) + 
+                                       '</div>' );
+                       }
+                       return false;
+               }
+               _this.loadSearchLib( provider, function() {
+                       // Do the search
+                       provider.sObj.getSearchResults();
+                       _this.waitForResults( function() {
+                               this.showResults();
+                       } );
+               } );
+       },
+
+       loadSearchLib: function( provider, callback ) {
+               var _this = this;
+               // set up the library req:
+               mvJsLoader.doLoad( [
+                       'baseRemoteSearch',
+                       provider.lib + 'Search'
+               ], function() {
+                       js_log( "loaded lib:: " + provider.lib );
+                       // else we need to run the search:
+                       var options = {
+                               'provider': provider,
+                               'rsd': _this
+                       };
+                       eval( 'provider.sObj = new ' + provider.lib + 'Search( options );' );
+                       if ( !provider.sObj ) {
+                               js_log( 'Error: could not find search lib for ' + cp_id );
+                               return false;
+                       }
+
+                       // inherit defaults if not set:
+                       provider.limit = provider.limit ? provider.limit : provider.sObj.limit;
+                       provider.offset = provider.offset ? provider.offset : provider.sObj.offset;
+                       callback();
+               } );
+       },
+
+       /* check for all the results to finish */
+       waitForResults: function( callback ) {
+               // js_log('rsd:waitForResults');
+               var _this = this;
+               var loading_done = true;
+
+               for ( var cp_id in this.content_providers ) {
+                       var cp = this.content_providers[ cp_id ];
+                       if ( typeof cp['sObj'] != 'undefined' ) {
+                               if ( cp.sObj.loading )
+                                       loading_done = false;
+                       }
+               }
+               if ( loading_done ) {
+                       callback();
+               } else {
+                       setTimeout( 
+                               function() {
+                                       _this.waitForResults( callback );
+                               }, 
+                               50 
+                       );
+               }
+       },
+
+       createTabs: function() {
+               var _this = this;
+               // add the tabs to the rsd_results container:
+               var s = '<div id="rsd_tabs_container" style="width:100%;">';
+               var selected_tab = 0;
+               var index = 0;
+               s += '<ul>';
+               var content = '';
+               for ( var providerName in this.content_providers ) {
+                       var provider = this.content_providers[providerName];
+                       var tabImage = mv_embed_path + '/skins/common/remote_cp/' + providerName + '_tab.png';
+                       if ( provider.enabled && provider.checked && provider.api_url ) {
+                               // add selected default if set
+                               if ( this.currentProvider == providerName )
+                                       selected_tab = index;
+
+                               s += '<li class="rsd_cp_tab">';
+                               s += '<a id="rsd_tab_' + providerName + '" href="#tab-' + providerName + '">';
+                               if ( provider.tab_img === true ) {
+                                       s += '<img alt="' + gM( 'rsd-' + providerName + '-title' ) + '" ' + 
+                                               'src="' + tabImage + '">';
+                               } else {
+                                       s += gM( 'rsd-' + providerName + '-title' );
+                               }
+                               s += '</a>';
+                               s += '</li>';
+                               index++;
+                       }
+                       content += '<div id="tab-' + providerName + '" class="rsd_results"/>';
+               }
+               // Do an upload tab if enabled:
+               if ( this.content_providers['upload'].enabled ) {
+                       s += '<li class="rsd_cp_tab" >' + 
+                               '<a id="rsd_tab_upload" href="#tab-upload">' + 
+                               gM( 'mwe-upload_tab' ) + 
+                               '</a></li>';
+                       content += '<div id="tab-upload" />';
+                       if ( this.currentProvider == 'upload' )
+                               selected_tab = index++;
+               }
+               s += '</ul>';
+               // Output the tab content containers:
+               s += content;
+               s += '</div>'; // close tab container
+
+               // Output the respective results holders
+               $j( '#rsd_results_container' ).html( s );
+               // Setup bindings for tabs make them sortable: (@@todo remember order)
+               js_log( 'selected tab is: ' + selected_tab );
+               $j( "#rsd_tabs_container" )
+                       .tabs( {
+                               selected: selected_tab,
+                               select: function( event, ui ) {
+                                       _this.selectTab( $j( ui.tab ).attr( 'id' ).replace( 'rsd_tab_', '' ) );
+                               }
+                       })
+                       // Add sorting
+                       .find( ".ui-tabs-nav" ).sortable( { axis: 'x' } );
+               // @@todo store sorted repo
+       },
+
+       // Resource title
+       getResourceFromTitle: function( title, callback ) {
+               var _this = this;
+               reqObj = {
+                       'action': 'query',
+                       'titles': _this.cFileNS + ':' + title
+               };
+               do_api_req( {
+                       'data': reqObj,
+                       'url': this.local_wiki_api_url
+                       }, function( data ) {
+                               // @@todo propagate the resource
+                               var resource = {};
+                       }
+               );
+       },
+
+       // @@todo we could load the id with the content provider id to find the object faster...
+       getResourceFromId: function( id ) {
+               var parts = id.replace( /^res_/, '' ).split( '__' );
+               var providerName = parts[0];
+               var resIndex = parts[1];
+
+               // Set the upload helper providerName (to render recent uploads by this user)
+               if ( providerName == 'upload' )
+                       providerName = 'this_wiki';
+
+               var provider = this.content_providers[providerName];
+               if ( provider && provider['sObj'] && provider.sObj.resultsObj[resIndex] ) {
+                       return provider.sObj.resultsObj[resIndex];
+               }
+               js_log( "ERROR: could not find " + resIndex );
+               return false;
+       },
+
+       showResults: function() {
+               js_log( 'f:showResults::' + this.currentProvider );
+               var _this = this;
+               var o = '';
+               var tabSelector = '';
+
+               if ( this.currentProvider == 'upload' ) {
+                       tabSelector = '#upload_bin';
+                       var provider = _this.content_providers['this_wiki'];
+               } else {
+                       var provider = this.content_providers[this.currentProvider];
+                       tabSelector = '#tab-' + this.currentProvider;
+                       // Output the results bar / controls
+               }
+               // Empty the existing results:
+               $j( tabSelector ).empty();
+               // @@todo give the user upload control love
+               if ( this.currentProvider != 'upload' ) {
+                       _this.showResultsHeader();
+               }
+
+               var numResults = 0;
+
+               // Output all the results for the current currentProvider
+               if ( typeof provider['sObj'] != 'undefined' ) {
+                       $j.each( provider.sObj.resultsObj, function( resIndex, resource ) {
+                               o += _this.getResultHtml( provider, resIndex, resource );
+                               numResults++;
+                       } );
+                       js_log( 'append to: ' + '#tab-' + cp_id );
+                       // Put in the tab output (plus clear the output)
+                       $j( tabSelector ).append( o + '<div style="clear:both"/>' );
+               }
+
+               js_log( 'did numResults :: ' + numResults + 
+                       ' append: ' + $j( '#rsd_q' ).val() );
+
+               // Remove any old search res
+               $j( '#rsd_no_search_res' ).remove();
+               if ( numResults == 0 ) {
+                       $j( '#tab-' + cp_id ).append( 
+                               '<span style="padding:10px">' + 
+                               gM( 'rsd_no_results', $j( '#rsd_q' ).val() ) + 
+                               '</span>' );
+               }
+               this.addResultBindings();
+       },
+
+       getResultHtml: function( provider, resIndex, resource ) {
+               var o = '';
+               if ( this.displayMode == 'box' ) {
+                       o += '<div id="mv_result_' + resIndex + '" ' + 
+                               'class="mv_clip_box_result" ' + 
+                               'style="' + 
+                                       'width:' + this.thumb_width + 'px;' + 
+                                       'height:' + ( this.thumb_width - 20 ) + 'px;' + 
+                                       'position:relative;">';
+                       // Check for missing poster types for audio
+                       if ( resource.mime == 'audio/ogg' && !resource.poster ) {
+                               resource.poster = mv_skin_img_path + 'sound_music_icon-80.png';
+                       }
+                       // Get a thumb with proper resolution transform if possible:
+                       var thumbUrl = provider.sObj.getImageTransform( resource, 
+                               { 'width' : this.thumb_width } );
+
+                       o += '<img title="' + resource.title + '" ' +
+                               'class="rsd_res_item" id="res_' + cp_id + '__' + resIndex + '" ' +
+                               'style="width:' + this.thumb_width + 'px;" ' + 
+                               'src="' + thumbUrl + '">';
+                       // Add a linkback to resource page in upper right:
+                       if ( resource.link ) {
+                               o += '<div class="' + 
+                                               'rsd_linkback ui-corner-all ui-state-default ui-widget-content" >' +
+                                       '<a target="_new" title="' + gM( 'mwe-resource_description_page' ) +
+                                       '" href="' + resource.link + '">' + gM( 'mwe-link' ) + '</a>' +
+                                       '</div>';
+                       }
+
+                       // Add file type icon if known
+                       if ( resource.mime ) {
+                               o += this.getTypeIcon( resource.mime );
+                       }
+
+                       // Add license icons if present
+                       if ( resource.license )
+                               o += this.getLicenseIconHtml( resource.license );
+
+                       o += '</div>';
+               } else if ( this.displayMode == 'list' ) {
+                       o += '<div id="mv_result_' + resIndex + '" class="mv_clip_list_result" style="width:90%">';
+                       o += 
+                               '<img ' + 
+                                       'title="' + resource.title + '" ' + 
+                                       'class="rsd_res_item" id="res_' + cp_id + '__' + resIndex + '" ' + 
+                                       'style="float:left;width:' + this.thumb_width + 'px;" ' +
+                                       'src="' + provider.sObj.getImageTransform( resource, { 'width': this.thumb_width } ) + '">';
+                       // Add license icons if present
+                       if ( resource.license )
+                               o += this.getLicenseIconHtml( resource.license );
+
+                       o += resource.desc ;
+                       o += '<div style="clear:both" />';
+                       o += '</div>';
+               }
+               return o;
+       }
+
+       addResultBindings: function() {
+               var _this = this;
+               $j( '.mv_clip_' + _this.displayMode + '_result' ).hover( 
+                       function() {
+                               $j( this ).addClass( 'mv_clip_' + _this.displayMode + '_result_over' );
+                               // Also set the animated image if available
+                               var res_id = $j( this ).children( '.rsd_res_item' ).attr( 'id' );
+                               var resource = _this.getResourceFromId( res_id );
+                               if ( resource.poster_ani )
+                                       $j( '#' + res_id ).attr( 'src', resource.poster_ani );
+                       }, function() {
+                               $j( this ).removeClass( 
+                                       'mv_clip_' + _this.displayMode + '_result_over' );
+                               var res_id = $j( this ).children( '.rsd_res_item' ).attr( 'id' );
+                               var resource = _this.getResourceFromId( res_id );
+                               // Restore the original (non animated)
+                               if ( resource.poster_ani )
+                                       $j( '#' + res_id ).attr( 'src', resource.poster );
+                       } 
+               );
+               // Resource click action: (bring up the resource editor)
+               $j( '.rsd_res_item' ).unbind().click( function() {
+                       var resource = _this.getResourceFromId( $j( this ).attr( "id" ) );
+                       _this.showResourceEditor( resource, this );
+               } );
+       },
+
+       addResourceEditLoader: function( maxWidth, overflowStyle ) {
+               var _this = this;
+               if ( !maxWidth ) maxWidth = 400;
+               if ( !overflowStyle ) overflowStyle = 'overflow:auto;';
+               // Remove any old instance:
+               $j( _this.target_container ).find( '#rsd_resource_edit' ).remove();
+
+               // Hide the results container
+               $j( '#rsd_results_container' ).hide();
+
+               var pt = $j( _this.target_container ).html();
+               // Add the edit layout window with loading place holders
+               $j( _this.target_container ).append( 
+                       '<div id="rsd_resource_edit" ' +
+                               'style="position:absolute;top:0px;left:0px;' + 
+                                       'bottom:0px;right:4px;background-color:#FFF;"> ' +
+                       '<div id="clip_edit_ctrl" ' + 
+                               'class="ui-widget ui-widget-content ui-corner-all" ' + 
+                               'style="position:absolute;left:2px;top:5px;bottom:10px;' + 
+                               'width:' + ( maxWidth + 5 ) + 'px;overflow:auto;padding:5px;" >' +
+                       '</div>' +
+                       '<div id="clip_edit_disp" ' +
+                               'class="ui-widget ui-widget-content ui-corner-all"' +
+                               'style="position:absolute;' + overflowStyle + ';' + 
+                               'left:' + ( maxWidth + 20 ) + 'px;right:0px;top:5px;bottom:10px;' + 
+                               'padding:5px;" >' +
+                       mv_get_loading_img( 'position:absolute;top:30px;left:30px' ) +
+                       '</div>' +
+                       '</div>' );
+       },
+
+       getEditWidth: function( resource ) {
+               var mediaType = this.getMediaType( resource );
+               if ( mediaType == 'image' ) {
+                       return resource.image_edit_width;
+               } else {
+                       return resource.video_edit_width;
+               }
+       },
+
+       getMediaType: function( resource ) {
+               if ( resource.mime.indexOf( 'image' ) != -1 ) {
+                       return 'image';
+               } else if ( resource.mime.indexOf( 'audio' ) != -1 ) {
+                       return 'audio';
+               } else {
+                       return 'video';
+               }
+       },
+
+       removeResourceEditor: function() {
+               $j( '#rsd_resource_edit' ).remove();
+               $j( '#rsd_resource_edit' ).css( 'opacity', 0 );
+               $j( '#rsd_edit_img' ).remove();
+       }
+
+       showResourceEditor: function( resource, rsdElement ) {
+               js_log( 'f:showResourceEditor:' + resource.title );
+               var _this = this;
+
+               // Remove any existing resource edit interface
+               _this.removeResourceEditor();
+
+               var mediaType = _this.getMediaType( resource );
+               var maxWidth = _this.getEditWidth( resource );
+
+               // So that transcripts show on top
+               var overflow_style = ( mediaType == 'video' ) ? '' : 'overflow:auto;';
+               // Append to the top level of model window:
+               _this.addResourceEditLoader( maxWidth, overflow_style );
+               // update add media wizard title:
+               var dialogTitle = gM( 'mwe-add_media_wizard' ) + ': ' + 
+                       gM( 'rsd_resource_edit', resource.title );
+               $j( _this.target_container ).dialog( 'option', 'title', dialogTitle );
+               js_log( 'did append to: ' + _this.target_container );
+
+               // Left side holds the image right size the controls /
+               $j( rsdElement )
+                       .clone()
+                       .attr( 'id', 'rsd_edit_img' )
+                       .appendTo( '#clip_edit_disp' )
+                       .css( {
+                               'position':'absolute',
+                               'top':'40%',
+                               'left':'20%',
+                               'cursor':'default',
+                               'opacity':0
+                       } );
+
+               // Try and keep aspect ratio for the thumbnail that we clicked:
+               var tRatio = $j( rsdElement ).height() / $j( rsdElement ).width();
+
+               if ( !tRatio ) {
+                       var tRatio = 1; // set ratio to 1 if tRatio did not work.
+               }
+               js_log( 'Set from ' +  tRatio + ' to init thumbimage to ' + 
+                       maxWidth + ' x ' + parseInt( tRatio * maxWidth ) );
+               // Scale up image and to swap with high res version
+               $j( '#rsd_edit_img' ).animate( 
+                       {
+                               'opacity': 1,
+                               'top': '5px',
+                               'left': '5px',
+                               'width': maxWidth + 'px',
+                               'height': parseInt( tRatio * maxWidth )  + 'px'
+                       }, 
+                       "slow" ); // Do it slow to give it a chance to finish loading the high quality version
+
+               if ( mediaType == 'image' ) {
+                       _this.loadHighQualityImage( 
+                               resource, 
+                               { 'width': maxWidth }, 
+                               'rsd_edit_img', 
+                               function() {
+                                       $j( '.mv_loading_img' ).remove();
+                               }
+                       );
+               }
+               // Also fade in the container:
+               $j( '#rsd_resource_edit' ).animate( {
+                       'opacity': 1,
+                       'background-color': '#FFF',
+                       'z-index': 99
+               } );
+
+               // Show the editor itself
+               if ( mediaType == 'image' ) {
+                       _this.showImageEditor( resource );
+               } else if ( mediaType == 'video' || mediaType == 'audio' ) {
+                       _this.showVideoEditor( resource );
+               }
+       },
+
+       loadHighQualityImage: function( resource, size, target_img_id, callback ) {
+               // Get the high quality image url:
+               resource.pSobj.getImageObj( resource, size, function( imObj ) {
+                       resource['edit_url'] = imObj.url;
+
+                       js_log( "edit url: " + resource.edit_url );
+                       // Update the resource
+                       resource['width'] = imObj.width;
+                       resource['height'] = imObj.height;
+
+                       // See if we need to animate some transition
+                       if ( size.width != imObj.width ) {
+                               js_log( 'loadHighQualityImage:size mismatch: ' + size.width + ' != ' + imObj.width );
+                               // Set the target id to the new size:
+                               $j( '#' + target_img_id ).animate( {
+                                       'width': imObj.width + 'px',
+                                       'height': imObj.height + 'px'
+                               });
+                       } else {
+                               js_log( 'using req size: ' + imObj.width + 'x' + imObj.height );
+                               $j( '#' + target_img_id ).animate( {
+                                       'width': imObj.width + 'px', 
+                                       'height': imObj.height + 'px' 
+                               });
+                       }
+                       // Don't swap it in until its loaded:
+                       var img = new Image();
+                       // Load the image image:
+                       $j( img ).load( function () {
+                                        $j( '#' + target_img_id ).attr( 'src', resource.edit_url );
+                                        // Let the caller know we are done and what size we ended up with:
+                                        callback();
+                               } ).error( function () {
+                                       js_log( "Error with:  " +  resource.edit_url );
+                               } ).attr( 'src', resource.edit_url );
+               } );
+       },
+
+       onCancelClipEdit: function() {
+               var _this = this;
+               js_log( 'onCancelClipEdit' );
+               var b_target = _this.target_container + '~ .ui-dialog-buttonpane';
+               $j( '#rsd_resource_edit' ).remove();
+               // Remove preview if its 'on'
+               $j( '#rsd_preview_display' ).remove();
+               // Restore the resource container:
+               $j( '#rsd_results_container' ).show();
+
+               // Restore the title:
+               $j( _this.target_container ).dialog( 'option', 'title', gM( 'mwe-add_media_wizard' ) );
+               js_log( "should update: " + b_target + ' with: cancel' );
+               // Restore the buttons:
+               $j( b_target )
+                       .html( $j.btnHtml( gM( 'mwe-cancel' ) , 'mv_cancel_rsd', 'close' ) )
+                       .children( '.mv_cancel_rsd' )
+                       .btnBind()
+                       .click( function() {
+                               $j( _this.target_container ).dialog( 'close' );
+                       } );
+       },
+
+       /** 
+        *  Get the control actions for clipEdit with relevant callbacks
+        */
+       getClipEditControlActions: function( provider ) {
+               var _this = this;
+               var actions = { };
+
+               actions['insert'] = function( resource ) {
+                       _this.insertResource( resource );
+               }
+               // If not directly inserting the resource is support a preview option:
+               if ( _this.import_url_mode != 'remote_link' ) {
+                       actions['preview'] = function( resource ) {
+                               _this.showPreview( resource )
+                       };
+               }
+               actions['cancel'] = function() {
+                       _this.onCancelClipEdit()
+               }
+               return actions;
+       },
+
+       getClipEditOptions: function( resource ) {
+               return {
+                       'rObj': resource,
+                       'parent_ct': 'rsd_modal_target',
+                       'clip_disp_ct': 'clip_edit_disp',
+                       'control_ct': 'clip_edit_ctrl',
+                       'media_type': this.getMediaType( resource ),
+                       'p_rsdObj': this,
+                       'controlActionsCb': this.getClipEditControlActions( resource.pSobj.cp ),
+                       'enabled_tools': this.enabled_tools
+               };
+       },
+
+       /**
+        * Internal function called by showResourceEditor() to show an image editor
+        */
+       showImageEditor: function( resource ) {
+               var _this = this;
+               var options = _this.getClipEditOptions( resource );
+               // Display the mvClipEdit obj once we are done loading:
+               mvJsLoader.doLoad( clibs, function() {
+                       // Run the image clip tools
+                       _this.clipEdit = new mvClipEdit( options );
+               } );
+       },
+
+       /**
+        * Internal function called by showResourceEditor() to show a video or audio
+        * editor.
+        */
+       showVideoEditor: function( resource ) {
+               var _this = this;
+               var options = _this.getClipEditOptions( resource );
+               var mediaType = this.getMediaType( resource );
+
+               js_log( 'media type:: ' + mediaType );
+               // Get any additional embedding helper meta data prior to doing the actual embed
+               // normally this meta should be provided in the search result 
+               // (but archive.org has another query for more media meta)
+               resource.pSobj.addResourceInfoCallback( resource, function() {
+                       // Make sure we have the embedVideo libs:
+                       var runFlag = false;
+                       mvJsLoader.embedVideoCheck( function() {
+                               // Strange concurrency issue with callbacks
+                               // @@todo try and figure out why this callback is fired twice
+                               if ( !runFlag ) {
+                                       runFlag = true;
+                               } else {
+                                       js_log( 'Error: embedVideoCheck run twice' );
+                                       return false;
+                               }
+                               var embedHtml = resource.pSobj.getEmbedHTML( resource, 
+                                       { id : 'embed_vid' } );
+                               js_log( 'append html: ' + embedHtml );
+                               $j( '#clip_edit_disp' ).html( embedHtml );
+                               js_log( "about to call rewrite_by_id::embed_vid" );
+                               // Rewrite by id
+                               rewrite_by_id( 'embed_vid', function() {
+                                       // Grab information avaliable from the embed instance
+                                       resource.pSobj.addResourceInfoFromEmbedInstance( resource, 'embed_vid' );
+
+                                       // Add the re-sizable to the doLoad request:
+                                       clibs.push( '$j.ui.resizable' );
+                                       clibs.push( '$j.fn.hoverIntent' );
+                                       mvJsLoader.doLoad( clibs, function() {
+                                               // Make sure the rsd_edit_img is removed:
+                                               $j( '#rsd_edit_img' ).remove();
+                                               // Run the image clip tools
+                                               _this.clipEdit = new mvClipEdit( options );
+                                       } );
+                               } );
+                       } );
+               } );
+       },
+
+       isProviderLocal: function( provider ) {
+               if ( provider.local ) {
+                       return true;
+               } else {
+                       // Check if we can embed the content locally per a domain name check:
+                       var localHost = mw.parseUri( this.local_wiki_api_url ).host;
+                       if ( provider.local_domains ) {
+                               for ( var i = 0; i < provider.local_domains.length; i++ ) {
+                                       var domain = provider.local_domains[i];
+                                       if ( localHost.indexOf( domain ) != -1 )
+                                               return true;
+                               }
+                       }
+                       return false;
+               }
+       },
+
+       /**
+        * Check if the file is either a local upload, or if it has already been 
+        * imported under the standard filename scheme. 
+        *
+        * Calls the callback with two parameters:
+        *     callback( resource, status )
+        *
+        * resource: a resource object pointing to the local file if there is one,
+        *    or false if not
+        *
+        * status: may be 'local', 'shared', 'imported' or 'missing'
+        */
+       isFileLocallyAvailable: function( resource, callback ) {
+               var _this = this;
+               // Add a loader on top
+               $j.addLoaderDialog( gM( 'mwe-checking-resource' ) );
+
+               // Extend the callback, closing the loader dialog before chaining
+               myCallback = function( newRes, status ) {
+                       $j.closeLoaderDialog();
+                       if ( typeof callback == 'function' ) {
+                               callback( newRes, status );
+                       }
+               }
+
+               // @@todo get the localized File/Image namespace name or do a general {NS}:Title
+               var provider = resource.pSobj.cp;
+               var _this = this;
+
+               // Clone the resource
+               var proto = {};
+               proto.prototype = resource;
+               var myRes = new proto;
+
+               // Update base target_resource_title:
+               myRes.target_resource_title = myRes.titleKey.replace( /^(File:|Image:)/ , '' )
+
+               // check if local repository
+               // or if import mode if just "linking" (we should already have the 'url'
+
+               if ( this.isProviderLocal( provider ) || this.import_url_mode == 'remote_link' ) {
+                       // Local repo, jump directly to the callback:
+                       myCallback( myRes, 'local' );
+               } else {
+                       // Check if the file is local (can be shared repo)
+                       if ( provider.check_shared ) {
+                               _this.findFileInLocalWiki( myRes.target_resource_title, function( imagePage ) {
+                                       if ( imagePage && imagePage['imagerepository'] == 'shared' ) {
+                                               myCallback( myRes, 'shared' );
+                                       } else {
+                                               _this.isFileAlreadyImported( myRes, myCallback );
+                                       }
+                               } );
+                       } else {
+                               _this.isFileAlreadyImported( myRes, myCallback );
+                       }
+               }
+       },
+
+       /**
+        * Check if the file is already imported with this extension's filename scheme
+        *
+        * Calls the callback with two parameters:
+        *     callback( resource, status )
+        *
+        * If the image is found, the status will be 'imported' and the resource
+        * will be the new local resource.
+        *
+        * If the image is not found, the status  will be 'missing' and the resource 
+        * will be false.
+        */
+       isFileAlreadyImported: function( resource, callback ) {
+               js_log( '::isFileAlreadyImported:: ' );
+               var _this = this;
+
+               // Clone the resource
+               var proto = {};
+               proto.prototype = resource;
+               var myRes = new proto;
+
+               var provider = myRes.pSobj.cp;
+
+               // update target_resource_title with resource repository prefix:
+               myRes.target_resource_title = provider.resource_prefix + myRes.target_resource_title;
+               // check if the file exists:
+               _this.findFileInLocalWiki( myRes.target_resource_title, function( imagePage ) {
+                       if ( imagePage ) {
+                               // update to local src
+                               myRes.local_src = imagePage['imageinfo'][0].url;
+                               // @@todo maybe  update poster too?
+                               myRes.local_poster = imagePage['imageinfo'][0].thumburl;
+                               // update the title:
+                               myRes.target_resource_title = imagePage.title.replace(/^(File:|Image:)/ , '' );
+                               callback( myRes, 'imported' );
+                       } else {
+                               callback( false, 'missing' );
+                       }
+               } );
+       },
+
+       showImportUI: function( resource, callback ) {
+               var _this = this;
+               js_log( "showImportUI:: update:" + _this.cFileNS + ':' + 
+                       resource.target_resource_title );
+
+               // setup the resource description from resource description:
+               // FIXME: i18n, namespace
+               var desc = '{{Information ' + "\n";
+
+               if ( resource.desc ) {
+                       desc += '|Description= ' + resource.desc + "\n";
+               } else {
+                       desc += '|Description= ' + gM( 'mwe-missing_desc_see_source', resource.link ) + "\n";
+               }
+
+               // output search specific info
+               desc += '|Source=' + resource.pSobj.getImportResourceDescWiki( resource ) + "\n";
+
+               if ( resource.author )
+                       desc += '|Author=' + resource.author + "\n";
+
+               if ( resource.date )
+                       desc += '|Date=' + resource.date + "\n";
+
+               // add the Permision info:
+               desc += '|Permission=' + resource.pSobj.getPermissionWikiTag( resource ) + "\n";
+
+               if ( resource.other_versions )
+                       desc += '|other_versions=' + resource.other_versions + "\n";
+
+               desc += '}}';
+
+               // get any extra categories or helpful links
+               desc += resource.pSobj.getExtraResourceDescWiki( resource );
+
+
+               $j( '#rsd_resource_import' ).remove();// remove any old resource imports
+
+               // @@ show user dialog to import the resource
+               $j( _this.target_container ).append( 
+                       '<div id="rsd_resource_import" ' +
+                               'class="ui-widget-content" ' +
+                               'style="position:absolute;top:0px;left:0px;right:0px;bottom:0px;z-index:5">' +
+                       '<h3 style="color:red;padding:5px;">' + 
+                       gM( 'mwe-resource-needs-import', [resource.title, _this.upload_api_name] ) + 
+                       '</h3>' +
+                       '<div id="rsd_preview_import_container" ' + 
+                               'style="position:absolute;width:50%;bottom:0px;left:5px;' + 
+                                       'overflow:auto;top:30px;">' +
+                       resource.pSobj.getEmbedHTML( resource, {
+                               'id': _this.target_container + '_rsd_pv_vid',
+                               'max_height': '220',
+                               'only_poster': true
+                       } ) + // get embedHTML with small thumb:
+                       '<br style="clear both"/>' +
+                       '<strong>' + gM( 'mwe-resource_page_desc' ) + '</strong>' +
+                       '<div id="rsd_import_desc" style="display:inline;">' +
+                       mv_get_loading_img( 'position:absolute;top:5px;left:5px' ) +
+                       '</div>' +
+                       '</div>' +
+                       '<div id="rds_edit_import_container" ' + 
+                               'style="position:absolute; ' + 
+                               'left:50%;bottom:0px;top:30px;right:0px;overflow:auto;">' +
+                       '<strong>' + gM( 'mwe-local_resource_title' ) + '</strong>' + 
+                       // FIXME: invalid HTML, <br> must be empty
+                       '<br/>' +
+                       '<input type="text" size="30" value="' + resource.target_resource_title + '" />' + 
+                       '<br/>' +
+                       '<strong>' + gM( 'mwe-edit_resource_desc' ) + '</strong>' +
+                       // FIXME: invalid HTML, two id attributes
+                       '<textarea id="rsd_import_ta" id="mv_img_desc" ' + 
+                               'style="width:90%;" rows="8" cols="50">' +
+                       desc +
+                       '</textarea>' + 
+                       '<br/>' +
+                       '<input type="checkbox" value="true" id="wpWatchthis" ' + 
+                               'name="wpWatchthis" tabindex="7" />' +
+                       '<label for="wpWatchthis">' + gM( 'mwe-watch_this_page' ) + '</label> ' + 
+                       '<br/><br/><br/>' +
+                       $j.btnHtml( gM( 'mwe-update_preview' ), 'rsd_import_apreview', 'refresh' ) + 
+                       ' ' +
+                       '</div>' +
+                       // output the rendered and non-rendered version of description for easy switching:
+                       '</div>' );
+               var buttonPaneSelector = _this.target_container + '~ .ui-dialog-buttonpane';
+               $j( buttonPaneSelector ).html (
+                       // add the btns to the bottom:
+                       $j.btnHtml( gM( 'mwe-do_import_resource' ), 'rsd_import_doimport', 'check' ) + 
+                       ' ' +
+                       $j.btnHtml( gM( 'mwe-cancel_import' ), 'rsd_import_acancel', 'close' ) + ' '
+               );
+
+               // add hover:
+
+               // update video tag (if a video)
+               if ( resource.mime.indexOf( 'video/' ) !== -1 )
+                       rewrite_by_id( $j( _this.target_container ).attr( 'id' ) + '_rsd_pv_vid' );
+
+               // load the preview text:
+               _this.parse(
+                       desc, _this.cFileNS + ':' + resource.target_resource_title, 
+                       function( descHtml ) {
+                               $j( '#rsd_import_desc' ).html( descHtml );
+                       } 
+               );
+               // add bindings:
+               $j( _this.target_container + ' .rsd_import_apreview' )
+                       .btnBind()
+                       .click( function() {
+                               js_log( " Do preview asset update" );
+                               $j( '#rsd_import_desc' ).html( mv_get_loading_img() );
+                               // load the preview text:
+                               _this.parse( 
+                                       $j( '#rsd_import_ta' ).val(), 
+                                       _this.cFileNS + ':' + resource.target_resource_title, 
+                                       function( o ) {
+                                               js_log( 'got updated preview: ' );
+                                               $j( '#rsd_import_desc' ).html( o );
+                                       } 
+                               );
+                       } );
+
+               $j( buttonPaneSelector + ' .rsd_import_doimport' )
+                       .btnBind()
+                       .click( function() {
+                               js_log( "do import asset:" + _this.import_url_mode );
+                               // check import mode:
+                               if ( _this.import_url_mode == 'api' ) {
+                                       if ( _this.upload_api_target == 'proxy' ) {
+                                               _this.setupProxy( function() {
+                                                       _this.doApiImport( resource, callback );
+                                               } );
+                                       } else {
+                                               _this.doApiImport( resource, callback );
+                                       }
+                               } else {
+                                       js_log( "Error: import mode is not form or API (can not copy asset)" );
+                               }
+                       } );
+               $j( buttonPaneSelector + ' .rsd_import_acancel' )
+                       .btnBind()
+                       .click( function() {
+                               $j( '#rsd_resource_import' ).fadeOut( "fast", function() {
+                                       $j( this ).remove();
+                                       // restore buttons (from the clipEdit object::)
+                                       _this.clipEdit.updateInsertControlActions();
+                                       $j( buttonPaneSelector ).removeClass( 'ui-state-error' );
+                               } );
+                       } );
+       },
+
+       /**
+        * Sets up the proxy for the remote inserts
+        */
+       setupProxy: function( callback ) {
+               var _this = this;
+
+               if ( _this.proxySetupDone ) {
+                       if ( callback )
+                               callback();
+                       return;
+               }
+               // setup the the proxy via  $j.apiProxy loader:
+               if ( !_this.upload_api_proxy_frame ) {
+                       js_log( "Error:: remote api but no proxy frame target" );
+                       return false;
+               } else {
+                       $j.apiProxy(
+                               'client',
+                               {
+                                       'server_frame': _this.upload_api_proxy_frame
+                               }, function() {
+                                       _this.proxySetupDone = true
+                                       if ( callback )
+                                               callback();
+                               }
+                       );
+               }
+       },
+
+       findFileInLocalWiki: function( fName, callback ) {
+               js_log( "findFileInLocalWiki::" + fName );
+               var _this = this;
+               reqObj = {
+                       'action': 'query',
+                       'titles': _this.cFileNS + ':' + fName,
+                       'prop': 'imageinfo',
+                       'iiprop': 'url',
+                       'iiurlwidth': '400'
+               };
+               // first check the api for imagerepository
+               do_api_req( 
+                       {
+                               'data': reqObj,
+                               'url': this.local_wiki_api_url
+                       }, function( data ) {
+                               if ( data.query.pages ) {
+                                       for ( var i in data.query.pages ) {
+                                               for ( var j in data.query.pages[i] ) {
+                                                       if ( j == 'missing' 
+                                                               && data.query.pages[i].imagerepository != 'shared' ) 
+                                                       {
+                                                               js_log( fName + " not found" );
+                                                               callback( false );
+                                                               return;
+                                                       }
+                                               }
+                                               // else page is found:
+                                               js_log( fName + "  found" );
+                                               callback( data.query.pages[i] );
+                                       }
+                               }
+                       }
+               );
+       },
+
+       doApiImport: function( resource, callback ) {
+               var _this = this;
+               js_log( ":doApiImport:" );
+               $j.addLoaderDialog( gM( 'mwe-importing_asset' ) );
+               // baseUploadInterface
+               mvJsLoader.doLoad( 
+                       [
+                               'mvBaseUploadInterface',
+                               '$j.ui.progressbar'
+                       ], 
+                       function() {
+                               js_log( 'mvBaseUploadInterface ready' );
+                               // initiate a upload object ( similar to url copy ):
+                               var uploader = new mvBaseUploadInterface( {
+                                       'api_url' : _this.upload_api_target,
+                                       'done_upload_cb':function() {
+                                               js_log( 'doApiImport:: run callback::' );
+                                               // we have finished the upload:
+
+                                               // close up the rsd_resource_import
+                                               $j( '#rsd_resource_import' ).remove();
+                                               // return the parent callback:
+                                               return callback();
+                                       }
+                               } );
+                               // get the edit token if we have it handy
+                               _this.getEditToken( function( token ) {
+                                       uploader.editToken = token;
+
+                                       // close the loader now that we are ready to present the progress dialog::
+                                       $j.closeLoaderDialog();
+
+                                       uploader.doHttpUpload( {
+                                               'url': resource.src,
+                                               'filename': resource.target_resource_title,
+                                               'comment': $j( '#rsd_import_ta' ).val()
+                                       } );
+                               } )
+                       }
+               );
+       },
+
+       getEditToken: function( callback ) {
+               var _this = this;
+               if ( _this.upload_api_target != 'proxy' ) {
+                       // (if not a proxy) first try to get the token from the page:
+                       var editToken = $j( "input[name='wpEditToken']" ).val();
+                       if ( editToken ) {
+                               callback( editToken );
+                               return;
+                       }
+               }
+               // @@todo try to load over ajax if( _this.local_wiki_api_url ) is set
+               // (your on the api domain but are inserting from a normal page view)
+               get_mw_token( null, _this.upload_api_target, function( token ) {
+                       callback( token );
+               } );
+       },
+
+       showPreview: function( resource ) {
+               var _this = this;
+               this.isFileLocallyAvailable( resource, function( newRes, status ) {
+                       if ( status === 'missing' ) {
+                               _this.showImportUI( resource, callback );
+                               return;
+                       }
+
+                       // put another window ontop:
+                       $j( _this.target_container ).append( 
+                               '<div id="rsd_preview_display"' +
+                                       'style="position:absolute;overflow:hidden;z-index:4;' + 
+                                       'top:0px;bottom:0px;right:0px;left:0px;background-color:#FFF;">' +
+                               mv_get_loading_img( 'top:30px;left:30px' ) +
+                               '</div>' );
+
+                       var buttonPaneSelector = _this.target_container + '~ .ui-dialog-buttonpane';
+                       var origTitle = $j( _this.target_container ).dialog( 'option', 'title' );
+
+                       // update title:
+                       $j( _this.target_container ).dialog( 'option', 'title', 
+                               gM( 'mwe-preview_insert_resource', newRes.title ) );
+
+                       // update buttons preview:
+                       $j( buttonPaneSelector )
+                               .html(
+                                       $j.btnHtml( gM( 'rsd_do_insert' ), 'preview_do_insert', 'check' ) + ' ' )
+                               .children( '.preview_do_insert' )
+                               .click( function() {
+                                       _this.insertResource( newRes );
+                               } );
+                       // update cancel button
+                       $j( buttonPaneSelector )
+                               .append( '<a href="#" class="preview_close">Do More Modification</a>' )
+                               .children( '.preview_close' )
+                               .click( function() {
+                                       $j( '#rsd_preview_display' ).remove();
+                                       // restore title:
+                                       $j( _this.target_container ).dialog( 'option', 'title', origTitle );
+                                       // restore buttons (from the clipEdit object::)
+                                       _this.clipEdit.updateInsertControlActions();
+                               } );
+
+                       // Get the preview wikitext
+                       _this.parse( 
+                               _this.getPreviewText( newRes ),
+                               _this.target_title,
+                               function( phtml ) {
+                                       $j( '#rsd_preview_display' ).html( phtml );
+                                       // update the display of video tag items (if any)
+                                       mwdomReady( true );
+                               }
+                       );
+               } );
+       },
+
+       getEmbedCode: function( resource ) {
+               if ( this.import_url_mode == 'remote_link' ) {
+                       return resource.pSobj.getEmbedHTML( resource );
+               } else {
+                       return resource.pSobj.getEmbedWikiCode( resource );
+               }
+       },
+
+       getPreviewText: function( resource ) {
+               var _this = this;
+               var text;
+
+               // insert at start if textInput cursor has not been set (ie == length)
+               var insertPos = _this.getCaretPos();
+               var originalText = _this.getTextboxValue();
+               var embedCode = _this.getEmbedCode( resource );
+               if ( insertPos !== false && originalText ) {
+                       if ( originalText.length == insertPos ) {
+                               insertPos = 0;
+                       }
+                       text = originalText.substring( 0, insertPos ) +
+                               embedCode + originalText.substring( insertPos );
+               } else {
+                       text = $j( _this.target_textbox ).val() + embedCode;
+               }
+               // check for missing </references>
+               if ( text.indexOf( '<references/>' ) == -1 && text.indexOf( '<ref>' ) != -1 ) {
+                       text = text + '<references/>';
+               }
+               return text;
+       },
+
+       parse: function( wikitext, title, callback ) {
+               do_api_req( 
+                       {
+                               'data': {
+                                       'action': 'parse',
+                                       'text': wikitext
+                               },
+                               'url': this.local_wiki_api_url
+                       }, function( data ) {
+                               callback( data.parse.text['*'] );
+                       }
+               );
+       },
+
+       insertResource: function( resource ) {
+               js_log( 'insertResource: ' + resource.title );
+
+               var _this = this;
+               // double check that the resource is present:
+               this.isFileLocallyAvailable( resource, function( newRes, status ) {
+                       if ( status === 'missing' ) {
+                               _this.showImportUI( resource, callback );
+                               return;
+                       }
+                       
+                       $j( _this.target_textbox ).val( _this.getPreviewText( newRes ) );
+                       _this.clearTextboxCache();
+
+                       // update the render area (if present)
+                       var embedCode = _this.getEmbedCode( newRes );
+                       if ( _this.target_render_area && embedCode ) {
+                               // output with some padding:
+                               $j( _this.target_render_area )
+                                       .append( embedCode + '<div style="clear:both;height:10px">' )
+
+                               // update the player if video or audio:
+                               if ( newRes.mime.indexOf( 'audio' ) != -1 ||
+                                       newRes.mime.indexOf( 'video' ) != -1 ||
+                                       newRes.mime.indexOf( '/ogg' ) != -1 ) 
+                               {
+                                       mvJsLoader.embedVideoCheck( function() {
+                                               mv_video_embed();
+                                       } );
+                               }
+                       }
+                       _this.closeAll();
+               } );
+       },
+
+       closeAll: function() {
+               var _this = this;
+               js_log( "close all:: "  + _this.target_container );
+               _this.onCancelClipEdit();
+               // Give a chance for the events to complete
+               // (somehow at least in firefox a rare condition occurs where
+               // the modal of the edit-box stick around even after the
+               // close request has been issued. )
+               setTimeout( 
+                       function() {
+                               $j( _this.target_container ).dialog( 'close' );
+                       }, 10 
+               );
+       },
+
+       showResultsHeader: function() {
+               var _this = this;
+               var darkBoxUrl = mv_skin_img_path + 'box_layout_icon_dark.png';
+               var lightBoxUrl = mv_skin_img_path + 'box_layout_icon.png';
+               var darkListUrl = mv_skin_img_path + 'list_layout_icon_dark.png';
+               var lightListUrl = mv_skin_img_path + 'list_layout_icon.png';
+
+               if ( !this.content_providers[ this.currentProvider ] ) {
+                       return;
+               }
+               var cp = this.content_providers[this.currentProvider];
+               var resultsFromMsg = gM( 'mwe-results_from', 
+                       [ cp.homepage, gM( 'rsd-' + this.currentProvider + '-title' ) ] );
+               var defaultBoxUrl, defaultListUrl;
+               if ( _this.displayMode == 'box' ) {
+                       defaultBoxUrl = darkBoxUrl;
+                       defaultListUrl = lightListUrl;
+               } else {
+                       defaultBoxUrl = lightBoxUrl;
+                       defaultListUrl = darkListUrl;
+               }
+
+               var about_desc = '<span style="position:relative;top:0px;font-style:italic;">' +
+                       '<i>' + resultsFromMsg + '</i></span>';
+
+               $j( '#tab-' + this.currentProvider ).append( '<div id="rds_results_bar">' +
+                       '<span style="float:left;top:0px;font-style:italic;">' +
+                       gM( 'rsd_layout' ) + ' ' +
+                       '<img id="msc_box_layout" ' +
+                               'title = "' + gM( 'rsd_box_layout' ) + '" ' +
+                               'src = "' +  defaultBoxUrl + '" ' +
+                               'style="width:20px;height:20px;cursor:pointer;"> ' +
+                       '<img id="msc_list_layout" ' +
+                               'title = "' + gM( 'rsd_list_layout' ) + '" ' +
+                               'src = "' +  defaultListUrl + '" ' +
+                               'style="width:20px;height:20px;cursor:pointer;">' +
+                       about_desc +
+                       '</span>' +
+                       '<span id="rsd_paging_ctrl" style="float:right;"></span>' +
+                       '</div>'
+               );
+
+               // Get paging with bindings:
+               this.showPagingHeader( '#rsd_paging_ctrl' );
+
+               $j( '#msc_box_layout' )
+                       .hover( 
+                               function() {
+                                       $j( this ).attr( "src", darkBoxUrl );
+                               }, 
+                               function() {
+                                       $j( this ).attr( "src",  defaultBoxUrl );
+                               } )
+                       .click( function() {
+                               $j( this ).attr( "src", darkBoxUrl );
+                               $j( '#msc_list_layout' ).attr( "src", lightListUrl );
+                               _this.setDisplayMode( 'box' );
+                       } );
+
+               $j( '#msc_list_layout' )
+                       .hover( 
+                               function() {
+                                       $j( this ).attr( "src", darkListUrl );
+                               }, 
+                               function() {
+                                       $j( this ).attr( "src", defaultListUrl );
+                               } )
+                       .click( function() {
+                               $j( this ).attr( "src", darkListUrl );
+                               $j( '#msc_box_layout' ).attr( "src", lightBoxUrl );
+                               _this.setDisplayMode( 'list' );
+                       } );
+       },
+
+       showPagingHeader: function( target ) {
+               var _this = this;
+               if ( _this.currentProvider == 'upload' ) {
+                       var provider = _this.content_providers['this_wiki'];
+               } else {
+                       var provider = _this.content_providers[ _this.currentProvider ];
+               }
+               var search = provider.sObj;
+               js_log( 'showPagingHeader:' + _this.currentProvider + ' len: ' + search.num_results );
+               var to_num = ( provider.limit > search.num_results ) ?
+                       ( parseInt( provider.offset ) + parseInt( search.num_results ) ) :
+                       ( parseInt( provider.offset ) + parseInt( provider.limit ) );
+               var out = '';
+
+               // @@todo we should instead support the wiki number format template system instead of inline calls
+               if ( search.num_results != 0 ) {
+                       if ( search.num_results  >  provider.limit ) {
+                               out += gM( 'rsd_results_desc_total', [( provider.offset + 1 ), to_num, 
+                                       mw.lang.formatNumber( search.num_results )] );
+                       } else {
+                               out += gM( 'rsd_results_desc', [( provider.offset + 1 ), to_num] );
+                       }
+               }
+               // check if we have more results (next prev link)
+               if ( provider.offset >= provider.limit ) {
+                       out += ' <a href="#" id="rsd_pprev">' + gM( 'rsd_results_prev' ) + ' ' + provider.limit + '</a>';
+               }
+
+               if ( search.more_results ) {
+                       out += ' <a href="#" id="rsd_pnext">' + gM( 'rsd_results_next' ) + ' ' + provider.limit + '</a>';
+               }
+
+               $j( target ).html( out );
+
+               // set bindings
+               $j( '#rsd_pnext' ).click( function() {
+                       provider.offset += provider.limit;
+                       _this.showCurrentTab();
+               } );
+
+               $j( '#rsd_pprev' ).click( function() {
+                       provider.offset -= provider.limit;
+                       if ( provider.offset < 0 )
+                               provider.offset = 0;
+                       _this.showCurrentTab();
+               } );
+       },
+
+       selectTab: function( provider ) {
+               js_log( 'select tab: ' + provider );
+               this.currentProvider = provider;
+               if ( this.currentProvider == 'upload' ) {
+                       this.showUploadTab();
+               } else {
+                       // update the search results:
+                       this.showCurrentTab();
+               }
+       },
+
+       setDisplayMode: function( mode ) {
+               js_log( 'setDisplayMode:' + mode );
+               this.displayMode = mode;
+               // run /update search display:
+               this.showResults();
+       }
+};
diff --git a/js2/mwEmbed/libAddMedia/searchLibs/archiveOrgSearch.js b/js2/mwEmbed/libAddMedia/searchLibs/archiveOrgSearch.js
new file mode 100644 (file)
index 0000000..b0d7e7b
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+* Archive.org Search
+* 
+* archive.org uses the solr engine: 
+* more about solr here:  
+* http://lucene.apache.org/solr/
+*/
+
+var archiveOrgSearch = function ( iObj ) {
+       return this.init( iObj );
+}
+archiveOrgSearch.prototype = {
+       // Archive.org constants: 
+       downloadUrl : 'http://www.archive.org/download/',
+       detailsUrl : 'http://www.archive.org/details/',
+       /*
+       * Inititalize the archiveOrgSearch class.
+       * archiveOrgSearch inherits the baseSearch class 
+       */
+       init:function( options ) {              
+               var baseSearch = new baseRemoteSearch( options );
+               for ( var i in baseSearch ) {
+                       if ( typeof this[i] == 'undefined' ) {
+                               this[i] = baseSearch[i];
+                       } else {
+                               this['parent_' + i] =  baseSearch[i];
+                       }
+               }
+       },
+       /**
+       * Gets the search results from the api query
+       */
+       getSearchResults:function() {
+               // call parent: 
+               this.parent_getSearchResults();
+               var _this = this;
+               js_log( 'f:getSearchResults for:' + $j( '#rsd_q' ).val() );
+               // build the query var
+               var q = $j( '#rsd_q' ).val();
+               // @@todo check advanced options: include audio and images media types
+               // for now force (Ogg video) & url based license
+               q += ' format:(Ogg video)';
+               q += ' licenseurl:(http\\:\\/\\/*)';
+               var reqObj = {
+                       'q': q, // just search for video atm
+                       'fl':"description,title,identifier,licenseurl,format,license,thumbnail",
+                       'wt':'json',
+                       'rows' : this.cp.limit,
+                       'start' : this.cp.offset
+               }
+               do_api_req( {
+                       'data':reqObj,
+                       'url':this.cp.api_url,
+                       'jsonCB':'json.wrf'
+                       }, function( data ) {
+                               _this.addResults( data );
+                               _this.loading = false;
+                       }
+               );
+       },
+       /**
+       * Adds the search results to the local resultsObj
+       */
+       addResults:function( data ) {
+               var _this = this;
+               if ( data.response && data.response.docs ) {
+                       // Set result info: 
+                       this.num_results = data.response.numFound;
+               
+                       for ( var resource_id in data.response.docs ) {
+                               var resource = data.response.docs[resource_id];
+                               var rObj = {
+                                       // @@todo we should add .ogv or oga if video or audio:
+                                       'titleKey'       :  resource.identifier + '.ogg',
+                                       'resourceKey':  resource.identifier,
+                                       'link'           : _this.detailsUrl + resource.identifier,
+                                       'title'          : resource.title,
+                                       'poster'         : _this.downloadUrl + resource.identifier + '/format=thumbnail',
+                                       'poster_ani' : _this.downloadUrl + resource.identifier + '/format=Animated+Gif',
+                                       'thumbwidth' : 160,
+                                       'thumbheight': 110,
+                                       'desc'           : resource.description,
+                                       'src'            : _this.downloadUrl + resource.identifier + '/format=Ogg+video',
+                                       'mime'           : 'application/ogg',
+                                       // Set the license: (rsd is a pointer to the parent remoteSearchDriver )                 
+                                       'license'        : this.rsd.getLicenseFromUrl( resource.licenseurl ),
+                                       'pSobj'          :_this
+                                       
+                               };
+                               this.resultsObj[ resource_id ] = rObj;
+                       }
+               }
+       },
+       /**
+       * Gets some media metadata via a archive.org special entry point "avinfo"
+       */ 
+       addResourceInfoCallback:function( rObj, callback ) {
+               var _this = this;
+               do_api_req( {
+                       'data': { 'avinfo' : 1 },
+                       'url':_this.downloadUrl + rObj.resourceKey + '/format=Ogg+video'
+               }, function( data ) {
+                       if ( data['length'] )
+                               rObj.duration = data['length'];
+                       if ( data['width'] )
+                               rObj.width = data['width'];
+                       if ( data['height'] )
+                               rObj.height = data['height'];
+                                                                  
+                       callback();
+               } );
+       },
+       /*
+       * Returns html to embed a given result Object ( rObj ) 
+       */      
+       getEmbedHTML: function( rObj , options ) {
+               js_log( 'getEmbedHTML:: ' + rObj.poster );
+               if ( !options )
+                       options = { };
+               var id_attr = ( options['id'] ) ? ' id = "' + options['id'] + '" ': '';
+               if ( rObj.duration ) {
+                       var src = rObj.src + '?t=0:0:0/' + seconds2npt( rObj.duration );
+               } else {
+                       var src = rObj.src;
+               }
+               if ( rObj.mime == 'application/ogg' || rObj.mime == 'audio/ogg' || rObj.mime == 'video/ogg' ) {
+                       return '<video ' + id_attr + ' src="' + src + '" poster="' + rObj.poster + '" type="video/ogg"></video>';
+               }
+       }
+}
diff --git a/js2/mwEmbed/libAddMedia/searchLibs/baseRemoteSearch.js b/js2/mwEmbed/libAddMedia/searchLibs/baseRemoteSearch.js
new file mode 100644 (file)
index 0000000..7065d17
--- /dev/null
@@ -0,0 +1,380 @@
+/*
+* Base remote search Object. 
+* provides the base class for the other search system to extend. 
+*/
+loadGM( {
+       "mwe-imported_from" : "$1 imported from [$2 $3]. See the original [$4 resource page] for more information.",
+       "mwe-import-description" : "$1, imported from $2"
+} );
+
+/*
+* rsd_default_rss_item_mapping
+* 
+*  @key is name of rObj variable
+*  @value is where to find the value in the item xml
+* 
+*  *value format:*
+*  . indicates multiple tags 
+*  @ separates the tag from attribute list
+*  {.}tag_name@{attribute1|attribute2}
+*
+* Also see mapAttributeToResource function bellow 
+*
+* FIXME should switch this over to something like Xpath if we end up parsing a lot of rss formats
+*/
+var rsd_default_rss_item_mapping = {
+       'poster'        : 'media:thumbnail@url',
+       'roe_url'       : 'media:roe_embed@url',
+       'person'        : 'media:person@label|url',
+       'parent_clip':'media:parent_clip@url',
+       'bill'          : 'media:bill@label|url',
+       'title'         : 'title',
+       'link'          : 'link',
+       'desc'          : 'description',
+       // multiple items
+       'category'  : '.media:category@label|url'
+};
+
+var baseRemoteSearch = function( iObj ) {
+       return this.init( iObj );
+};
+baseRemoteSearch.prototype = {
+
+       completed_req:0,
+       num_req:0,
+       
+       // ResultsObj holds the array of results
+       resultsObj: { },
+
+       // Default search result values for paging:
+       offset                   :0,
+       limit                   : 30,
+       more_results    : false,
+       num_results             : 0,
+
+       /**
+       * Initialise the baseRemoteSearch 
+       * @param {Object} options The set of options for the remote search class
+       */
+       init: function( options ) {
+               js_log( 'mvBaseRemoteSearch:init' );
+               for ( var i in options ) {
+                       this[i] = options[i];
+               }
+               return this;
+       },
+       getSearchResults:function() {
+               // Empty out the current results before issuing a request
+               this.resultsObj = { };
+               
+               // Do global getSearchResults bindings
+               this.last_query = $j( '#rsd_q' ).val();
+               this.last_offset = this.cp.offset;
+               
+               // Set the loading flag:                
+               this.loading = true;
+       },
+       /*
+       * Parses and adds video rss based input format
+       * @param {XML Nodes} data the data to be parsed
+       * @param {String} provider_url the source url (used to generate absolute links)
+       */
+       addRSSData:function( data , provider_url ) {
+               js_log( 'f:addRSSData' );
+               var _this = this;
+               var http_host = '';
+               var http_path = '';
+               if ( provider_url ) {
+                       pUrl =  mw.parseUri( provider_url );
+                       http_host = pUrl.protocol + '://' + pUrl.authority;
+                       http_path = pUrl.directory;
+               }
+               var items = data.getElementsByTagName( 'item' );
+               // js_log('found ' + items.length );
+               $j.each( items, function( inx, item ) {         
+                       var rObj = { };
+                       for ( var attr in rsd_default_rss_item_mapping ) {                              
+                               _this.mapAttributeToResource( rObj, item, attr );
+                       }
+                       // make relative urls absolute:
+                       var url_param = new Array( 'src', 'poster' );
+                       for ( var j = 0; j < url_param.length; j++ ) {
+                               var p = url_param[j];
+                               if ( typeof rObj[p] != 'undefined' ) {
+                                       if ( rObj[p].substr( 0, 1 ) == '/' ) {
+                                               rObj[p] = http_host + rObj[p];
+                                       }
+                                       if ( mw.parseUri( rObj[i] ).host ==  rObj[p] ) {
+                                               rObj[p] = http_host + http_path + rObj[p];
+                                       }
+                               }
+                       }
+                       // Force a mime type. In the future generalize for other RSS feeds
+                       rObj['mime'] = 'video/ogg';
+                       // Add pointer to parent search obj:( this.cp.limit )? this.cp.limit : this.limit,
+
+                       rObj['pSobj'] = _this;
+
+                       // Set target_resource_title
+                       _this.updateTargetResourceTitle( rObj );
+
+                       // add the result to the result set:
+                       _this.resultsObj[ inx ] = rObj;
+                       _this.num_results++;
+               } );
+       },
+       /*
+       * Maps a given attribute to a resource object per mapping defined in 
+       * rsd_default_rss_item_mapping
+       *
+       * @param {Object} rObj the resource object
+       * @param {XML Node} the xml result node
+       * @param {attr} the name attribute we are maping to the resource object 
+       */
+       mapAttributeToResource: function( rObj, item, attr ){           
+               var selector = rsd_default_rss_item_mapping[ attr ].split( '@' );
+               var flag_multiple = (  selector[0].substr( 0, 1 ) == '.' ) ? true : false;
+               if ( flag_multiple ) {
+                       rObj[ attr ] = new Array();
+                       var tag_name = selector[0].substr( 1 );
+               } else {
+                       var tag_name = selector[0];
+               }
+
+               var attr_name = null;
+               if ( typeof selector[1] != 'undefined' ) {
+                       attr_name = selector[1];
+                       if ( attr_name.indexOf( '|' ) != -1 )
+                               attr_name = attr_name.split( '|' );
+               }
+
+               $j.each( item.getElementsByTagName( tag_name ), function ( inx, node ) {
+                       var tag_val = '';
+                       if ( node != null && attr_name == null ) {
+                               if ( node.childNodes[0] != null ) {
+                                       // trim and strip html:
+                                       tag_val = $j.trim( node.firstChild.nodeValue ).replace(/(<([^>]+)>)/ig,"");
+                               }
+                       }
+                       if ( node != null && attr_name != null ) {
+                               if ( typeof attr_name == 'string' ) {
+                                       tag_val = $j.trim( $j( node ).attr( attr_name ) );
+                               } else {
+                                       var attr_vals = { };
+                                       for ( var j in attr_name ) {
+                                               if ( $j( node ).attr( attr_name[j] ).length != 0 )
+                                                       attr_vals[ attr_name[j] ] = $j.trim( $j(node).attr( attr_name[j]) ).replace(/(<([^>]+)>)/ig,"");
+                                       }
+                                       tag_val = attr_vals ;
+                               }
+                       }
+                       if ( flag_multiple ) {
+                               rObj[ attr ].push( tag_val )
+                       } else {
+                               rObj[ attr ] = tag_val;
+                       }
+               } );
+               // Nothing to return we update the "rObj" directly
+       }, 
+       
+       /**
+       * Get the html representation of the resource Object parameter
+       */
+       getEmbedHTML: function( rObj , options ) {
+               if ( !options )
+                       options = { };                  
+               // Set up the output var with the default values: 
+               if(! options.width )
+                       options.width = rObj.width;
+               if(! options.height )
+                       options.height = rObj.height
+                       
+               var outHtml  = '';
+               if ( options['max_height'] ) {
+                       options.height = ( options.max_height > rObj.height ) ? rObj.height : options.max_height;
+                       options.width = ( rObj.width / rObj.height ) * options.height;
+               }
+               options.style = '';
+               if( options.height )
+                       options.style += 'height:' + options.height + 'px;';
+                       
+               if( options.width )
+                       options.style += 'width:' + options.width + 'px;';                                                      
+               
+               if ( rObj.mime.indexOf( 'image' ) != -1 )
+                       outHtml = this.getImageEmbedHTML( rObj, options );
+                       
+               if ( rObj.mime == 'application/ogg' || rObj.mime == 'video/ogg' || rObj.mime == 'audio/ogg' ) {
+                       // Setup the attribute html:
+                       var ahtml = ( options['id'] ) ? ' id = "' + options['id'] + '" ': '';
+                       ahtml+= 'src="' + rObj.src + '" ' +
+                                       'style="' + options.style + '" ' +
+                                       'poster="' +  rObj.poster + '" ';
+                                       
+                       if (  rObj.mime == 'application/ogg' || rObj.mime == 'video/ogg'  ) {
+                               outHtml = '<video ' + ahtml + '></video>';
+                       }
+                                       
+                       if ( rObj.mime == 'audio/ogg' ) {
+                               outHtml = '<audio ' + ahtml + '></audio>';
+                       }
+               }
+               
+               // Return the output. Wrap with a description div if remote_insert_description is on.           
+               if( outHtml != '')
+                       return ( this.rsd['remote_insert_description'] ) ?
+                                       this.wrapHtmlDesc(rObj, options, outHtml) :
+                                       outHtml;
+                       
+               // No output give error: 
+               js_log( "ERROR:: no embed code for mime type: " + rObj.mime );  
+               return 'Error missing embed code for: ' + escape( rObj.mime );
+       },
+       wrapHtmlDesc: function( rObj, options, outHtml ) {
+               var stripedTitle =  rObj.title.replace( /File:|Image:|.jpg|.png|.ogg|.ogv|.oga|.svg/ig, '');
+               
+               var titleLink = '<a href="' + rObj.link + '" title="' + stripedTitle + '">' +
+                                                        stripedTitle + '</a>';
+               var cpTitle = gM('rsd-' + this.cp.id + '-title');
+               var remoteProviderLink = '<a href="' + this.cp.homepage + '" '+
+                                                                       'title="' + cpTitle + '">' +
+                                                                       cpTitle + '</a>';                                                                       
+               return '<div class="mw-imported-resource" '+ 
+                               'style="width:' + options.width + 'px;' + 
+                                       'height:' + ( options.height + 20 ) + 'px;">' +
+                                       outHtml +
+                                       gM( 'mwe-import-description',  [titleLink, remoteProviderLink]) + 
+                               '</div>';
+       },
+       /**
+       * Get the embed html specifically for an image type resource Object. 
+       */
+       getImageEmbedHTML:function( rObj, options ) {
+               // if crop is null do base output: 
+               var imgHtml = '<img ';
+               imgHtml += ( options['id'] ) ? ' id = "' + options['id'] + '" ': '';
+               imgHtml += ' src="' + rObj.edit_url  + '" '+
+                                       'style="' + options.style + '" />';
+               if ( rObj.crop == null )
+                       return imgHtml;
+               // Else do crop output: 
+               return '<div style="width:' + rObj.crop.w + 'px;height: ' + rObj.crop.h + 'px;overflow:hidden;position:relative">' +
+                                       '<div style="position:relative;top:-' + rObj.crop.y + 'px;left:-' + rObj.crop.x + 'px">' +
+                                               imgHtml +
+                                       '</div>' +
+                               '</div>';
+       },
+       /**
+       * Gets an image object from a requested transformation via callback
+       * ( letting api search implementations query the remote server for a 
+       *  given transformation )  
+       * 
+       * By default just return the existing image.
+       */
+       getImageObj:function( rObj, size, callback ) {
+               callback( { 
+                       'url' : rObj.poster 
+               } );
+       },
+       /**
+       * Gets the inline wikiText description of the resource Object
+       */
+       getInlineDescWiki:function( rObj ) {
+               // return striped html  & trim white space
+               if ( rObj.desc )
+                       return $j.trim( rObj.desc.replace(/(<([^>]+)>)/ig,"") );
+               // No Description available:  
+               return '';
+       },
+       /**
+       * Get the license wikiText tag for a given resource Object.
+       *
+       * By default license permission wiki text is cc based template mapping 
+       * (does not confirm the templates actually exist)
+       */
+       getPermissionWikiTag: function( rObj ) {
+               if ( !rObj.license )
+                       return '';// no license info
+                       
+               // First check if we have a special license template tag already set: 
+               if( rObj.license_template_tag )
+                       return '{{' + rObj.license_template_tag + '}}';
+                       
+               // Check that its a defined creative commons license key:
+               if (  this.rsd.licenses.cc.licenses[ rObj.license.key ] != 'undefined' ) {
+                       return '{{Cc-' + rObj.license.key + '}}';
+               } else if ( rObj.license.lurl ) {
+                       return '{{Template:External_License|' + rObj.license.lurl + '}}';
+               }
+
+       },
+       /**
+       * Gets the resource import description text
+       */
+       getImportResourceDescWiki:function( rObj ) {
+               return gM( 'mwe-imported_from', [rObj.title,  this.cp.homepage, gM('rsd-' + this.cp.id + '-title'), rObj.link] );
+       },
+       /**
+       * Get any extra wikitext description for the given resource object. 
+       * For content outside of the main template description, 
+       * like categories or additional wikitext notes. 
+       *
+       * By default its an empty string. 
+       */
+       getExtraResourceDescWiki:function( rObj ) {
+               return '';
+       },
+       
+       /** 
+       * Gets a image transformation 
+       * by default it just return the poster
+       */
+       getImageTransform:function( rObj, opt ) {
+               return rObj.poster;
+       },
+       
+       /**
+       * Adds additional resource information post clip embedding. 
+       */
+       addResourceInfoFromEmbedInstance : function( rObj, eb_id ) {
+               return rObj;
+       },
+       
+       /**
+       * Adds resource info with a callback function
+       *
+       * Use full for grabbing extra info that is not available in the initial 
+       * search results api request.
+       */
+       addResourceInfoCallback:function( rObj, callback ) {
+               callback();
+       },
+       
+       /**
+       * Get the wiki embed code for a given resource object
+       */
+       getEmbedWikiCode:function( rObj ) {
+               var layout = ( rObj.layout ) ? rObj.layout:"right"
+               var o = '[[' + this.rsd.fileNS + ':' + rObj.target_resource_title + '|thumb|' + layout;
+
+               if ( !rObj.target_width && rObj.width ) {
+                       rObj.target_width = ( rObj.width < 640 ) ? rObj.width: '640';
+               }
+
+               if ( rObj.target_width )
+                       o += '|' + rObj.target_width + 'px';
+
+               if ( rObj.inlineDesc )
+                       o += '|' + rObj.inlineDesc;
+
+               o += ']]';
+               return o;
+       },
+       /**
+       * Updates / normalizes the target_resource_title
+       */
+       updateTargetResourceTitle:function( rObj ) {
+               rObj.target_resource_title = rObj.titleKey.replace( /^(File:|Image:)/ , '' );
+               rObj.target_resource_title = this.cp.resource_prefix + rObj.target_resource_title;
+       }
+}
diff --git a/js2/mwEmbed/libAddMedia/searchLibs/flickrSearch.js b/js2/mwEmbed/libAddMedia/searchLibs/flickrSearch.js
new file mode 100644 (file)
index 0000000..c96bb2c
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Basic flickr search uses flickr jsonp api  
+ * http://www.flickr.com/services/api/
+ * 
+ *
+ * we look for licenses from method=flickr.photos.licenses.getInfo
+ * per http://commons.wikimedia.org/wiki/Special:Upload?uselang=fromflickr
+ * we are interested in:  
+ *     (4) Attribution License 
+ *     (5) Attribution-ShareAlike License, 
+ *     (7) No known copyright restrictions,
+ *     (8) United States Government Work
+ */
+
+var flickrSearch = function ( iObj ) {
+       return this.init( iObj );
+}
+flickrSearch.prototype = {
+       dtUrl : 'http://www.flickr.com/photos/',
+       // @@todo probably would be good to read the api-key from configuration
+       apikey : '2867787a545cc66c0bce6f2e57aca1d1',
+       // What license we are interested in
+       _license_keys: '4,5,7,8',
+       _srctypes: ['t', 'sq', 's', 'm', 'o'],
+       licenseMap: {
+               '4' : 'http://creativecommons.org/licenses/by/3.0/',
+               '5'     : 'http://creativecommons.org/licenses/by-sa/3.0/',
+               '7'     : 'http://www.flickr.com/commons/usage/',
+               '8' : 'http://www.usa.gov/copyright.shtml'
+       },
+       /**
+       * Initialize the flickr Search with provided options
+       */
+       init:function( options ) {              
+               var baseSearch = new baseRemoteSearch( options );
+               for ( var i in baseSearch ) {
+                       if ( typeof this[i] == 'undefined' ) {
+                               this[i] = baseSearch[i];
+                       } else {
+                               this['parent_' + i] =  baseSearch[i];
+                       }
+               }
+       },
+       /**
+       * Gets the Search results setting _loading flag to false once results have been added 
+       */
+       getSearchResults:function() {
+               var _this = this;
+               js_log( "flickr::getSearchResults" );
+               // call parent (sets loading sate and other setup stuff) 
+               this.parent_getSearchResults();
+               // setup the flickr request: 
+               var reqObj = {
+                       'method':'flickr.photos.search',
+                       'format':'json',
+                       'license':this._license_keys,
+                       'api_key':this.apikey,
+                       'per_page': this.cp.limit,
+                       'page' : this.cp.offset,
+                       'text': $j( '#rsd_q' ).val(),
+                       'extras' :      'license, date_upload, date_taken, owner_name, icon_server, original_format, last_update, geo, tags, machine_tags, o_dims, views, media, path_alias, url_sq, url_t, url_s, url_m, url_o'
+               }
+               do_api_req( {
+                       'data': reqObj,
+                       'url':this.cp.api_url,
+                       'jsonCB':'jsoncallback',
+               },      function( data ) {
+                       _this.addResults( data );
+                       _this.loading = false;
+               } );
+       },
+       /**
+       * Adds Results for a given data response from api query
+       */
+       addResults:function( data ) {
+               var _this = this;
+               if ( data.photos && data.photos.photo ) {
+                       // set result info: 
+                       this.num_results = data.photos.total;
+                       if ( this.num_results > this.cp.offset + this.cp.limit ) {
+                               this.more_results = true;
+                       }
+                       for ( var resource_id in data.photos.photo ) {
+                               var sourceResource = data.photos.photo[ resource_id ];
+                               var rObj = _this.getResourceObject( sourceResource );
+                               _this.resultsObj[ resource_id ] = rObj;
+                       }
+               }
+       },
+       /**
+       * Gets an individual resource object from a given source Resource
+       */
+       getResourceObject: function( resource ){                        
+               var _this = this;               
+               var rObj = {
+                       'titleKey'       : resource.title + '.jpg',
+                       'resourceKey': resource.id,
+                       'link'           : _this.dtUrl + resource.pathalias + '/' + resource.id,
+                       'title'          : resource.title,
+                       'thumbwidth' : resource.width_t,
+                       'thumbheight': resource.height_t,
+                       'desc'           : resource.title,
+                       // Set the license
+                       'license'        : this.rsd.getLicenceFromUrl( _this.licenseMap[ resource.license ] ),
+                       'pSobj'          : _this,
+                       // Assume image/jpeg for flickr response
+                       'mime'           : 'image/jpeg'
+               };
+               // Add all the provided src types that are avaliable 
+               rObj['srcSet'] = { };
+               for ( var i in _this._srctypes ) {
+                       var st = _this._srctypes[i];
+                       // if resource has a url add it to the srcSet:  
+                       if ( resource['url_' + st] ) {
+                               rObj['srcSet'][st] = {
+                                       'h': resource['height_' + st],
+                                       'w': resource['width_' + st],
+                                       'src': resource['url_' + st]
+                               }
+                               // Set src to the largest
+                               rObj['src'] = resource['url_' + st];
+                       }
+               }
+               return rObj;
+       },
+       /**
+       * return image transform via callback
+       */ 
+       getImageObj:function( rObj, size, callback ) {
+               if ( size.width ) {
+                       var skey = this.getSrcTypeKey( rObj, size.width )
+                       callback ( {
+                               'url' : rObj.srcSet[ skey ].src,
+                               'width' : rObj.srcSet[ skey ].w,
+                               'height' : rObj.srcSet[ skey ].h
+                       } );
+               }
+       },
+       /**
+       * Gets an image transformation based a SrcTypeKey gennerated by the requested options
+       */
+       getImageTransform:function( rObj, options ) {
+               if ( options.width ) {
+                       return rObj.srcSet[ this.getSrcTypeKey( rObj, options.width ) ].src;
+               }
+               return rObj.srcSet[ _srctypes[_srctypes.length-1] ];
+       },
+       getSrcTypeKey:function( rObj, width ) {
+               if ( width <= 75 ) {
+                       if ( rObj.srcSet['sq'] )
+                               return 'sq';
+               } else if ( width <= 100 ) {
+                       if ( rObj.srcSet['t'] )
+                               return 't';
+               } else if ( width <= 240 ) {
+                       if ( rObj.srcSet['s'] )
+                               return 's';
+               } else if ( width <= 500 ) {
+                       if ( rObj.srcSet['m'] )
+                               return 'm';
+               } else {
+                       if ( rObj.srcSet['o'] )
+                               return 'o';
+               }
+               // original was missing return medium or small
+               if ( rObj.srcSet['m'] )
+                       return 'm';
+               if ( rObj.srcSet['s'] )
+                       return 's';
+               
+       }
+}
diff --git a/js2/mwEmbed/libAddMedia/searchLibs/mediaWikiSearch.js b/js2/mwEmbed/libAddMedia/searchLibs/mediaWikiSearch.js
new file mode 100644 (file)
index 0000000..583fbc8
--- /dev/null
@@ -0,0 +1,357 @@
+var mediaWikiSearch = function( iObj ) {
+       return this.init( iObj );
+};
+mediaWikiSearch.prototype = {
+       init:function( iObj ) {
+               // init base class and inherit: 
+               var baseSearch = new baseRemoteSearch( iObj );
+               for ( var i in baseSearch ) {
+                       if ( typeof this[i] == 'undefined' ) {
+                               this[i] = baseSearch[i];
+                       } else {
+                               this['parent_' + i] =  baseSearch[i];
+                       }
+               }
+               // inherit the cp settings for 
+       },
+       // returns a rObj by title 
+       addByTitle:function( title , callback, redirect_count ) {
+               js_log( "AddByTitle::" + title );
+               var _this = this;
+               if ( !redirect_count )
+                       redirect_count = 0;
+               if ( redirect_count > 5 ) {
+                       js_log( 'Error: addByTitle too many redirects' );
+                       callback( false );
+                       return false;
+               }
+               var reqObj = {
+                       'action':'query',
+                       'titles':'File:' + title,
+                       'prop':'imageinfo|revisions|categories',
+                       'iiprop':'url|mime|size',
+                       'iiurlwidth': parseInt( this.rsd.thumb_width ),
+                       'rvprop':'content'
+               }
+               do_api_req( {
+                       'data':reqObj,
+                       'url':this.cp.api_url
+                       }, function( data ) {
+                               // check for redirect
+                               for ( var i in data.query.pages ) {
+                                       var page = data.query.pages[i];
+                                       if ( page.revisions[0]['*'] && page.revisions[0]['*'].indexOf( '#REDIRECT' ) === 0 ) {
+                                               var re = new RegExp( /[^\[]*\[\[([^\]]*)/ );
+                                               var pt = page.revisions[0]['*'].match( re );
+                                               if ( pt[1] ) {
+                                                       _this.addByTitle( pt[1], callback, redirect_count++ );
+                                                       return ;
+                                               } else {
+                                                       js_log( 'Error: addByTitle could not proccess redirect' );
+                                                       callback( false );
+                                                       return false;
+                                               }
+                                       }
+                               }
+                               // if not a redirect do the callback directly:  
+                               callback( _this.addSingleResult( data ) );
+                       }
+               );
+       },
+       clearResults:function() {
+               this.resultsObj = { };
+               this.last_query = '';
+       },
+       // update the resultObj with recently uploaded items by current User:
+       getUserRecentUploads:function( wgUser, callback ) {
+               var _this = this;
+               do_api_req( {
+                       'url':this.cp.api_url,
+                       'data': {
+                               'action':'query',
+                               'list':'recentchanges',
+                               'rcnamespace':6, // only files
+                               'rcuser': wgUser,
+                               'rclimit':15 // get last 15 uploaded files                              
+                       }                       
+               }, function( data ) {
+                       var titleSet = { };
+                       var titleStr = ''
+                       var pound = '';
+                       // loop over the data and group by title
+                       if ( data.query && data.query.recentchanges ) {
+                               for ( var i in data.query.recentchanges ) {
+                                       var rc = data.query.recentchanges[i];
+                                       if ( !titleSet[ rc.title ] ) {
+                                               titleSet[ rc.title ] = true;
+                                               titleStr += pound + rc.title;
+                                               pound = '|';
+                                       }
+                               }
+                       }
+                       // now run the actual query ( too bad we can't use recentchanges as a generator )
+                       // bug 20563
+                       do_api_req( {
+                               'data' : {
+                                       'action'        : 'query',
+                                       'titles'        : titleStr,
+                                       'prop'          : 'imageinfo|revisions|categories',
+                                       'iiprop'        : 'url|mime|size',
+                                       'iiurlwidth': parseInt( _this.rsd.thumb_width ),
+                                       'rvprop':'content'
+                               },
+                               'url':_this.cp.api_url
+                       }, function( data ) {
+                               _this.clearResults();
+                               _this.addResults( data );
+                               if ( callback )
+                                       callback();
+                       } );
+               } );
+       },
+       getSearchResults:function() {
+               // Call parent: 
+               this.parent_getSearchResults();
+               // Set local ref:
+               var _this = this;
+                               
+               js_log( 'f:getSearchResults for:' + $j( '#rsd_q' ).val() );
+               // Do two queries against the Image / File / MVD namespace:
+
+               // Build the image request object: 
+               var reqObj = {
+                       'action':'query',
+                       'generator':'search',
+                       'gsrsearch':  $j( '#rsd_q' ).val(),
+                       'gsrnamespace':6, // (only search the "file" namespace (audio, video, images)
+                       'gsrwhat':'title',
+                       'gsrlimit':  this.cp.limit,
+                       'gsroffset': this.cp.offset,
+                       'prop':'imageinfo|revisions|categories',
+                       'iiprop':'url|mime|size',
+                       'iiurlwidth': parseInt( this.rsd.thumb_width ),
+                       'rvprop':'content'
+               };
+               // Set up the number of request: 
+               this.completed_req = 0;
+               this.num_req = 1;
+               // Setup the number of requests result flag:                                                                                     
+               // Also do a request for page titles (would be nice if api could query both at the same time) 
+               reqObj['gsrwhat'] = 'text';
+               do_api_req( {
+                       'data':reqObj,
+                       'url':this.cp.api_url
+                       }, function( data ) {
+                               js_log( 'mediaWikiSearch: got data response' );
+                               // parse the return data
+                               _this.addResults( data );
+                               // _this.checkRequestDone(); //only need if we do two queries one for title one for text
+                               _this.loading = false;
+               } );
+       },
+       // same as below but returns your rObj for convenience 
+       addSingleResult:function( data ) {
+               return this.addResults( data, true );
+       },
+       addResults:function( data, returnFirst ) {
+               js_log( "f:addResults" );
+               var _this = this
+               // check if we have 
+               if ( typeof data['query-continue'] != 'undefined' ) {
+                       if ( typeof data['query-continue'].search != 'undefined' )
+                               this.more_results = true;
+               }
+               // Make sure we have pages to idorate:  
+               if ( data.query && data.query.pages ) {
+                       for ( var page_id in  data.query.pages ) {
+                               var page =  data.query.pages[ page_id ];
+                               
+                               // Make sure the reop is shared (don't show for now it confusing things)
+                               // @@todo support remote repository better
+                               if ( page.imagerepository == 'shared' ) {
+                                       continue;
+                               }
+                               
+                               // Make sure the page is not a redirect
+                               if ( page.revisions && page.revisions[0] &&
+                                       page.revisions[0]['*'] && page.revisions[0]['*'].indexOf( '#REDIRECT' ) === 0 ) {
+                                       // skip page is redirect 
+                                       continue;
+                               }
+                               // Skip if its an empty or missing imageinfo: 
+                               if ( !page.imageinfo )
+                                       continue;
+                               var rObj =      {
+                                       'id'             : page_id,
+                                       'titleKey'       : page.title,
+                                       'link'           : page.imageinfo[0].descriptionurl,
+                                       'title'          : page.title.replace(/File:.jpg|.png|.svg|.ogg|.ogv|.oga/ig, ''),
+                                       'poster'         : page.imageinfo[0].thumburl,
+                                       'thumbwidth' : page.imageinfo[0].thumbwidth,
+                                       'thumbheight': page.imageinfo[0].thumbheight,
+                                       'orgwidth'       : page.imageinfo[0].width,
+                                       'orgheight'      : page.imageinfo[0].height,
+                                       'mime'           : page.imageinfo[0].mime,
+                                       'src'            : page.imageinfo[0].url,
+                                       'desc'           : page.revisions[0]['*'],
+                                       // add pointer to parent search obj:
+                                       'pSobj'          :_this,
+                                       'meta': {
+                                               'categories':page.categories
+                                       }
+                               };
+                               /*
+                                //to use once we get the wiki-text parser in shape
+                               var pObj = mw.parser.pNew( rObj.desc );
+                               //structured data on commons is based on the "information" template: 
+                               var tmplInfo = pObj.templates( 'information' );         
+                               rObj.desc = tmplInfo.description                
+                               */
+                               
+                               // Attempt to parse out the description current user desc from the commons template: 
+                               // @@todo these could be combined to a single regEx
+                               // or better improve the wiki-text parsing and use above 
+                               var desc = rObj.desc.match( /\|\s*description\s*=\s*(([^\n]*\n)*)\|\s*source=/i );
+                               if ( desc && desc[1] ) {
+                                       rObj.desc = $j.trim( desc[1] );
+                                       // attempt to get the user language if set: 
+                                       if ( typeof wgUserLanguage != 'undefined' && wgUserLanguage ) {
+                                               // for some reason the RegExp object is not happy:
+                                               var reg = new RegExp( '\{\{\s*' + wgUserLanguage + '([^=]*)=([^\}]*)\}\}', 'gim' );
+                                               var langMatch = reg.exec( rObj.desc );
+                                               if ( langMatch && langMatch[2] ) {
+                                                       rObj.desc = langMatch[2];
+                                               } else {
+                                                       // try simple lang template form:
+                                                       var reg = new RegExp( '\{\{\s*' + wgUserLanguage + '\\|([^\}]*)\}\}', 'gim' );
+                                                       var langMatch = reg.exec( rObj.desc );
+                                                       if ( langMatch && langMatch[1] ) {
+                                                               rObj.desc = langMatch[1];
+                                                       }
+                                               }
+                                       }
+                               }
+                                                                               
+                               // Likely a audio clip if no poster and type application/ogg 
+                               // @@todo we should return audio/ogg for the mime type or some other way to specify its "audio" 
+                               if ( ! rObj.poster && rObj.mime == 'application/ogg' ) {
+                                       rObj.mime = 'audio/ogg';
+                               }
+                               // Add to the resultObj
+                               this.resultsObj[page_id] = rObj;
+                               
+                               // If returnFirst flag:
+                               if ( returnFirst )
+                                       return this.resultsObj[page_id];
+                               
+                               
+                               this.num_results++;
+                               // for(var i in this.resultsObj[page_id]){
+                               //      js_log('added: '+ i +' '+ this.resultsObj[page_id][i]);
+                               // }
+                       }
+               } else {
+                       js_log( 'no results:' + data );
+               }
+       },
+       // Check request done used for when we have multiple requests to check before formating results. 
+       checkRequestDone:function() {
+               // Display output if done: 
+               this.completed_req++;
+               if ( this.completed_req == this.num_req ) {
+                       this.loading = 0;
+               }
+       },
+       getImageObj:function( rObj, size, callback ) {
+               if ( rObj.mime == 'application/ogg' )
+                       return callback( { 'url':rObj.src, 'poster' : rObj.url } );
+               
+               // This could be depreciated if thumb.php support is standard
+               var reqObj = {
+                       'action':'query',
+                       'format':'json',
+                       'titles':rObj.titleKey,
+                       'prop':'imageinfo',
+                       'iiprop':'url|size|mime'
+               }
+               // Set the width: 
+               if ( size.width )
+                       reqObj['iiurlwidth'] = size.width;
+                js_log( 'going to do req: ' + this.cp.api_url + ' ' + reqObj );
+               do_api_req( {
+                       'data':reqObj,
+                       'url' : this.cp.api_url
+                       }, function( data ) {
+                               var imObj = { };
+                               for ( var page_id in  data.query.pages ) {
+                                       var iminfo =  data.query.pages[ page_id ].imageinfo[0];
+                                       // store the orginal width:                              
+                                       imObj['org_width'] = iminfo.width;
+                                       // check if thumb size > than image size and is jpeg or png (it will not scale well above its max res)                          
+                                       if ( ( iminfo.mime == 'image/jpeg' || iminfo == 'image/png' ) &&
+                                               iminfo.thumbwidth > iminfo.width ) {
+                                               imObj['url'] = iminfo.url;
+                                               imObj['width'] = iminfo.width;
+                                               imObj['height'] = iminfo.height;
+                                       } else {
+                                               imObj['url'] = iminfo.thumburl;
+                                               imObj['width'] = iminfo.thumbwidth;
+                                               imObj['height'] = iminfo.thumbheight;
+                                       }
+                               }
+                               js_log( 'getImageObj: get: ' + size.width + ' got url:' + imObj.url );
+                               callback( imObj );
+               } );
+       },
+       // the insert image function   
+       insertImage:function( cEdit ) {
+               if ( !cEdit )
+                       var cEdit = _this.cEdit;
+       },      
+       getInlineDescWiki:function( rObj ) {
+               var desc = this.parent_getInlineDescWiki( rObj );
+               
+               // Strip categories for inline Desc: (should strip license tags too but not as easy)
+               desc = desc.replace( /\[\[Category\:[^\]]*\]\]/gi, '' );
+               
+               // Just grab the description tag for inline desc:
+               var descMatch = new RegExp( /Description=(\{\{en\|)?([^|]*|)/ );
+               var dparts = desc.match( descMatch );
+                               
+               if ( dparts && dparts.length > 1 ) {
+                       desc = ( dparts.length == 2 ) ? dparts[1] : dparts[2].replace( '}}', '' );
+                       desc = ( desc.substr( 0, 2 ) == '1=' ) ? desc.substr( 2 ): desc;
+                       return desc;
+               }
+               // Hackish attempt to strip templates
+               desc = desc.replace( /\{\{[^\}]*\}\}/gi, '' );
+               // strip any nexted template closures
+               desc = desc.replace( /\}\}/gi, '' );
+               // strip titles
+               desc = desc.replace( /\=\=[^\=]*\=\=/gi, '' );
+                               
+               // else return the title since we could not find the desc:
+               js_log( 'Error: No Description Tag, Using::' + desc );
+               return desc;
+       },
+       // Returns the inline wikitext for insertion (template based crops for now) 
+       getEmbedWikiCode: function( rObj ) {
+                       // Set default layout to right justified
+                       var layout = ( rObj.layout ) ? rObj.layout:"right"
+                       // if crop is null do base output: 
+                       if ( rObj.crop == null )
+                               return this.parent_getEmbedWikiCode( rObj );
+                       // Using the preview crop template: http://en.wikipedia.org/wiki/Template:Preview_Crop
+                       // @@todo should be replaced with server side cropping 
+                       return '{{Preview Crop ' + "\n" +
+                                               '|Image   = ' + rObj.target_resource_title + "\n" +
+                                               '|bSize   = ' + rObj.width + "\n" +
+                                               '|cWidth  = ' + rObj.crop.w + "\n" +
+                                               '|cHeight = ' + rObj.crop.h + "\n" +
+                                               '|oTop  = ' + rObj.crop.y + "\n" +
+                                               '|oLeft   = ' + rObj.crop.x + "\n" +
+                                               '|Location =' + layout + "\n" +
+                                               '|Description =' + rObj.inlineDesc + "\n" +
+                                       '}}';
+       }
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libAddMedia/searchLibs/metavidSearch.js b/js2/mwEmbed/libAddMedia/searchLibs/metavidSearch.js
new file mode 100644 (file)
index 0000000..0d7ddb9
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+* API modes (implementations should call these objects which inherit the mvBaseRemoteSearch
+*/
+loadGM( {
+       "mwe-stream_title" : "$1 $2 to $3"
+} );
+var metavidSearch = function( iObj ) {
+       return this.init( iObj );
+};
+metavidSearch.prototype = {
+       defaultReq: {  // set up the default request paramaters
+               'order':'recent',
+               'feed_format':'json_rss',
+               'cb_inx': 1 // Not really used (we should update the metavid json retrun system) 
+       },
+       init:function( iObj ) {
+               // init base class and inherit:
+               var baseSearch = new baseRemoteSearch( iObj );
+               for ( var i in baseSearch ) {
+                       if ( typeof this[i] == 'undefined' ) {
+                               this[i] = baseSearch[i];
+                       } else {
+                               this['parent_' + i] =  baseSearch[i];
+                       }
+               }
+       },
+       getSearchResults:function() {
+               // call parent:
+               this.parent_getSearchResults();
+               // set local ref:
+               var _this = this;
+               js_log( 'metavidSearch::getSearchResults()' );
+               // Proccess all options
+               var url = this.cp.api_url;
+               var reqObj = $j.extend({}, this.defaultReq);
+               reqObj[ 'f[0][t]' ] = 'match';
+               reqObj[ 'f[0][v]' ] = $j( '#rsd_q' ).val();
+               
+               // add offset limit:
+               reqObj[ 'limit' ] = this.cp.limit;
+               reqObj[ 'offset' ] =  this.cp.offset;
+
+               do_api_req({
+                       'url' : url,
+                       'jsonCB' : 'cb',                        
+                       'data' : reqObj
+               }, function( data ) {   
+                       js_log( 'mvSearch: got data response::' );
+                       var xmldata = ( data && data['pay_load'] ) ? mw.parseXML( data['pay_load'] ) : false;
+                       if( !xmldata ){
+                               // XML Error or No results: 
+                               _this.resultsObj = {};
+                               _this.loading = 0;
+                               return ;                                
+                       }
+                                               
+                       // Add the data xml payload with context url:
+                       _this.addRSSData( xmldata , url );
+                       
+                       // Do some metavid specific pos processing on the rObj data:
+                       for ( var i in _this.resultsObj ) {
+                               var rObj = _this.resultsObj[i];
+                               var proe = mw.parseUri( rObj['roe_url'] );
+                               rObj['start_time'] = proe.queryKey['t'].split( '/' )[0];
+                               rObj['end_time'] = proe.queryKey['t'].split( '/' )[1];
+                               rObj['stream_name'] = proe.queryKey['stream_name'];
+
+                               // All metavid content is public domain:
+                               rObj['license'] = _this.rsd.getLicenseFromKey( 'pd' );
+
+                               // Transform the title into a wiki_safe title:                          
+                               rObj['titleKey'] =       _this.getTitleKey( rObj );
+
+                               // Default width of metavid clips:
+                               rObj['target_width'] = 400;
+                                                               
+                               rObj['author'] = 'US Government';
+                               
+                               // Add in the date as UTC "toDateString" : 
+                               var d = _this.getDateFromLink( rObj.link );
+                               rObj['date'] =   d.toDateString();
+                               
+                               // Set the license_template_tag ( all metavid content is PD-USGov )
+                               rObj['license_template_tag'] = 'PD-USGov';
+                       }
+                       // done loading:
+                       _this.loading = 0;
+               } );
+       },
+       /** 
+       * Get a Title key for the assset name inside the mediaWiki system
+       */
+       getTitleKey:function( rObj ) {
+               return rObj['stream_name'] + '_part_' + rObj['start_time'].replace(/:/g, '.' ) + '_to_' + rObj['end_time'].replace(/:/g, '.' ) + '.ogv';
+       },
+       getTitle:function( rObj ) {
+               var sn = rObj['stream_name'].replace( /_/g, ' ' );
+               sn = sn.charAt( 0 ).toUpperCase() + sn.substr( 1 );
+               return gM( 'mwe-stream_title', [ sn, rObj.start_time, rObj.end_time ] );
+       },
+       getExtraResourceDescWiki:function( rObj ) {
+               var o = "\n";
+               // check for person
+               if (  rObj.person && rObj.person['label'] )
+                       o += '* featuring [[' + rObj.person['label'] + ']]' + "\n";
+
+               if ( rObj.parent_clip )
+                       o += '* part of longer [' + rObj.parent_clip + ' video clip]' + "\n";
+
+               if ( rObj.person && rObj.person['url'] && rObj.person['label'] )
+                       o += '* also see speeches by [' +  $j.trim( rObj.person.url ) + ' ' + rObj.person['label'] + ']' + "\n";
+
+               // check for bill:
+               if ( rObj.bill && rObj.bill['label'] && rObj.bill['url'] )
+                       o += '* related to bill: [[' + rObj.bill['label'] + ']] more bill [' + rObj.bill['url'] + ' video clips]' + "\n";
+               return o;
+       },
+       // format is "quote" followed by [[name of person]]
+       getInlineDescWiki:function( rObj ) {
+               var o = this.parent_getInlineDescWiki( rObj );
+               // add in person if found
+               if ( rObj.person &&  rObj.person['label'] ) {
+                       o = $j.trim(  o.replace( rObj.person['label'], '' ) );
+                       // trim leading :
+                       if ( o.substr( 0, 1 ) == ':' )
+                               o =  o.substr( 1 );
+                       // add quotes and person at the end:
+                       var d = this.getDateFromLink( rObj.link );
+                       o = '"' + o + '" [[' + rObj.person['label'] + ']] on ' + d.toDateString();
+               }
+               // could do ref or direct link:
+               o += ' \'\'[' + $j.trim( rObj.link ) + ' source clip]\'\' ';
+
+               // var o= '"' + o + '" by [[' + rObj.person['label'] + ']] '+
+               //              '<ref>[' + rObj.link + ' Metavid Source Page] for ' + rObj.title +'</ref>';
+               return o;
+       },
+       // give an updated start and end time updates the title and url
+       applyVideoAdj: function( rObj ) {
+               js_log( 'mv ApplyVideoAdj::' );
+               // update the titleKey:
+               rObj['titleKey'] =       this.getTitleKey( rObj );
+
+               // update the title:
+               rObj['title'] = this.getTitle( rObj );
+
+               // update the interface:
+               js_log( 'update title to: ' + rObj['title'] );
+               $j( '#rsd_resource_title' ).html( gM( 'rsd_resource_edit', rObj['title'] ) );
+
+               // if the video is "roe" based select the ogg stream
+               if ( rObj.roe_url && rObj.pSobj.cp.stream_import_key ) {
+                       var source = $j( '#embed_vid' ).get( 0 ).media_element.getSourceById( rObj.pSobj.cp.stream_import_key );
+                       if ( !source ) {
+                               js_error( 'Error::could not find source: ' +  rObj.pSobj.cp.stream_import_key );
+                       } else {
+                               rObj['src'] = source.getURI();
+                               js_log( "g src_key: " + rObj.pSobj.cp.stream_import_key + ' src:' + rObj['src'] ) ;
+                               return true;
+                       }
+               }
+       },
+       getEmbedHTML:function( rObj , options ) {
+           if ( !options )
+                    options = { };
+               var id_attr = ( options['id'] ) ? ' id = "' + options['id'] + '" ': '';
+               var style_attr = ( options['max_width'] ) ? ' style="width:' + options['max_width'] + 'px;"':'';
+               // @@maybe check type here ?
+               if ( options['only_poster'] ) {
+                       return '<img ' + id_attr + ' src="' + rObj['poster'] + '" ' + style_attr + '>';
+               } else {
+                       return '<video ' + id_attr + ' roe="' + rObj['roe_url'] + '"></video>';
+               }
+       },
+       getImageTransform:function( rObj, opt ) {
+               if ( opt.width <= 80 ) {
+                       return getURLParamReplace( rObj.poster, { 'size' : "icon" } )
+               } else if ( opt.width <= 160 ) {
+                       return getURLParamReplace( rObj.poster, { 'size' : "small" } )
+               } else if ( opt.width <= 320 ) {
+                       return getURLParamReplace( rObj.poster, { 'size' : 'medium' } )
+               } else if ( opt.width <= 512 ) {
+                       return getURLParamReplace( rObj.poster, { 'size' : 'large' } )
+               } else {
+                       return getURLParamReplace( rObj.poster, { 'size' : 'full' } )
+               }
+       },
+       addResourceInfoFromEmbedInstance : function( rObj, embed_id ) {
+               var sources = $j( '#' + embed_id ).get( 0 ).media_element.getSources();
+               rObj.other_versions = '*[' + rObj['roe_url'] + ' XML of all Video Formats and Timed Text]' + "\n";
+               for ( var i in sources ) {
+                       var cur_source = sources[i];
+                       // rObj.other_versions += '*['+cur_source.getURI() +' ' + cur_source.title +']' + "\n";
+                       if ( cur_source.id ==  this.cp.target_source_id )
+                               rObj['url'] = cur_source.getURI();
+               }
+               // js_log('set url to: ' + rObj['url']);
+               return rObj;
+       },
+       getDateFromLink:function( link ) {
+               var dateExp = new RegExp( /_([0-9]+)\-([0-9]+)\-([0-9]+)/ );
+               var dParts = link.match ( dateExp );
+               var d = new Date();
+               var year_full = ( dParts[3].length == 2 ) ? '20' + dParts[3].toString():dParts[3];
+               d.setFullYear( year_full, dParts[1] - 1, dParts[2] );
+               return d;
+       }
+}
diff --git a/js2/mwEmbed/libAddMedia/simpleUploadForm.js b/js2/mwEmbed/libAddMedia/simpleUploadForm.js
new file mode 100644 (file)
index 0000000..e2e76e1
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * simple form output jquery binding
+ * enables dynamic form output to a given target
+ *
+ */
+
+loadGM( {
+       "mwe-select_file" : "Select file",
+       "mwe-more_license_options" : "For more license options, view the <a href=\"$1\">normal upload page<\/a>",
+       "mwe-select_ownwork" : "I am uploading entirely my own work, and licencing it under:",
+       "mwe-license_cc-by-sa" : "Creative Commons Share Alike (3.0)",
+       "mwe-upload" : "Upload file",
+       "mwe-destfilename" : "Destination filename:",
+       "mwe-summary" : "Summary",
+       "mwe-error_not_loggedin" : "You do not appear to be logged in or do not have upload privileges.",
+       "mwe-watch-this-file" : "Watch this file",
+       "mwe-ignore-any-warnings" : "Ignore any warnings"
+} );
+
+var default_form_options = {
+       'enable_fogg'    : true,
+       'license_options': ['cc-by-sa'],
+       'api_target' : false,
+       'ondone_cb' : null
+};
+
+( function( $ ) {
+       $.fn.simpleUploadForm = function( opt , callback ) {
+               var _this = this;
+               // set the options:
+               for ( var i in default_form_options ) {
+                       if ( !opt[i] )
+                               opt[i] = default_form_options[i];
+               }
+
+               // first do a reality check on the options:
+               if ( !opt.api_target ) {
+                       $( this.selector ).html( 'Error: Missing api target' );
+                       return false;
+               }
+
+               // @@todo this is just a proof of concept
+               // much todo to improved this web form
+               get_mw_token( 'File:MyRandomFileTokenCheck', opt.api_target, function( eToken ) {
+                       if ( !eToken || eToken == '+\\' ) {
+                               $( this.selector ).html( gM( 'mwe-error_not_loggedin' ) );
+                               return false;
+                       }
+
+                       // build an upload form:
+                       var o = '<div>' +
+                                               '<form id="suf-upload" enctype="multipart/form-data" action="' + opt.api_target + '" method="post">'  +
+                                               // hidden input:
+                                               '<input type="hidden" name="action" value="upload">' +
+                                               '<input type="hidden" name="format" value="jsonfm">' +
+                                               '<input type="hidden" id="wpEditToken" name="wpEditToken" value="' + eToken + '">' +
+                       
+                                               // form name set:
+                                               '<label for="wpUploadFile">' + gM( 'mwe-select_file' ) + '</label><br>' +
+                                               '<input id="wpUploadFile" type="file" style="display: inline;" name="wpUploadFile" size="15"/><br>' +
+                       
+                                               '<label for="wpDestFile">' + gM( 'mwe-destfilename' ) + '</label><br>' +
+                                               '<input id="wpDestFile" type="text" id="wpDestFile" name="wpDestFile" size="30" /><br>' +
+                       
+                                               '<label for="wpUploadDescription">' + gM( 'mwe-summary' ) + ':</label><br>' +
+                                               '<textarea id="wpUploadDescription" cols="30" rows="3" name="wpUploadDescription" tabindex="3"/><br>' +
+                                               
+                                               '<input type="checkbox" value="true" id="wpWatchthis" name="watch" tabindex="7"/>' +
+                                               '<label for="wpWatchthis">' + gM( 'mwe-watch-this-file' ) + '</label>' +
+                                               
+                                               '<input type="checkbox" value="true" id="wpIgnoreWarning" name="ignorewarnings" tabindex="8"/>' +
+                                               '<label for="wpIgnoreWarning">' + gM( 'mwe-ignore-any-warnings' ) + '</label></br>' +
+                                               
+                                               '<div id="wpDestFile-warning"></div>' +
+                                               '<div style="clear:both;"></div>' + '<p>' +
+                       
+                                               gM( 'mwe-select_ownwork' ) + '<br>' +
+                                               '<input type="checkbox" id="wpLicence" name="wpLicence" value="cc-by-sa">' + gM( 'mwe-license_cc-by-sa' ) + '</p>' +
+                       
+                                               '<input type="submit" accesskey="s" value="' + gM( 'mwe-upload' ) + '" name="wpUploadBtn" id="wpUploadBtn"  tabindex="9"/>' +
+                                               // close the form and div
+                                               '</form>' +
+                               '</div>';
+
+                       // set the target with the form output:
+                       $( _this.selector ).html( o );
+                       // by default dissable:
+                       $j( '#wpUploadBtn' ).attr( 'disabled', 'disabled' );
+
+                       // set up basic license binding:
+                       $j( '#wpLicence' ).click( function() {
+                               if ( $j( this ).is( ':checked' ) ) {
+                                       $j( '#wpUploadBtn' ).removeAttr( 'disabled' );
+                               } else {
+                                       $j( '#wpUploadBtn' ).attr( 'disabled', 'disabled' );
+                               }
+                       } );
+                       // do destination fill:
+                       // @@should integrate with doDestinationFill on upload page
+                       $j( "#wpUploadFile" ).change( function() {
+                               var path = $j( this ).val();
+                               // Find trailing part
+                               var slash = path.lastIndexOf( '/' );
+                               var backslash = path.lastIndexOf( '\\' );
+                               var fname;
+                               if ( slash == -1 && backslash == -1 ) {
+                                       fname = path;
+                               } else if ( slash > backslash ) {
+                                       fname = path.substring( slash + 1, 10000 );
+                               } else {
+                                       fname = path.substring( backslash + 1, 10000 );
+                               }
+                               fname = fname.charAt( 0 ).toUpperCase().concat( fname.substring( 1, 10000 ) ).replace( / /g, '_' );
+                               // Output result
+                               $j( "#wpDestFile" ).val( fname );
+                               // do destination check
+                               $j( "#wpDestFile" ).doDestCheck( {
+                                       'warn_target':'#wpDestFile-warning'
+                               } );
+                       } );
+
+
+                       // do destination check:
+                       $j( "#wpDestFile" ).change( function() {                        
+                               $j( "#wpDestFile" ).doDestCheck( {
+                                       'warn_target':'#wpDestFile-warning'
+                               } );
+                       } );
+
+                       if ( typeof opt.ondone_cb == 'undefined' )
+                               opt.ondone_cb = false;
+
+                       // set up the binding per the config
+                       if ( opt.enable_fogg ) {
+                               $j( "#wpUploadFile" ).firefogg( {
+                                       // An api url (we won't submit directly to action of the form)
+                                       'api_url' : opt.api_target,
+                                       
+                                       // If we should do a form rewrite
+                                       'form_rewrite': true,
+                                                                               
+                                       // MediaWiki API supports chunk uploads: 
+                                       'enable_chunks' : true,
+                                                                               
+                                       'edit_form_selector' : '#suf-upload',
+                                       'new_source_cb' : function( orgFilename, oggName ) {
+                                               $j( "#wpDestFile" ).val( oggName ).doDestCheck( {
+                                                       warn_target: "#wpDestFile-warning"
+                                               } );
+                                       },
+                                       'done_upload_cb' : opt.ondone_cb
+                               } );
+                       }
+               } );
+       }
+} )( jQuery );
diff --git a/js2/mwEmbed/libClipEdit/Jcrop/css/Jcrop.gif b/js2/mwEmbed/libClipEdit/Jcrop/css/Jcrop.gif
new file mode 100644 (file)
index 0000000..72ea7cc
Binary files /dev/null and b/js2/mwEmbed/libClipEdit/Jcrop/css/Jcrop.gif differ
diff --git a/js2/mwEmbed/libClipEdit/Jcrop/css/jquery.Jcrop.css b/js2/mwEmbed/libClipEdit/Jcrop/css/jquery.Jcrop.css
new file mode 100644 (file)
index 0000000..16ea45d
--- /dev/null
@@ -0,0 +1,35 @@
+/* Fixes issue here http://code.google.com/p/jcrop/issues/detail?id=1 */
+.jcrop-holder { text-align: left; }
+
+.jcrop-vline, .jcrop-hline
+{
+       font-size: 0;
+       position: absolute;
+       background: white url('Jcrop.gif') top left repeat;
+}
+.jcrop-vline { height: 100%; width: 1px !important; }
+.jcrop-hline { width: 100%; height: 1px !important; }
+.jcrop-handle {
+       font-size: 1px;
+       width: 7px !important;
+       height: 7px !important;
+       border: 1px #eee solid;
+       background-color: #333;
+       width: 9px;
+       height: 9px;
+}
+
+.jcrop-tracker { width: 100%; height: 100%; }
+
+.custom .jcrop-vline,
+.custom .jcrop-hline
+{
+       background: yellow;
+}
+.custom .jcrop-handle
+{
+       border-color: black;
+       background-color: #C7BB00;
+       -moz-border-radius: 3px;
+       -webkit-border-radius: 3px;
+}
diff --git a/js2/mwEmbed/libClipEdit/Jcrop/js/jquery.Jcrop.js b/js2/mwEmbed/libClipEdit/Jcrop/js/jquery.Jcrop.js
new file mode 100644 (file)
index 0000000..ad261f9
--- /dev/null
@@ -0,0 +1,1197 @@
+/**
+ * jquery.Jcrop.js v0.9.8
+ * jQuery Image Cropping Plugin
+ * @author Kelly Hallman <khallman@gmail.com>
+ * Copyright (c) 2008-2009 Kelly Hallman - released under MIT License {{{
+ *
+ * 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.
+
+ * }}}
+ */
+
+(function($) {
+
+$.Jcrop = function(obj,opt)
+{
+       // Initialization {{{
+
+       // Sanitize some options {{{
+       var obj = obj, opt = opt;
+
+       if (typeof(obj) !== 'object') obj = $(obj)[0];
+       if (typeof(opt) !== 'object') opt = { };
+
+       // Some on-the-fly fixes for MSIE...sigh
+       if (!('trackDocument' in opt))
+       {
+               opt.trackDocument = $.browser.msie ? false : true;
+               if ($.browser.msie && $.browser.version.split('.')[0] == '8')
+                       opt.trackDocument = true;
+       }
+
+       if (!('keySupport' in opt))
+                       opt.keySupport = $.browser.msie ? false : true;
+               
+       // }}}
+       // Extend the default options {{{
+       var defaults = {
+
+               // Basic Settings
+               trackDocument:          false,
+               baseClass:                      'jcrop',
+               addClass:                       null,
+
+               // Styling Options
+               bgColor:                        'black',
+               bgOpacity:                      .6,
+               borderOpacity:          .4,
+               handleOpacity:          .5,
+
+               handlePad:                      5,
+               handleSize:                     9,
+               handleOffset:           5,
+               edgeMargin:                     14,
+
+               aspectRatio:            0,
+               keySupport:                     true,
+               cornerHandles:          true,
+               sideHandles:            true,
+               drawBorders:            true,
+               dragEdges:                      true,
+
+               boxWidth:                       0,
+               boxHeight:                      0,
+
+               boundary:                       8,
+               animationDelay:         20,
+               swingSpeed:                     3,
+
+               allowSelect:            true,
+               allowMove:                      true,
+               allowResize:            true,
+
+               minSelect:                      [ 0, 0 ],
+               maxSize:                        [ 0, 0 ],
+               minSize:                        [ 0, 0 ],
+
+               // Callbacks / Event Handlers
+               onChange: function() { },
+               onSelect: function() { }
+
+       };
+       var options = defaults;
+       setOptions(opt);
+
+       // }}}
+       // Initialize some jQuery objects {{{
+
+       var $origimg = $(obj);
+       var $img = $origimg.clone().removeAttr('id').css({ position: 'absolute' });
+
+       $img.width($origimg.width());
+       $img.height($origimg.height());
+       $origimg.after($img).hide();
+
+       presize($img,options.boxWidth,options.boxHeight);
+
+       var boundx = $img.width(),
+               boundy = $img.height(),
+
+               $div = $('<div />')
+                       .width(boundx).height(boundy)
+                       .addClass(cssClass('holder'))
+                       .css({
+                               position: 'relative',
+                               backgroundColor: options.bgColor
+                       }).insertAfter($origimg).append($img);
+       ;
+       
+       if (options.addClass) $div.addClass(options.addClass);
+       //$img.wrap($div);
+
+       var $img2 = $('<img />')/*{{{*/
+                       .attr('src',$img.attr('src'))
+                       .css('position','absolute')
+                       .width(boundx).height(boundy)
+       ;/*}}}*/
+       var $img_holder = $('<div />')/*{{{*/
+               .width(pct(100)).height(pct(100))
+               .css({
+                       zIndex: 310,
+                       position: 'absolute',
+                       overflow: 'hidden'
+               })
+               .append($img2)
+       ;/*}}}*/
+       var $hdl_holder = $('<div />')/*{{{*/
+               .width(pct(100)).height(pct(100))
+               .css('zIndex',320);
+       /*}}}*/
+       var $sel = $('<div />')/*{{{*/
+               .css({
+                       position: 'absolute',
+                       zIndex: 300
+               })
+               .insertBefore($img)
+               .append($img_holder,$hdl_holder)
+       ;/*}}}*/
+
+       var bound = options.boundary;
+       var $trk = newTracker().width(boundx+(bound*2)).height(boundy+(bound*2))
+               .css({ position: 'absolute', top: px(-bound), left: px(-bound), zIndex: 290 })
+               .mousedown(newSelection);       
+       
+       /* }}} */
+       // Set more variables {{{
+
+       var xlimit, ylimit, xmin, ymin;
+       var xscale, yscale, enabled = true;
+       var docOffset = getPos($img),
+               // Internal states
+               btndown, lastcurs, dimmed, animating,
+               shift_down;
+
+       // }}}
+               
+
+               // }}}
+       // Internal Modules {{{
+
+       var Coords = function()/*{{{*/
+       {
+               var x1 = 0, y1 = 0, x2 = 0, y2 = 0, ox, oy;
+
+               function setPressed(pos)/*{{{*/
+               {
+                       var pos = rebound(pos);
+                       x2 = x1 = pos[0];
+                       y2 = y1 = pos[1];
+               };
+               /*}}}*/
+               function setCurrent(pos)/*{{{*/
+               {
+                       var pos = rebound(pos);
+                       ox = pos[0] - x2;
+                       oy = pos[1] - y2;
+                       x2 = pos[0];
+                       y2 = pos[1];
+               };
+               /*}}}*/
+               function getOffset()/*{{{*/
+               {
+                       return [ ox, oy ];
+               };
+               /*}}}*/
+               function moveOffset(offset)/*{{{*/
+               {
+                       var ox = offset[0], oy = offset[1];
+
+                       if (0 > x1 + ox) ox -= ox + x1;
+                       if (0 > y1 + oy) oy -= oy + y1;
+
+                       if (boundy < y2 + oy) oy += boundy - (y2 + oy);
+                       if (boundx < x2 + ox) ox += boundx - (x2 + ox);
+
+                       x1 += ox;
+                       x2 += ox;
+                       y1 += oy;
+                       y2 += oy;
+               };
+               /*}}}*/
+               function getCorner(ord)/*{{{*/
+               {
+                       var c = getFixed();
+                       switch(ord)
+                       {
+                               case 'ne': return [ c.x2, c.y ];
+                               case 'nw': return [ c.x, c.y ];
+                               case 'se': return [ c.x2, c.y2 ];
+                               case 'sw': return [ c.x, c.y2 ];
+                       }
+               };
+               /*}}}*/
+               function getFixed()/*{{{*/
+               {
+                       if (!options.aspectRatio) return getRect();
+                       // This function could use some optimization I think...
+                       var aspect = options.aspectRatio,
+                               min_x = options.minSize[0]/xscale, 
+                               min_y = options.minSize[1]/yscale,
+                               max_x = options.maxSize[0]/xscale, 
+                               max_y = options.maxSize[1]/yscale,
+                               rw = x2 - x1,
+                               rh = y2 - y1,
+                               rwa = Math.abs(rw),
+                               rha = Math.abs(rh),
+                               real_ratio = rwa / rha,
+                               xx, yy
+                       ;
+                       if (max_x == 0) { max_x = boundx * 10 }
+                       if (max_y == 0) { max_y = boundy * 10 }
+                       if (real_ratio < aspect)
+                       {
+                               yy = y2;
+                               w = rha * aspect;
+                               xx = rw < 0 ? x1 - w : w + x1;
+
+                               if (xx < 0)
+                               {
+                                       xx = 0;
+                                       h = Math.abs((xx - x1) / aspect);
+                                       yy = rh < 0 ? y1 - h: h + y1;
+                               }
+                               else if (xx > boundx)
+                               {
+                                       xx = boundx;
+                                       h = Math.abs((xx - x1) / aspect);
+                                       yy = rh < 0 ? y1 - h : h + y1;
+                               }
+                       }
+                       else
+                       {
+                               xx = x2;
+                               h = rwa / aspect;
+                               yy = rh < 0 ? y1 - h : y1 + h;
+                               if (yy < 0)
+                               {
+                                       yy = 0;
+                                       w = Math.abs((yy - y1) * aspect);
+                                       xx = rw < 0 ? x1 - w : w + x1;
+                               }
+                               else if (yy > boundy)
+                               {
+                                       yy = boundy;
+                                       w = Math.abs(yy - y1) * aspect;
+                                       xx = rw < 0 ? x1 - w : w + x1;
+                               }
+                       }
+
+                       // Magic %-)
+                       if(xx > x1) { // right side
+                         if(xx - x1 < min_x) {
+                               xx = x1 + min_x;
+                         } else if (xx - x1 > max_x) {
+                               xx = x1 + max_x;
+                         }
+                         if(yy > y1) {
+                               yy = y1 + (xx - x1)/aspect;
+                         } else {
+                               yy = y1 - (xx - x1)/aspect;
+                         }
+                       } else if (xx < x1) { // left side
+                         if(x1 - xx < min_x) {
+                               xx = x1 - min_x
+                         } else if (x1 - xx > max_x) {
+                               xx = x1 - max_x;
+                         }
+                         if(yy > y1) {
+                               yy = y1 + (x1 - xx)/aspect;
+                         } else {
+                               yy = y1 - (x1 - xx)/aspect;
+                         }
+                       }
+
+                       if(xx < 0) {
+                               x1 -= xx;
+                               xx = 0;
+                       } else  if (xx > boundx) {
+                               x1 -= xx - boundx;
+                               xx = boundx;
+                       }
+
+                       if(yy < 0) {
+                               y1 -= yy;
+                               yy = 0;
+                       } else  if (yy > boundy) {
+                               y1 -= yy - boundy;
+                               yy = boundy;
+                       }
+
+                       return last = makeObj(flipCoords(x1,y1,xx,yy));
+               };
+               /*}}}*/
+               function rebound(p)/*{{{*/
+               {
+                       if (p[0] < 0) p[0] = 0;
+                       if (p[1] < 0) p[1] = 0;
+
+                       if (p[0] > boundx) p[0] = boundx;
+                       if (p[1] > boundy) p[1] = boundy;
+
+                       return [ p[0], p[1] ];
+               };
+               /*}}}*/
+               function flipCoords(x1,y1,x2,y2)/*{{{*/
+               {
+                       var xa = x1, xb = x2, ya = y1, yb = y2;
+                       if (x2 < x1)
+                       {
+                               xa = x2;
+                               xb = x1;
+                       }
+                       if (y2 < y1)
+                       {
+                               ya = y2;
+                               yb = y1;
+                       }
+                       return [ Math.round(xa), Math.round(ya), Math.round(xb), Math.round(yb) ];
+               };
+               /*}}}*/
+               function getRect()/*{{{*/
+               {
+                       var xsize = x2 - x1;
+                       var ysize = y2 - y1;
+
+                       if (xlimit && (Math.abs(xsize) > xlimit))
+                               x2 = (xsize > 0) ? (x1 + xlimit) : (x1 - xlimit);
+                       if (ylimit && (Math.abs(ysize) > ylimit))
+                               y2 = (ysize > 0) ? (y1 + ylimit) : (y1 - ylimit);
+
+                       if (ymin && (Math.abs(ysize) < ymin))
+                               y2 = (ysize > 0) ? (y1 + ymin) : (y1 - ymin);
+                       if (xmin && (Math.abs(xsize) < xmin))
+                               x2 = (xsize > 0) ? (x1 + xmin) : (x1 - xmin);
+
+                       if (x1 < 0) { x2 -= x1; x1 -= x1; }
+                       if (y1 < 0) { y2 -= y1; y1 -= y1; }
+                       if (x2 < 0) { x1 -= x2; x2 -= x2; }
+                       if (y2 < 0) { y1 -= y2; y2 -= y2; }
+                       if (x2 > boundx) { var delta = x2 - boundx; x1 -= delta; x2 -= delta; }
+                       if (y2 > boundy) { var delta = y2 - boundy; y1 -= delta; y2 -= delta; }
+                       if (x1 > boundx) { var delta = x1 - boundy; y2 -= delta; y1 -= delta; }
+                       if (y1 > boundy) { var delta = y1 - boundy; y2 -= delta; y1 -= delta; }
+
+                       return makeObj(flipCoords(x1,y1,x2,y2));
+               };
+               /*}}}*/
+               function makeObj(a)/*{{{*/
+               {
+                       return { x: a[0], y: a[1], x2: a[2], y2: a[3],
+                               w: a[2] - a[0], h: a[3] - a[1] };
+               };
+               /*}}}*/
+
+               return {
+                       flipCoords: flipCoords,
+                       setPressed: setPressed,
+                       setCurrent: setCurrent,
+                       getOffset: getOffset,
+                       moveOffset: moveOffset,
+                       getCorner: getCorner,
+                       getFixed: getFixed
+               };
+       }();
+
+       /*}}}*/
+       var Selection = function()/*{{{*/
+       {
+               var start, end, dragmode, awake, hdep = 370;
+               var borders = { };
+               var handle = { };
+               var seehandles = false;
+               var hhs = options.handleOffset;
+
+               /* Insert draggable elements {{{*/
+
+               // Insert border divs for outline
+               if (options.drawBorders) {
+                       borders = {
+                                       top: insertBorder('hline')
+                                               .css('top',$.browser.msie?px(-1):px(0)),
+                                       bottom: insertBorder('hline'),
+                                       left: insertBorder('vline'),
+                                       right: insertBorder('vline')
+                       };
+               }
+
+               // Insert handles on edges
+               if (options.dragEdges) {
+                       handle.t = insertDragbar('n');
+                       handle.b = insertDragbar('s');
+                       handle.r = insertDragbar('e');
+                       handle.l = insertDragbar('w');
+               }
+
+               // Insert side handles
+               options.sideHandles &&
+                       createHandles(['n','s','e','w']);
+
+               // Insert corner handles
+               options.cornerHandles &&
+                       createHandles(['sw','nw','ne','se']);
+
+               /*}}}*/
+               // Private Methods
+               function insertBorder(type)/*{{{*/
+               {
+                       var jq = $('<div />')
+                               .css({position: 'absolute', opacity: options.borderOpacity })
+                               .addClass(cssClass(type));
+                       $img_holder.append(jq);
+                       return jq;
+               };
+               /*}}}*/
+               function dragDiv(ord,zi)/*{{{*/
+               {
+                       var jq = $('<div />')
+                               .mousedown(createDragger(ord))
+                               .css({
+                                       cursor: ord+'-resize',
+                                       position: 'absolute',
+                                       zIndex: zi 
+                               })
+                       ;
+                       $hdl_holder.append(jq);
+                       return jq;
+               };
+               /*}}}*/
+               function insertHandle(ord)/*{{{*/
+               {
+                       return dragDiv(ord,hdep++)
+                               .css({ top: px(-hhs+1), left: px(-hhs+1), opacity: options.handleOpacity })
+                               .addClass(cssClass('handle'));
+               };
+               /*}}}*/
+               function insertDragbar(ord)/*{{{*/
+               {
+                       var s = options.handleSize,
+                               o = hhs,
+                               h = s, w = s,
+                               t = o, l = o;
+
+                       switch(ord)
+                       {
+                               case 'n': case 's': w = pct(100); break;
+                               case 'e': case 'w': h = pct(100); break;
+                       }
+
+                       return dragDiv(ord,hdep++).width(w).height(h)
+                               .css({ top: px(-t+1), left: px(-l+1)});
+               };
+               /*}}}*/
+               function createHandles(li)/*{{{*/
+               {
+                       for(i in li) handle[li[i]] = insertHandle(li[i]);
+               };
+               /*}}}*/
+               function moveHandles(c)/*{{{*/
+               {
+                       var midvert  = Math.round((c.h / 2) - hhs),
+                               midhoriz = Math.round((c.w / 2) - hhs),
+                               north = west = -hhs+1,
+                               east = c.w - hhs,
+                               south = c.h - hhs,
+                               x, y;
+
+                       'e' in handle &&
+                               handle.e.css({ top: px(midvert), left: px(east) }) &&
+                               handle.w.css({ top: px(midvert) }) &&
+                               handle.s.css({ top: px(south), left: px(midhoriz) }) &&
+                               handle.n.css({ left: px(midhoriz) });
+
+                       'ne' in handle &&
+                               handle.ne.css({ left: px(east) }) &&
+                               handle.se.css({ top: px(south), left: px(east) }) &&
+                               handle.sw.css({ top: px(south) });
+
+                       'b' in handle &&
+                               handle.b.css({ top: px(south) }) &&
+                               handle.r.css({ left: px(east) });
+               };
+               /*}}}*/
+               function moveto(x,y)/*{{{*/
+               {
+                       $img2.css({ top: px(-y), left: px(-x) });
+                       $sel.css({ top: px(y), left: px(x) });
+               };
+               /*}}}*/
+               function resize(w,h)/*{{{*/
+               {
+                       $sel.width(w).height(h);
+               };
+               /*}}}*/
+               function refresh()/*{{{*/
+               {
+                       var c = Coords.getFixed();
+
+                       Coords.setPressed([c.x,c.y]);
+                       Coords.setCurrent([c.x2,c.y2]);
+
+                       updateVisible();
+               };
+               /*}}}*/
+
+               // Internal Methods
+               function updateVisible()/*{{{*/
+                       { if (awake) return update(); };
+               /*}}}*/
+               function update()/*{{{*/
+               {
+                       var c = Coords.getFixed();
+
+                       resize(c.w,c.h);
+                       moveto(c.x,c.y);
+
+                       options.drawBorders &&
+                               borders['right'].css({ left: px(c.w-1) }) &&
+                                       borders['bottom'].css({ top: px(c.h-1) });
+
+                       seehandles && moveHandles(c);
+                       awake || show();
+
+                       options.onChange(unscale(c));
+               };
+               /*}}}*/
+               function show()/*{{{*/
+               {
+                       $sel.show();
+                       $img.css('opacity',options.bgOpacity);
+                       awake = true;
+               };
+               /*}}}*/
+               function release()/*{{{*/
+               {
+                       disableHandles();
+                       $sel.hide();
+                       $img.css('opacity',1);
+                       awake = false;
+               };
+               /*}}}*/
+               function showHandles()//{{{
+               {
+                       if (seehandles)
+                       {
+                               moveHandles(Coords.getFixed());
+                               $hdl_holder.show();
+                       }
+               };
+               //}}}
+               function enableHandles()/*{{{*/
+               { 
+                       seehandles = true;
+                       if (options.allowResize)
+                       {
+                               moveHandles(Coords.getFixed());
+                               $hdl_holder.show();
+                               return true;
+                       }
+               };
+               /*}}}*/
+               function disableHandles()/*{{{*/
+               {
+                       seehandles = false;
+                       $hdl_holder.hide();
+               };
+               /*}}}*/
+               function animMode(v)/*{{{*/
+               {
+                       (animating = v) ? disableHandles(): enableHandles();
+               };
+               /*}}}*/
+               function done()/*{{{*/
+               {
+                       animMode(false);
+                       refresh();
+               };
+               /*}}}*/
+
+               var $track = newTracker().mousedown(createDragger('move'))
+                               .css({ cursor: 'move', position: 'absolute', zIndex: 360 })
+
+               $img_holder.append($track);
+               disableHandles();
+
+               return {
+                       updateVisible: updateVisible,
+                       update: update,
+                       release: release,
+                       refresh: refresh,
+                       setCursor: function (cursor) { $track.css('cursor',cursor); },
+                       enableHandles: enableHandles,
+                       enableOnly: function() { seehandles = true; },
+                       showHandles: showHandles,
+                       disableHandles: disableHandles,
+                       animMode: animMode,
+                       done: done
+               };
+       }();
+       /*}}}*/
+       var Tracker = function()/*{{{*/
+       {
+               var onMove              = function() { },
+                       onDone          = function() { },
+                       trackDoc        = options.trackDocument;
+
+               if (!trackDoc)
+               {
+                       $trk
+                               .mousemove(trackMove)
+                               .mouseup(trackUp)
+                               .mouseout(trackUp)
+                       ;
+               }
+
+               function toFront()/*{{{*/
+               {
+                       $trk.css({zIndex:450});
+                       if (trackDoc)
+                       {
+                               $(document)
+                                       .mousemove(trackMove)
+                                       .mouseup(trackUp)
+                               ;
+                       }
+               }
+               /*}}}*/
+               function toBack()/*{{{*/
+               {
+                       $trk.css({zIndex:290});
+                       if (trackDoc)
+                       {
+                               $(document)
+                                       .unbind('mousemove',trackMove)
+                                       .unbind('mouseup',trackUp)
+                               ;
+                       }
+               }
+               /*}}}*/
+               function trackMove(e)/*{{{*/
+               {
+                       onMove(mouseAbs(e));
+               };
+               /*}}}*/
+               function trackUp(e)/*{{{*/
+               {
+                       e.preventDefault();
+                       e.stopPropagation();
+
+                       if (btndown)
+                       {
+                               btndown = false;
+
+                               onDone(mouseAbs(e));
+                               options.onSelect(unscale(Coords.getFixed()));
+                               toBack();
+                               onMove = function() { };
+                               onDone = function() { };
+                       }
+
+                       return false;
+               };
+               /*}}}*/
+
+               function activateHandlers(move,done)/* {{{ */
+               {
+                       btndown = true;
+                       onMove = move;
+                       onDone = done;
+                       toFront();
+                       return false;
+               };
+               /* }}} */
+
+               function setCursor(t) { $trk.css('cursor',t); };
+
+               $img.before($trk);
+               return {
+                       activateHandlers: activateHandlers,
+                       setCursor: setCursor
+               };
+       }();
+       /*}}}*/
+       var KeyManager = function()/*{{{*/
+       {
+               var $keymgr = $('<input type="radio" />')
+                               .css({ position: 'absolute', left: '-30px' })
+                               .keypress(parseKey)
+                               .blur(onBlur),
+
+                       $keywrap = $('<div />')
+                               .css({
+                                       position: 'absolute',
+                                       overflow: 'hidden'
+                               })
+                               .append($keymgr)
+               ;
+
+               function watchKeys()/*{{{*/
+               {
+                       if (options.keySupport)
+                       {
+                               $keymgr.show();
+                               $keymgr.focus();
+                       }
+               };
+               /*}}}*/
+               function onBlur(e)/*{{{*/
+               {
+                       $keymgr.hide();
+               };
+               /*}}}*/
+               function doNudge(e,x,y)/*{{{*/
+               {
+                       if (options.allowMove) {
+                               Coords.moveOffset([x,y]);
+                               Selection.updateVisible();
+                       };
+                       e.preventDefault();
+                       e.stopPropagation();
+               };
+               /*}}}*/
+               function parseKey(e)/*{{{*/
+               {
+                       if (e.ctrlKey) return true;
+                       shift_down = e.shiftKey ? true : false;
+                       var nudge = shift_down ? 10 : 1;
+                       switch(e.keyCode)
+                       {
+                               case 37: doNudge(e,-nudge,0); break;
+                               case 39: doNudge(e,nudge,0); break;
+                               case 38: doNudge(e,0,-nudge); break;
+                               case 40: doNudge(e,0,nudge); break;
+
+                               case 27: Selection.release(); break;
+
+                               case 9: return true;
+                       }
+
+                       return nothing(e);
+               };
+               /*}}}*/
+               
+               if (options.keySupport) $keywrap.insertBefore($img);
+               return {
+                       watchKeys: watchKeys
+               };
+       }();
+       /*}}}*/
+
+       // }}}
+       // Internal Methods {{{
+
+       function px(n) { return '' + parseInt(n) + 'px'; };
+       function pct(n) { return '' + parseInt(n) + '%'; };
+       function cssClass(cl) { return options.baseClass + '-' + cl; };
+       function getPos(obj)/*{{{*/
+       {
+               // Updated in v0.9.4 to use built-in dimensions plugin
+               var pos = $(obj).offset();
+               return [ pos.left, pos.top ];
+       };
+       /*}}}*/
+       function mouseAbs(e)/*{{{*/
+       {
+               return [ (e.pageX - docOffset[0]), (e.pageY - docOffset[1]) ];
+       };
+       /*}}}*/
+       function myCursor(type)/*{{{*/
+       {
+               if (type != lastcurs)
+               {
+                       Tracker.setCursor(type);
+                       //Handles.xsetCursor(type);
+                       lastcurs = type;
+               }
+       };
+       /*}}}*/
+       function startDragMode(mode,pos)/*{{{*/
+       {
+               docOffset = getPos($img);
+               Tracker.setCursor(mode=='move'?mode:mode+'-resize');
+
+               if (mode == 'move')
+                       return Tracker.activateHandlers(createMover(pos), doneSelect);
+
+               var fc = Coords.getFixed();
+               var opp = oppLockCorner(mode);
+               var opc = Coords.getCorner(oppLockCorner(opp));
+
+               Coords.setPressed(Coords.getCorner(opp));
+               Coords.setCurrent(opc);
+
+               Tracker.activateHandlers(dragmodeHandler(mode,fc),doneSelect);
+       };
+       /*}}}*/
+       function dragmodeHandler(mode,f)/*{{{*/
+       {
+               return function(pos) {
+                       if (!options.aspectRatio) switch(mode)
+                       {
+                               case 'e': pos[1] = f.y2; break;
+                               case 'w': pos[1] = f.y2; break;
+                               case 'n': pos[0] = f.x2; break;
+                               case 's': pos[0] = f.x2; break;
+                       }
+                       else switch(mode)
+                       {
+                               case 'e': pos[1] = f.y+1; break;
+                               case 'w': pos[1] = f.y+1; break;
+                               case 'n': pos[0] = f.x+1; break;
+                               case 's': pos[0] = f.x+1; break;
+                       }
+                       Coords.setCurrent(pos);
+                       Selection.update();
+               };
+       };
+       /*}}}*/
+       function createMover(pos)/*{{{*/
+       {
+               var lloc = pos;
+               KeyManager.watchKeys();
+
+               return function(pos)
+               {
+                       Coords.moveOffset([pos[0] - lloc[0], pos[1] - lloc[1]]);
+                       lloc = pos;
+                       
+                       Selection.update();
+               };
+       };
+       /*}}}*/
+       function oppLockCorner(ord)/*{{{*/
+       {
+               switch(ord)
+               {
+                       case 'n': return 'sw';
+                       case 's': return 'nw';
+                       case 'e': return 'nw';
+                       case 'w': return 'ne';
+                       case 'ne': return 'sw';
+                       case 'nw': return 'se';
+                       case 'se': return 'nw';
+                       case 'sw': return 'ne';
+               };
+       };
+       /*}}}*/
+       function createDragger(ord)/*{{{*/
+       {
+               return function(e) {
+                       if (options.disabled) return false;
+                       if ((ord == 'move') && !options.allowMove) return false;
+                       btndown = true;
+                       startDragMode(ord,mouseAbs(e));
+                       e.stopPropagation();
+                       e.preventDefault();
+                       return false;
+               };
+       };
+       /*}}}*/
+       function presize($obj,w,h)/*{{{*/
+       {
+               var nw = $obj.width(), nh = $obj.height();
+               if ((nw > w) && w > 0)
+               {
+                       nw = w;
+                       nh = (w/$obj.width()) * $obj.height();
+               }
+               if ((nh > h) && h > 0)
+               {
+                       nh = h;
+                       nw = (h/$obj.height()) * $obj.width();
+               }
+               xscale = $obj.width() / nw;
+               yscale = $obj.height() / nh;
+               $obj.width(nw).height(nh);
+       };
+       /*}}}*/
+       function unscale(c)/*{{{*/
+       {
+               return {
+                       x: parseInt(c.x * xscale), y: parseInt(c.y * yscale), 
+                       x2: parseInt(c.x2 * xscale), y2: parseInt(c.y2 * yscale), 
+                       w: parseInt(c.w * xscale), h: parseInt(c.h * yscale)
+               };
+       };
+       /*}}}*/
+       function doneSelect(pos)/*{{{*/
+       {
+               var c = Coords.getFixed();
+               if (c.w > options.minSelect[0] && c.h > options.minSelect[1])
+               {
+                       Selection.enableHandles();
+                       Selection.done();
+               }
+               else
+               {
+                       Selection.release();
+               }
+               Tracker.setCursor( options.allowSelect?'crosshair':'default' );
+       };
+       /*}}}*/
+       function newSelection(e)/*{{{*/
+       {
+               if (options.disabled) return false;
+               if (!options.allowSelect) return false;
+               btndown = true;
+               docOffset = getPos($img);
+               Selection.disableHandles();
+               myCursor('crosshair');
+               var pos = mouseAbs(e);
+               Coords.setPressed(pos);
+               Tracker.activateHandlers(selectDrag,doneSelect);
+               KeyManager.watchKeys();
+               Selection.update();
+
+               e.stopPropagation();
+               e.preventDefault();
+               return false;
+       };
+       /*}}}*/
+       function selectDrag(pos)/*{{{*/
+       {
+               Coords.setCurrent(pos);
+               Selection.update();
+       };
+       /*}}}*/
+       function newTracker()
+       {
+               var trk = $('<div></div>').addClass(cssClass('tracker'));
+               $.browser.msie && trk.css({ opacity: 0, backgroundColor: 'white' });
+               return trk;
+       };
+
+       // }}}
+       // API methods {{{
+               
+       function animateTo(a)/*{{{*/
+       {
+               var x1 = a[0] / xscale,
+                       y1 = a[1] / yscale,
+                       x2 = a[2] / xscale,
+                       y2 = a[3] / yscale;
+
+               if (animating) return;
+
+               var animto = Coords.flipCoords(x1,y1,x2,y2);
+               var c = Coords.getFixed();
+               var animat = initcr = [ c.x, c.y, c.x2, c.y2 ];
+               var interv = options.animationDelay;
+
+               var x = animat[0];
+               var y = animat[1];
+               var x2 = animat[2];
+               var y2 = animat[3];
+               var ix1 = animto[0] - initcr[0];
+               var iy1 = animto[1] - initcr[1];
+               var ix2 = animto[2] - initcr[2];
+               var iy2 = animto[3] - initcr[3];
+               var pcent = 0;
+               var velocity = options.swingSpeed;
+
+               Selection.animMode(true);
+
+               var animator = function()
+               {
+                       return function()
+                       {
+                               pcent += (100 - pcent) / velocity;
+
+                               animat[0] = x + ((pcent / 100) * ix1);
+                               animat[1] = y + ((pcent / 100) * iy1);
+                               animat[2] = x2 + ((pcent / 100) * ix2);
+                               animat[3] = y2 + ((pcent / 100) * iy2);
+
+                               if (pcent < 100) animateStart();
+                                       else Selection.done();
+
+                               if (pcent >= 99.8) pcent = 100;
+
+                               setSelectRaw(animat);
+                       };
+               }();
+
+               function animateStart()
+                       { window.setTimeout(animator,interv); };
+
+               animateStart();
+       };
+       /*}}}*/
+       function setSelect(rect)//{{{
+       {
+               setSelectRaw([rect[0]/xscale,rect[1]/yscale,rect[2]/xscale,rect[3]/yscale]);
+       };
+       //}}}
+       function setSelectRaw(l) /*{{{*/
+       {
+               Coords.setPressed([l[0],l[1]]);
+               Coords.setCurrent([l[2],l[3]]);
+               Selection.update();
+       };
+       /*}}}*/
+       function setOptions(opt)/*{{{*/
+       {
+               if (typeof(opt) != 'object') opt = { };
+               options = $.extend(options,opt);
+
+               if (typeof(options.onChange)!=='function')
+                       options.onChange = function() { };
+
+               if (typeof(options.onSelect)!=='function')
+                       options.onSelect = function() { };
+
+       };
+       /*}}}*/
+       function tellSelect()/*{{{*/
+       {
+               return unscale(Coords.getFixed());
+       };
+       /*}}}*/
+       function tellScaled()/*{{{*/
+       {
+               return Coords.getFixed();
+       };
+       /*}}}*/
+       function setOptionsNew(opt)/*{{{*/
+       {
+               setOptions(opt);
+               interfaceUpdate();
+       };
+       /*}}}*/
+       function disableCrop()//{{{
+       {
+               options.disabled = true;
+               Selection.disableHandles();
+               Selection.setCursor('default');
+               Tracker.setCursor('default');
+       };
+       //}}}
+       function enableCrop()//{{{
+       {
+               options.disabled = false;
+               interfaceUpdate();
+       };
+       //}}}
+       function cancelCrop()//{{{
+       {
+               Selection.done();
+               Tracker.activateHandlers(null,null);
+       };
+       //}}}
+       function destroy()//{{{
+       {
+               $div.remove();
+               $origimg.show();
+       };
+       //}}}
+
+       function interfaceUpdate(alt)//{{{
+       // This method tweaks the interface based on options object.
+       // Called when options are changed and at end of initialization.
+       {
+               options.allowResize ?
+                       alt?Selection.enableOnly():Selection.enableHandles():
+                       Selection.disableHandles();
+
+               Tracker.setCursor( options.allowSelect? 'crosshair': 'default' );
+               Selection.setCursor( options.allowMove? 'move': 'default' );
+
+               $div.css('backgroundColor',options.bgColor);
+
+               if ('setSelect' in options) {
+                       setSelect(opt.setSelect);
+                       Selection.done();
+                       delete(options.setSelect);
+               }
+
+               if ('trueSize' in options) {
+                       xscale = options.trueSize[0] / boundx;
+                       yscale = options.trueSize[1] / boundy;
+               }
+
+               xlimit = options.maxSize[0] || 0;
+               ylimit = options.maxSize[1] || 0;
+               xmin = options.minSize[0] || 0;
+               ymin = options.minSize[1] || 0;
+
+               if ('outerImage' in options)
+               {
+                       $img.attr('src',options.outerImage);
+                       delete(options.outerImage);
+               }
+
+               Selection.refresh();
+       };
+       //}}}
+
+       // }}}
+
+       $hdl_holder.hide();
+       interfaceUpdate(true);
+       
+       var api = {
+               animateTo: animateTo,
+               setSelect: setSelect,
+               setOptions: setOptionsNew,
+               tellSelect: tellSelect,
+               tellScaled: tellScaled,
+
+               disable: disableCrop,
+               enable: enableCrop,
+               cancel: cancelCrop,
+
+               focus: KeyManager.watchKeys,
+
+               getBounds: function() { return [ boundx * xscale, boundy * yscale ]; },
+               getWidgetSize: function() { return [ boundx, boundy ]; },
+
+               release: Selection.release,
+               destroy: destroy
+
+       };
+
+       $origimg.data('Jcrop',api);
+       return api;
+};
+
+$.fn.Jcrop = function(options)/*{{{*/
+{
+       function attachWhenDone(from)/*{{{*/
+       {
+               var loadsrc = options.useImg || from.src;
+               var img = new Image();
+               img.onload = function() { $.Jcrop(from,options); };
+               img.src = loadsrc;
+       };
+       /*}}}*/
+       if (typeof(options) !== 'object') options = { };
+
+       // Iterate over each object, attach Jcrop
+       this.each(function()
+       {
+               // If we've already attached to this object
+               if ($(this).data('Jcrop'))
+               {
+                       // The API can be requested this way (undocumented)
+                       if (options == 'api') return $(this).data('Jcrop');
+                       // Otherwise, we just reset the options...
+                       else $(this).data('Jcrop').setOptions(options);
+               }
+               // If we haven't been attached, preload and attach
+               else attachWhenDone(this);
+       });
+
+       // Return "this" so we're chainable a la jQuery plugin-style!
+       return this;
+};
+/*}}}*/
+
+})(jQuery);
diff --git a/js2/mwEmbed/libClipEdit/colorpicker/css/colorpicker.css b/js2/mwEmbed/libClipEdit/colorpicker/css/colorpicker.css
new file mode 100644 (file)
index 0000000..c2b9296
--- /dev/null
@@ -0,0 +1,177 @@
+.colorpicker {\r
+       width: 356px;\r
+       height: 176px;\r
+       overflow: hidden;\r
+       position: absolute;\r
+       background: url(../images/colorpicker_background.png);\r
+       font-family: Arial, Helvetica, sans-serif;\r
+       display: none;\r
+}\r
+.colorpicker_color {\r
+       width: 150px;\r
+       height: 150px;\r
+       left: 14px;\r
+       top: 13px;\r
+       position: absolute;\r
+       background: #f00;\r
+       overflow: hidden;\r
+       cursor: crosshair;\r
+}\r
+.colorpicker_color div {\r
+       position: absolute;\r
+       top: 0;\r
+       left: 0;\r
+       width: 150px;\r
+       height: 150px;\r
+       background: url(../images/colorpicker_overlay.png);\r
+}\r
+.colorpicker_color div div {\r
+       position: absolute;\r
+       top: 0;\r
+       left: 0;\r
+       width: 11px;\r
+       height: 11px;\r
+       overflow: hidden;\r
+       background: url(../images/colorpicker_select.gif);\r
+       margin: -5px 0 0 -5px;\r
+}\r
+.colorpicker_hue {\r
+       position: absolute;\r
+       top: 13px;\r
+       left: 171px;\r
+       width: 35px;\r
+       height: 150px;\r
+       cursor: n-resize;\r
+}\r
+.colorpicker_hue div {\r
+       position: absolute;\r
+       width: 35px;\r
+       height: 9px;\r
+       overflow: hidden;\r
+       background: url(../images/colorpicker_indic.gif) left top;\r
+       margin: -4px 0 0 0;\r
+       left: 0px;\r
+}\r
+.colorpicker_new_color {\r
+       position: absolute;\r
+       width: 60px;\r
+       height: 30px;\r
+       left: 213px;\r
+       top: 13px;\r
+       background: #f00;\r
+}\r
+.colorpicker_current_color {\r
+       position: absolute;\r
+       width: 60px;\r
+       height: 30px;\r
+       left: 283px;\r
+       top: 13px;\r
+       background: #f00;\r
+}\r
+.colorpicker input {\r
+       background-color: transparent;\r
+       border: 1px solid transparent;\r
+       position: absolute;\r
+       font-size: 10px;\r
+       font-family: Arial, Helvetica, sans-serif;\r
+       color: #898989;\r
+       top: 4px;\r
+       right: 11px;\r
+       text-align: right;\r
+       margin: 0;\r
+       padding: 0;\r
+       height: 11px;\r
+}\r
+.colorpicker_hex {\r
+       position: absolute;\r
+       width: 72px;\r
+       height: 22px;\r
+       background: url(../images/colorpicker_hex.png) top;\r
+       left: 212px;\r
+       top: 142px;\r
+}\r
+.colorpicker_hex input {\r
+       right: 6px;\r
+}\r
+.colorpicker_field {\r
+       height: 22px;\r
+       width: 62px;\r
+       background-position: top;\r
+       position: absolute;\r
+}\r
+.colorpicker_field span {\r
+       position: absolute;\r
+       width: 12px;\r
+       height: 22px;\r
+       overflow: hidden;\r
+       top: 0;\r
+       right: 0;\r
+       cursor: n-resize;\r
+}\r
+.colorpicker_rgb_r {\r
+       background-image: url(../images/colorpicker_rgb_r.png);\r
+       top: 52px;\r
+       left: 212px;\r
+}\r
+.colorpicker_rgb_g {\r
+       background-image: url(../images/colorpicker_rgb_g.png);\r
+       top: 82px;\r
+       left: 212px;\r
+}\r
+.colorpicker_rgb_b {\r
+       background-image: url(../images/colorpicker_rgb_b.png);\r
+       top: 112px;\r
+       left: 212px;\r
+}\r
+.colorpicker_hsb_h {\r
+       background-image: url(../images/colorpicker_hsb_h.png);\r
+       top: 52px;\r
+       left: 282px;\r
+}\r
+.colorpicker_hsb_s {\r
+       background-image: url(../images/colorpicker_hsb_s.png);\r
+       top: 82px;\r
+       left: 282px;\r
+}\r
+.colorpicker_hsb_b {\r
+       background-image: url(../images/colorpicker_hsb_b.png);\r
+       top: 112px;\r
+       left: 282px;\r
+}\r
+.colorpicker_submit {\r
+       position: absolute;\r
+       width: 22px;\r
+       height: 22px;\r
+       background: url(../images/colorpicker_submit.png) top;\r
+       left: 322px;\r
+       top: 142px;\r
+       overflow: hidden;\r
+}\r
+.colorpicker_focus {\r
+       background-position: center;\r
+}\r
+.colorpicker_hex.colorpicker_focus {\r
+       background-position: bottom;\r
+}\r
+.colorpicker_submit.colorpicker_focus {\r
+       background-position: bottom;\r
+}\r
+.colorpicker_slider {\r
+       background-position: bottom;\r
+}
+
+/* chery picked from layout.css (should be more "jquery-ui" like when we get a chance */
+.colorSelector  {
+       background:url("../images/select.png") repeat scroll 0 0 transparent;
+       height:36px;
+       position:relative;
+       width:36px;
+}
+.colorSelector div {
+       position: absolute;
+       top: 3px;
+       left: 3px;
+       width: 30px;
+       height: 30px;
+       background: url(../images/select.png) center;
+}\r
diff --git a/js2/mwEmbed/libClipEdit/colorpicker/css/layout.css b/js2/mwEmbed/libClipEdit/colorpicker/css/layout.css
new file mode 100644 (file)
index 0000000..cc5da1d
--- /dev/null
@@ -0,0 +1,218 @@
+body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,p,blockquote,th,td { 
+       margin:0;
+       padding:0;
+}
+table {
+       border-collapse:collapse;
+       border-spacing:0;
+}
+fieldset,img { 
+       border:0;
+}
+address,caption,cite,code,dfn,em,strong,th,var {
+       font-style:normal;
+       font-weight:normal;
+}
+ol,ul {
+       list-style:none;
+}
+caption,th {
+       text-align:left;
+}
+h1,h2,h3,h4,h5,h6 {
+       font-size:100%;
+       font-weight:normal;
+}
+q:before,q:after {
+       content:'';
+}
+abbr,acronym { border:0;
+}
+html, body {
+       background-color: #fff;
+       font-family: Arial, Helvetica, sans-serif;
+       font-size: 12px;
+       line-height: 18px;
+       color: #52697E;
+}
+body {
+       text-align: center;
+       overflow: auto;
+}
+.wrapper {
+       width: 700px;
+       margin: 0 auto;
+       text-align: left;
+}
+h1 {
+       font-size: 21px;
+       height: 47px;
+       line-height: 47px;
+       text-transform: uppercase;
+}
+.navigationTabs {
+       height: 23px;
+       line-height: 23px;
+       border-bottom: 1px solid #ccc;
+}
+.navigationTabs li {
+       float: left;
+       height: 23px;
+       line-height: 23px;
+       padding-right: 3px;
+}
+.navigationTabs li a{
+       float: left;
+       dispaly: block;
+       height: 23px;
+       line-height: 23px;
+       padding: 0 10px;
+       overflow: hidden;
+       color: #52697E;
+       background-color: #eee;
+       position: relative;
+       text-decoration: none;
+}
+.navigationTabs li a:hover {
+       background-color: #f0f0f0;
+}
+.navigationTabs li a.active {
+       background-color: #fff;
+       border: 1px solid #ccc;
+       border-bottom: 0px solid;
+}
+.tabsContent {
+       border: 1px solid #ccc;
+       border-top: 0px solid;
+       width: 698px;
+       overflow: hidden;
+}
+.tab {
+       padding: 16px;
+       display: none;
+}
+.tab h2 {
+       font-weight: bold;
+       font-size: 16px;
+}
+.tab h3 {
+       font-weight: bold;
+       font-size: 14px;
+       margin-top: 20px;
+}
+.tab p {
+       margin-top: 16px;
+       clear: both;
+}
+.tab ul {
+       margin-top: 16px;
+       list-style: disc;
+}
+.tab li {
+       margin: 10px 0 0 35px;
+}
+.tab a {
+       color: #8FB0CF;
+}
+.tab strong {
+       font-weight: bold;
+}
+.tab pre {
+       font-size: 11px;
+       margin-top: 20px;
+       width: 668px;
+       overflow: auto;
+       clear: both;
+}
+.tab table {
+       width: 100%;
+}
+.tab table td {
+       padding: 6px 10px 6px 0;
+       vertical-align: top;
+}
+.tab dt {
+       margin-top: 16px;
+}
+
+#colorSelector {
+       position: relative;
+       width: 36px;
+       height: 36px;
+       background: url(../images/select.png);
+}
+#colorSelector div {
+       position: absolute;
+       top: 3px;
+       left: 3px;
+       width: 30px;
+       height: 30px;
+       background: url(../images/select.png) center;
+}
+#colorSelector2 {
+       position: absolute;
+       top: 0;
+       left: 0;
+       width: 36px;
+       height: 36px;
+       background: url(../images/select2.png);
+}
+#colorSelector2 div {
+       position: absolute;
+       top: 4px;
+       left: 4px;
+       width: 28px;
+       height: 28px;
+       background: url(../images/select2.png) center;
+}
+#colorpickerHolder2 {
+       top: 32px;
+       left: 0;
+       width: 356px;
+       height: 0;
+       overflow: hidden;
+       position: absolute;
+}
+#colorpickerHolder2 .colorpicker {
+       background-image: url(../images/custom_background.png);
+       position: absolute;
+       bottom: 0;
+       left: 0;
+}
+#colorpickerHolder2 .colorpicker_hue div {
+       background-image: url(../images/custom_indic.gif);
+}
+#colorpickerHolder2 .colorpicker_hex {
+       background-image: url(../images/custom_hex.png);
+}
+#colorpickerHolder2 .colorpicker_rgb_r {
+       background-image: url(../images/custom_rgb_r.png);
+}
+#colorpickerHolder2 .colorpicker_rgb_g {
+       background-image: url(../images/custom_rgb_g.png);
+}
+#colorpickerHolder2 .colorpicker_rgb_b {
+       background-image: url(../images/custom_rgb_b.png);
+}
+#colorpickerHolder2 .colorpicker_hsb_s {
+       background-image: url(../images/custom_hsb_s.png);
+       display: none;
+}
+#colorpickerHolder2 .colorpicker_hsb_h {
+       background-image: url(../images/custom_hsb_h.png);
+       display: none;
+}
+#colorpickerHolder2 .colorpicker_hsb_b {
+       background-image: url(../images/custom_hsb_b.png);
+       display: none;
+}
+#colorpickerHolder2 .colorpicker_submit {
+       background-image: url(../images/custom_submit.png);
+}
+#colorpickerHolder2 .colorpicker input {
+       color: #778398;
+}
+#customWidget {
+       position: relative;
+       height: 36px;
+}
diff --git a/js2/mwEmbed/libClipEdit/colorpicker/images/blank.gif b/js2/mwEmbed/libClipEdit/colorpicker/images/blank.gif
new file mode 100644 (file)
index 0000000..75b945d
Binary files /dev/null and b/js2/mwEmbed/libClipEdit/colorpicker/images/blank.gif differ
diff --git a/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_background.png b/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_background.png
new file mode 100644 (file)
index 0000000..8401572
Binary files /dev/null and b/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_background.png differ
diff --git a/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_hex.png b/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_hex.png
new file mode 100644 (file)
index 0000000..4e532d7
Binary files /dev/null and b/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_hex.png differ
diff --git a/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_hsb_b.png b/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_hsb_b.png
new file mode 100644 (file)
index 0000000..dfac595
Binary files /dev/null and b/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_hsb_b.png differ
diff --git a/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_hsb_h.png b/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_hsb_h.png
new file mode 100644 (file)
index 0000000..3977ed9
Binary files /dev/null and b/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_hsb_h.png differ
diff --git a/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_hsb_s.png b/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_hsb_s.png
new file mode 100644 (file)
index 0000000..a2a6997
Binary files /dev/null and b/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_hsb_s.png differ
diff --git a/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_indic.gif b/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_indic.gif
new file mode 100644 (file)
index 0000000..f9fa95e
Binary files /dev/null and b/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_indic.gif differ
diff --git a/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_overlay.png b/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_overlay.png
new file mode 100644 (file)
index 0000000..561cdd9
Binary files /dev/null and b/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_overlay.png differ
diff --git a/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_rgb_b.png b/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_rgb_b.png
new file mode 100644 (file)
index 0000000..dfac595
Binary files /dev/null and b/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_rgb_b.png differ
diff --git a/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_rgb_g.png b/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_rgb_g.png
new file mode 100644 (file)
index 0000000..72b3276
Binary files /dev/null and b/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_rgb_g.png differ
diff --git a/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_rgb_r.png b/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_rgb_r.png
new file mode 100644 (file)
index 0000000..4855fe0
Binary files /dev/null and b/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_rgb_r.png differ
diff --git a/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_select.gif b/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_select.gif
new file mode 100644 (file)
index 0000000..599f7f1
Binary files /dev/null and b/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_select.gif differ
diff --git a/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_submit.png b/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_submit.png
new file mode 100644 (file)
index 0000000..7f4c082
Binary files /dev/null and b/js2/mwEmbed/libClipEdit/colorpicker/images/colorpicker_submit.png differ
diff --git a/js2/mwEmbed/libClipEdit/colorpicker/images/custom_background.png b/js2/mwEmbed/libClipEdit/colorpicker/images/custom_background.png
new file mode 100644 (file)
index 0000000..cf55ffd
Binary files /dev/null and b/js2/mwEmbed/libClipEdit/colorpicker/images/custom_background.png differ
diff --git a/js2/mwEmbed/libClipEdit/colorpicker/images/custom_hex.png b/js2/mwEmbed/libClipEdit/colorpicker/images/custom_hex.png
new file mode 100644 (file)
index 0000000..888f444
Binary files /dev/null and b/js2/mwEmbed/libClipEdit/colorpicker/images/custom_hex.png differ
diff --git a/js2/mwEmbed/libClipEdit/colorpicker/images/custom_hsb_b.png b/js2/mwEmbed/libClipEdit/colorpicker/images/custom_hsb_b.png
new file mode 100644 (file)
index 0000000..2f99dae
Binary files /dev/null and b/js2/mwEmbed/libClipEdit/colorpicker/images/custom_hsb_b.png differ
diff --git a/js2/mwEmbed/libClipEdit/colorpicker/images/custom_hsb_h.png b/js2/mwEmbed/libClipEdit/colorpicker/images/custom_hsb_h.png
new file mode 100644 (file)
index 0000000..a217e92
Binary files /dev/null and b/js2/mwEmbed/libClipEdit/colorpicker/images/custom_hsb_h.png differ
diff --git a/js2/mwEmbed/libClipEdit/colorpicker/images/custom_hsb_s.png b/js2/mwEmbed/libClipEdit/colorpicker/images/custom_hsb_s.png
new file mode 100644 (file)
index 0000000..7826b41
Binary files /dev/null and b/js2/mwEmbed/libClipEdit/colorpicker/images/custom_hsb_s.png differ
diff --git a/js2/mwEmbed/libClipEdit/colorpicker/images/custom_indic.gif b/js2/mwEmbed/libClipEdit/colorpicker/images/custom_indic.gif
new file mode 100644 (file)
index 0000000..222fb94
Binary files /dev/null and b/js2/mwEmbed/libClipEdit/colorpicker/images/custom_indic.gif differ
diff --git a/js2/mwEmbed/libClipEdit/colorpicker/images/custom_rgb_b.png b/js2/mwEmbed/libClipEdit/colorpicker/images/custom_rgb_b.png
new file mode 100644 (file)
index 0000000..80764e5
Binary files /dev/null and b/js2/mwEmbed/libClipEdit/colorpicker/images/custom_rgb_b.png differ
diff --git a/js2/mwEmbed/libClipEdit/colorpicker/images/custom_rgb_g.png b/js2/mwEmbed/libClipEdit/colorpicker/images/custom_rgb_g.png
new file mode 100644 (file)
index 0000000..fc9778b
Binary files /dev/null and b/js2/mwEmbed/libClipEdit/colorpicker/images/custom_rgb_g.png differ
diff --git a/js2/mwEmbed/libClipEdit/colorpicker/images/custom_rgb_r.png b/js2/mwEmbed/libClipEdit/colorpicker/images/custom_rgb_r.png
new file mode 100644 (file)
index 0000000..91b0cd4
Binary files /dev/null and b/js2/mwEmbed/libClipEdit/colorpicker/images/custom_rgb_r.png differ
diff --git a/js2/mwEmbed/libClipEdit/colorpicker/images/custom_submit.png b/js2/mwEmbed/libClipEdit/colorpicker/images/custom_submit.png
new file mode 100644 (file)
index 0000000..cd202cd
Binary files /dev/null and b/js2/mwEmbed/libClipEdit/colorpicker/images/custom_submit.png differ
diff --git a/js2/mwEmbed/libClipEdit/colorpicker/images/select.png b/js2/mwEmbed/libClipEdit/colorpicker/images/select.png
new file mode 100644 (file)
index 0000000..21213bf
Binary files /dev/null and b/js2/mwEmbed/libClipEdit/colorpicker/images/select.png differ
diff --git a/js2/mwEmbed/libClipEdit/colorpicker/images/select2.png b/js2/mwEmbed/libClipEdit/colorpicker/images/select2.png
new file mode 100644 (file)
index 0000000..2cd2cab
Binary files /dev/null and b/js2/mwEmbed/libClipEdit/colorpicker/images/select2.png differ
diff --git a/js2/mwEmbed/libClipEdit/colorpicker/images/slider.png b/js2/mwEmbed/libClipEdit/colorpicker/images/slider.png
new file mode 100644 (file)
index 0000000..8b03da9
Binary files /dev/null and b/js2/mwEmbed/libClipEdit/colorpicker/images/slider.png differ
diff --git a/js2/mwEmbed/libClipEdit/colorpicker/index.html b/js2/mwEmbed/libClipEdit/colorpicker/index.html
new file mode 100644 (file)
index 0000000..f8da8af
--- /dev/null
@@ -0,0 +1,184 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+       <link rel="stylesheet" href="css/colorpicker.css" type="text/css" />
+    <link rel="stylesheet" media="screen" type="text/css" href="css/layout.css" />
+    <title>ColorPicker - jQuery plugin</title>
+       <script type="text/javascript" src="js/jquery.js"></script>
+       <script type="text/javascript" src="js/colorpicker.js"></script>
+    <script type="text/javascript" src="js/eye.js"></script>
+    <script type="text/javascript" src="js/utils.js"></script>
+    <script type="text/javascript" src="js/layout.js?ver=1.0.2"></script>
+</head>
+<body>
+    <div class="wrapper">
+        <h1>Color Picker - jQuery plugin</h1>
+        <ul class="navigationTabs">
+            <li><a href="#about" rel="about">About</a></li>
+            <li><a href="#download" rel="download">Download</a></li>
+            <li><a href="#implement" rel="implement">Implement</a></li>
+        </ul>
+        <div class="tabsContent">
+            <div class="tab">
+                <h2>About</h2>
+                <p>A simple component to select color in the same way you select color in Adobe Photoshop</p>
+                               <h3>Last update</h3>
+                               <p>23.05.2009 - Check Download tab</p>
+                <h3>Features</h3>
+                <ul>
+                    <li>Flat mode - as element in page</li>
+                    <li>Powerful controls for color selection</li>
+                                       <li>Easy to customize the look by changing some images</li>
+                                       <li>Fits into the viewport</li>
+                </ul>
+                               <h3>License</h3>
+                               <p>Dual licensed under the MIT and GPL licenses.</p>
+                <h3>Examples</h3>
+                <p>Flat mode.</p>
+                <p id="colorpickerHolder">
+                </p>
+                <pre>
+$('#colorpickerHolder').ColorPicker({flat: true});
+                </pre>
+                <p>Custom skin and using flat mode to display the color picker in a custom widget.</p>
+                               <div id="customWidget">
+                                       <div id="colorSelector2"><div style="background-color: #00ff00"></div></div>
+                       <div id="colorpickerHolder2">
+                       </div>
+                               </div>
+
+                               <p>Attached to an text field and using callback functions to update the color with field's value and set the value back in the field by submiting the color.</p>
+                               <p><input type="text" maxlength="6" size="6" id="colorpickerField1" value="00ff00" /></p>
+                               <p><input type="text" maxlength="6" size="6" id="colorpickerField3" value="0000ff" /></p>
+                               <p><input type="text" maxlength="6" size="6" id="colorpickerField2" value="ff0000" /></p>
+                               <pre>$('#colorpickerField1, #colorpickerField2, #colorpickerField3').ColorPicker({
+       onSubmit: function(hsb, hex, rgb, el) {
+               $(el).val(hex);
+               $(el).ColorPickerHide();
+       },
+       onBeforeShow: function () {
+               $(this).ColorPickerSetColor(this.value);
+       }
+})
+.bind('keyup', function(){
+       $(this).ColorPickerSetColor(this.value);
+});
+</pre>
+                               <p>Attached to DOMElement and using callbacks to live preview the color and adding animation.</p>
+                               <p>
+                                       <div id="colorSelector"><div style="background-color: #0000ff"></div></div>
+                               </p>
+                               <pre>
+$('#colorSelector').ColorPicker({
+       color: '#0000ff',
+       onShow: function (colpkr) {
+               $(colpkr).fadeIn(500);
+               return false;
+       },
+       onHide: function (colpkr) {
+               $(colpkr).fadeOut(500);
+               return false;
+       },
+       onChange: function (hsb, hex, rgb) {
+               $('#colorSelector div').css('backgroundColor', '#' + hex);
+       }
+});
+</pre>
+            </div>
+            <div class="tab">
+                <h2>Download</h2>
+                <p><a href="colorpicker.zip">colorpicker.zip (73 kb)</a>: jQuery, Javscript files, CSS files, images, examples and instructions.</p>
+                <h3>Changelog</h3>
+                <dl>
+                                       <dt>23.05.2009</dt>
+                                       <dd>Added: close on color selection example</dd>
+                                       <dd>Added: restore original color option</dd>
+                                       <dd>Changed: color update on key up event</dd>
+                                       <dd>Fixed: colorpicker hide and show methods</dd>
+                                       <dd>Fixed: reference to options. Multiple fields with colorpickers is possible now.</dd>
+                                       <dd>Fixed: RGB to HSB convertion</dd>
+                                       <dt>22.08.2008</dt>
+                                       <dd>Fixed bug: where some events were not canceled right on Safari</dd>
+                                       <dd>Fixed bug: where teh view port was not detected right on Safari</dd>
+                                       <dt>16-07-2008</dt>
+                                       <dd>Fixed bug where the letter 'F' could not be typed in the Hex field</dd>
+                                       <dd>Fixed bug where the changes on Hex field where not parsed</dd>
+                                       <dd>Added new option 'livePreview'</dd>
+                                       <dt>08-07-2008</dt>
+                                       <dd>Fixed typo in the code, both JavaScript and CSS</dd>
+                                       <dd>Changed the cursor for some elements</dd>
+                                       <dd>Added new demo explaining how to implement custom skin</dd>
+                                       <dt>07.07.2008</dt>
+                                       <dd>The first release.</dd>
+                </dl>
+            </div>
+            <div class="tab">
+                <h2>Implement</h2>
+                <p>Attach the Javascript and CSS files to your document. Edit CSS file and fix the paths to  images and change colors to fit your site theme.</p>
+                <pre>
+&lt;link rel="stylesheet" media="screen" type="text/css" href="css/colorpicker.css" /&gt;
+&lt;script type="text/javascript" src="js/colorpicker.js"&gt;&lt;/script&gt;
+                </pre>
+                <h3>Invocation code</h3>
+                <p>All you have to do is to select the elements in a jQuery way and call the plugin.</p>
+                <pre>
+ $('input').ColorPicker(options);
+                </pre>
+                <h3>Options</h3>
+                <p>A hash of parameters. All parameters are optional.</p>
+                <table>
+                       <tr>
+                               <td><strong>eventName</strong></td>
+                               <td>string</td>
+                               <td>The desired event to trigger the colorpicker. Default: 'click'</td>
+                       </tr>
+                       <tr>
+                               <td><strong>color</strong></td>
+                               <td>string or hash</td>
+                               <td>The default color. String for hex color or hash for RGB and HSB ({r:255, r:0, b:0}) . Default: 'ff0000'</td>
+                       </tr>
+                       <tr>
+                               <td><strong>flat</strong></td>
+                               <td>boolean</td>
+                               <td>Whatever if the color picker is appended to the element or triggered by an event. Default false</td>
+                       </tr>
+                       <tr>
+                               <td><strong>livePreview</strong></td>
+                               <td>boolean</td>
+                               <td>Whatever if the color values are filled in the fields while changing values on selector or a field. If false it may improve speed. Default true</td>
+                       </tr>
+                       <tr>
+                               <td><strong>onShow</strong></td>
+                               <td>function</td>
+                               <td>Callback function triggered when the color picker is shown</td>
+                       </tr>
+                       <tr>
+                               <td><strong>onBeforeShow</strong></td>
+                               <td>function</td>
+                               <td>Callback function triggered before the color picker is shown</td>
+                       </tr>
+                       <tr>
+                               <td><strong>onHide</strong></td>
+                               <td>function</td>
+                               <td>Callback function triggered when the color picker is hidden</td>
+                       </tr>
+                       <tr>
+                               <td><strong>onChange</strong></td>
+                               <td>function</td>
+                               <td>Callback function triggered when the color is changed</td>
+                       </tr>
+                       <tr>
+                               <td><strong>onSubmit</strong></td>
+                               <td>function</td>
+                               <td>Callback function triggered when the color it is chosen</td>
+                       </tr>
+                </table>
+                <h3>Set color</h3>
+                <p>If you want to set a new color.</p>
+                <pre>$('input').ColorPickerSetColor(color);</pre>
+                               <p>The 'color' argument is the same format as the option color, string for hex color or hash for RGB and HSB ({r:255, r:0, b:0}).</p>
+            </div>
+        </div>
+    </div>
+</body>
+</html>
diff --git a/js2/mwEmbed/libClipEdit/colorpicker/js/colorpicker.js b/js2/mwEmbed/libClipEdit/colorpicker/js/colorpicker.js
new file mode 100644 (file)
index 0000000..3d0d259
--- /dev/null
@@ -0,0 +1,484 @@
+/**
+ *
+ * Color picker
+ * Author: Stefan Petre www.eyecon.ro
+ * 
+ * Dual licensed under the MIT and GPL licenses
+ * 
+ */
+(function ($) {
+       var ColorPicker = function () {
+               var
+                       ids = {},
+                       inAction,
+                       charMin = 65,
+                       visible,
+                       tpl = '<div class="colorpicker"><div class="colorpicker_color"><div><div></div></div></div><div class="colorpicker_hue"><div></div></div><div class="colorpicker_new_color"></div><div class="colorpicker_current_color"></div><div class="colorpicker_hex"><input type="text" maxlength="6" size="6" /></div><div class="colorpicker_rgb_r colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_rgb_g colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_rgb_b colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_hsb_h colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_hsb_s colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_hsb_b colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_submit"></div></div>',
+                       defaults = {
+                               eventName: 'click',
+                               onShow: function () {},
+                               onBeforeShow: function(){},
+                               onHide: function () {},
+                               onChange: function () {},
+                               onSubmit: function () {},
+                               color: 'ff0000',
+                               livePreview: true,
+                               flat: false
+                       },
+                       fillRGBFields = function  (hsb, cal) {
+                               var rgb = HSBToRGB(hsb);
+                               $(cal).data('colorpicker').fields
+                                       .eq(1).val(rgb.r).end()
+                                       .eq(2).val(rgb.g).end()
+                                       .eq(3).val(rgb.b).end();
+                       },
+                       fillHSBFields = function  (hsb, cal) {
+                               $(cal).data('colorpicker').fields
+                                       .eq(4).val(hsb.h).end()
+                                       .eq(5).val(hsb.s).end()
+                                       .eq(6).val(hsb.b).end();
+                       },
+                       fillHexFields = function (hsb, cal) {
+                               $(cal).data('colorpicker').fields
+                                       .eq(0).val(HSBToHex(hsb)).end();
+                       },
+                       setSelector = function (hsb, cal) {
+                               $(cal).data('colorpicker').selector.css('backgroundColor', '#' + HSBToHex({h: hsb.h, s: 100, b: 100}));
+                               $(cal).data('colorpicker').selectorIndic.css({
+                                       left: parseInt(150 * hsb.s/100, 10),
+                                       top: parseInt(150 * (100-hsb.b)/100, 10)
+                               });
+                       },
+                       setHue = function (hsb, cal) {
+                               $(cal).data('colorpicker').hue.css('top', parseInt(150 - 150 * hsb.h/360, 10));
+                       },
+                       setCurrentColor = function (hsb, cal) {
+                               $(cal).data('colorpicker').currentColor.css('backgroundColor', '#' + HSBToHex(hsb));
+                       },
+                       setNewColor = function (hsb, cal) {
+                               $(cal).data('colorpicker').newColor.css('backgroundColor', '#' + HSBToHex(hsb));
+                       },
+                       keyDown = function (ev) {
+                               var pressedKey = ev.charCode || ev.keyCode || -1;
+                               if ((pressedKey > charMin && pressedKey <= 90) || pressedKey == 32) {
+                                       return false;
+                               }
+                               var cal = $(this).parent().parent();
+                               if (cal.data('colorpicker').livePreview === true) {
+                                       change.apply(this);
+                               }
+                       },
+                       change = function (ev) {
+                               var cal = $(this).parent().parent(), col;
+                               if (this.parentNode.className.indexOf('_hex') > 0) {
+                                       cal.data('colorpicker').color = col = HexToHSB(fixHex(this.value));
+                               } else if (this.parentNode.className.indexOf('_hsb') > 0) {
+                                       cal.data('colorpicker').color = col = fixHSB({
+                                               h: parseInt(cal.data('colorpicker').fields.eq(4).val(), 10),
+                                               s: parseInt(cal.data('colorpicker').fields.eq(5).val(), 10),
+                                               b: parseInt(cal.data('colorpicker').fields.eq(6).val(), 10)
+                                       });
+                               } else {
+                                       cal.data('colorpicker').color = col = RGBToHSB(fixRGB({
+                                               r: parseInt(cal.data('colorpicker').fields.eq(1).val(), 10),
+                                               g: parseInt(cal.data('colorpicker').fields.eq(2).val(), 10),
+                                               b: parseInt(cal.data('colorpicker').fields.eq(3).val(), 10)
+                                       }));
+                               }
+                               if (ev) {
+                                       fillRGBFields(col, cal.get(0));
+                                       fillHexFields(col, cal.get(0));
+                                       fillHSBFields(col, cal.get(0));
+                               }
+                               setSelector(col, cal.get(0));
+                               setHue(col, cal.get(0));
+                               setNewColor(col, cal.get(0));
+                               cal.data('colorpicker').onChange.apply(cal, [col, HSBToHex(col), HSBToRGB(col)]);
+                       },
+                       blur = function (ev) {
+                               var cal = $(this).parent().parent();
+                               cal.data('colorpicker').fields.parent().removeClass('colorpicker_focus');
+                       },
+                       focus = function () {
+                               charMin = this.parentNode.className.indexOf('_hex') > 0 ? 70 : 65;
+                               $(this).parent().parent().data('colorpicker').fields.parent().removeClass('colorpicker_focus');
+                               $(this).parent().addClass('colorpicker_focus');
+                       },
+                       downIncrement = function (ev) {
+                               var field = $(this).parent().find('input').focus();
+                               var current = {
+                                       el: $(this).parent().addClass('colorpicker_slider'),
+                                       max: this.parentNode.className.indexOf('_hsb_h') > 0 ? 360 : (this.parentNode.className.indexOf('_hsb') > 0 ? 100 : 255),
+                                       y: ev.pageY,
+                                       field: field,
+                                       val: parseInt(field.val(), 10),
+                                       preview: $(this).parent().parent().data('colorpicker').livePreview                                      
+                               };
+                               $(document).bind('mouseup', current, upIncrement);
+                               $(document).bind('mousemove', current, moveIncrement);
+                       },
+                       moveIncrement = function (ev) {
+                               ev.data.field.val(Math.max(0, Math.min(ev.data.max, parseInt(ev.data.val + ev.pageY - ev.data.y, 10))));
+                               if (ev.data.preview) {
+                                       change.apply(ev.data.field.get(0), [true]);
+                               }
+                               return false;
+                       },
+                       upIncrement = function (ev) {
+                               change.apply(ev.data.field.get(0), [true]);
+                               ev.data.el.removeClass('colorpicker_slider').find('input').focus();
+                               $(document).unbind('mouseup', upIncrement);
+                               $(document).unbind('mousemove', moveIncrement);
+                               return false;
+                       },
+                       downHue = function (ev) {
+                               var current = {
+                                       cal: $(this).parent(),
+                                       y: $(this).offset().top
+                               };
+                               current.preview = current.cal.data('colorpicker').livePreview;
+                               $(document).bind('mouseup', current, upHue);
+                               $(document).bind('mousemove', current, moveHue);
+                       },
+                       moveHue = function (ev) {
+                               change.apply(
+                                       ev.data.cal.data('colorpicker')
+                                               .fields
+                                               .eq(4)
+                                               .val(parseInt(360*(150 - Math.max(0,Math.min(150,(ev.pageY - ev.data.y))))/150, 10))
+                                               .get(0),
+                                       [ev.data.preview]
+                               );
+                               return false;
+                       },
+                       upHue = function (ev) {
+                               fillRGBFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));
+                               fillHexFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));
+                               $(document).unbind('mouseup', upHue);
+                               $(document).unbind('mousemove', moveHue);
+                               return false;
+                       },
+                       downSelector = function (ev) {
+                               var current = {
+                                       cal: $(this).parent(),
+                                       pos: $(this).offset()
+                               };
+                               current.preview = current.cal.data('colorpicker').livePreview;
+                               $(document).bind('mouseup', current, upSelector);
+                               $(document).bind('mousemove', current, moveSelector);
+                       },
+                       moveSelector = function (ev) {
+                               change.apply(
+                                       ev.data.cal.data('colorpicker')
+                                               .fields
+                                               .eq(6)
+                                               .val(parseInt(100*(150 - Math.max(0,Math.min(150,(ev.pageY - ev.data.pos.top))))/150, 10))
+                                               .end()
+                                               .eq(5)
+                                               .val(parseInt(100*(Math.max(0,Math.min(150,(ev.pageX - ev.data.pos.left))))/150, 10))
+                                               .get(0),
+                                       [ev.data.preview]
+                               );
+                               return false;
+                       },
+                       upSelector = function (ev) {
+                               fillRGBFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));
+                               fillHexFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));
+                               $(document).unbind('mouseup', upSelector);
+                               $(document).unbind('mousemove', moveSelector);
+                               return false;
+                       },
+                       enterSubmit = function (ev) {
+                               $(this).addClass('colorpicker_focus');
+                       },
+                       leaveSubmit = function (ev) {
+                               $(this).removeClass('colorpicker_focus');
+                       },
+                       clickSubmit = function (ev) {
+                               var cal = $(this).parent();
+                               var col = cal.data('colorpicker').color;
+                               cal.data('colorpicker').origColor = col;
+                               setCurrentColor(col, cal.get(0));
+                               cal.data('colorpicker').onSubmit(col, HSBToHex(col), HSBToRGB(col), cal.data('colorpicker').el);
+                       },
+                       show = function (ev) {
+                               var cal = $('#' + $(this).data('colorpickerId'));
+                               cal.data('colorpicker').onBeforeShow.apply(this, [cal.get(0)]);
+                               var pos = $(this).offset();
+                               var viewPort = getViewport();
+                               var top = pos.top + this.offsetHeight;
+                               var left = pos.left;
+                               if (top + 176 > viewPort.t + viewPort.h) {
+                                       top -= this.offsetHeight + 176;
+                               }
+                               if (left + 356 > viewPort.l + viewPort.w) {
+                                       left -= 356;
+                               }
+                               cal.css({left: left + 'px', top: top + 'px'});
+                               if (cal.data('colorpicker').onShow.apply(this, [cal.get(0)]) != false) {
+                                       cal.show();
+                               }
+                               $(document).bind('mousedown', {cal: cal}, hide);
+                               return false;
+                       },
+                       hide = function (ev) {
+                               if (!isChildOf(ev.data.cal.get(0), ev.target, ev.data.cal.get(0))) {
+                                       if (ev.data.cal.data('colorpicker').onHide.apply(this, [ev.data.cal.get(0)]) != false) {
+                                               ev.data.cal.hide();
+                                       }
+                                       $(document).unbind('mousedown', hide);
+                               }
+                       },
+                       isChildOf = function(parentEl, el, container) {
+                               if (parentEl == el) {
+                                       return true;
+                               }
+                               if (parentEl.contains) {
+                                       return parentEl.contains(el);
+                               }
+                               if ( parentEl.compareDocumentPosition ) {
+                                       return !!(parentEl.compareDocumentPosition(el) & 16);
+                               }
+                               var prEl = el.parentNode;
+                               while(prEl && prEl != container) {
+                                       if (prEl == parentEl)
+                                               return true;
+                                       prEl = prEl.parentNode;
+                               }
+                               return false;
+                       },
+                       getViewport = function () {
+                               var m = document.compatMode == 'CSS1Compat';
+                               return {
+                                       l : window.pageXOffset || (m ? document.documentElement.scrollLeft : document.body.scrollLeft),
+                                       t : window.pageYOffset || (m ? document.documentElement.scrollTop : document.body.scrollTop),
+                                       w : window.innerWidth || (m ? document.documentElement.clientWidth : document.body.clientWidth),
+                                       h : window.innerHeight || (m ? document.documentElement.clientHeight : document.body.clientHeight)
+                               };
+                       },
+                       fixHSB = function (hsb) {
+                               return {
+                                       h: Math.min(360, Math.max(0, hsb.h)),
+                                       s: Math.min(100, Math.max(0, hsb.s)),
+                                       b: Math.min(100, Math.max(0, hsb.b))
+                               };
+                       }, 
+                       fixRGB = function (rgb) {
+                               return {
+                                       r: Math.min(255, Math.max(0, rgb.r)),
+                                       g: Math.min(255, Math.max(0, rgb.g)),
+                                       b: Math.min(255, Math.max(0, rgb.b))
+                               };
+                       },
+                       fixHex = function (hex) {
+                               var len = 6 - hex.length;
+                               if (len > 0) {
+                                       var o = [];
+                                       for (var i=0; i<len; i++) {
+                                               o.push('0');
+                                       }
+                                       o.push(hex);
+                                       hex = o.join('');
+                               }
+                               return hex;
+                       }, 
+                       HexToRGB = function (hex) {
+                               var hex = parseInt(((hex.indexOf('#') > -1) ? hex.substring(1) : hex), 16);
+                               return {r: hex >> 16, g: (hex & 0x00FF00) >> 8, b: (hex & 0x0000FF)};
+                       },
+                       HexToHSB = function (hex) {
+                               return RGBToHSB(HexToRGB(hex));
+                       },
+                       RGBToHSB = function (rgb) {
+                               var hsb = {
+                                       h: 0,
+                                       s: 0,
+                                       b: 0
+                               };
+                               var min = Math.min(rgb.r, rgb.g, rgb.b);
+                               var max = Math.max(rgb.r, rgb.g, rgb.b);
+                               var delta = max - min;
+                               hsb.b = max;
+                               if (max != 0) {
+                                       
+                               }
+                               hsb.s = max != 0 ? 255 * delta / max : 0;
+                               if (hsb.s != 0) {
+                                       if (rgb.r == max) {
+                                               hsb.h = (rgb.g - rgb.b) / delta;
+                                       } else if (rgb.g == max) {
+                                               hsb.h = 2 + (rgb.b - rgb.r) / delta;
+                                       } else {
+                                               hsb.h = 4 + (rgb.r - rgb.g) / delta;
+                                       }
+                               } else {
+                                       hsb.h = -1;
+                               }
+                               hsb.h *= 60;
+                               if (hsb.h < 0) {
+                                       hsb.h += 360;
+                               }
+                               hsb.s *= 100/255;
+                               hsb.b *= 100/255;
+                               return hsb;
+                       },
+                       HSBToRGB = function (hsb) {
+                               var rgb = {};
+                               var h = Math.round(hsb.h);
+                               var s = Math.round(hsb.s*255/100);
+                               var v = Math.round(hsb.b*255/100);
+                               if(s == 0) {
+                                       rgb.r = rgb.g = rgb.b = v;
+                               } else {
+                                       var t1 = v;
+                                       var t2 = (255-s)*v/255;
+                                       var t3 = (t1-t2)*(h%60)/60;
+                                       if(h==360) h = 0;
+                                       if(h<60) {rgb.r=t1;     rgb.b=t2; rgb.g=t2+t3}
+                                       else if(h<120) {rgb.g=t1; rgb.b=t2;     rgb.r=t1-t3}
+                                       else if(h<180) {rgb.g=t1; rgb.r=t2;     rgb.b=t2+t3}
+                                       else if(h<240) {rgb.b=t1; rgb.r=t2;     rgb.g=t1-t3}
+                                       else if(h<300) {rgb.b=t1; rgb.g=t2;     rgb.r=t2+t3}
+                                       else if(h<360) {rgb.r=t1; rgb.g=t2;     rgb.b=t1-t3}
+                                       else {rgb.r=0; rgb.g=0; rgb.b=0}
+                               }
+                               return {r:Math.round(rgb.r), g:Math.round(rgb.g), b:Math.round(rgb.b)};
+                       },
+                       RGBToHex = function (rgb) {
+                               var hex = [
+                                       rgb.r.toString(16),
+                                       rgb.g.toString(16),
+                                       rgb.b.toString(16)
+                               ];
+                               $.each(hex, function (nr, val) {
+                                       if (val.length == 1) {
+                                               hex[nr] = '0' + val;
+                                       }
+                               });
+                               return hex.join('');
+                       },
+                       HSBToHex = function (hsb) {
+                               return RGBToHex(HSBToRGB(hsb));
+                       },
+                       restoreOriginal = function () {
+                               var cal = $(this).parent();
+                               var col = cal.data('colorpicker').origColor;
+                               cal.data('colorpicker').color = col;
+                               fillRGBFields(col, cal.get(0));
+                               fillHexFields(col, cal.get(0));
+                               fillHSBFields(col, cal.get(0));
+                               setSelector(col, cal.get(0));
+                               setHue(col, cal.get(0));
+                               setNewColor(col, cal.get(0));
+                       };
+               return {
+                       init: function (opt) {
+                               opt = $.extend({}, defaults, opt||{});
+                               if (typeof opt.color == 'string') {
+                                       opt.color = HexToHSB(opt.color);
+                               } else if (opt.color.r != undefined && opt.color.g != undefined && opt.color.b != undefined) {
+                                       opt.color = RGBToHSB(opt.color);
+                               } else if (opt.color.h != undefined && opt.color.s != undefined && opt.color.b != undefined) {
+                                       opt.color = fixHSB(opt.color);
+                               } else {
+                                       return this;
+                               }
+                               return this.each(function () {
+                                       if (!$(this).data('colorpickerId')) {
+                                               var options = $.extend({}, opt);
+                                               options.origColor = opt.color;
+                                               var id = 'collorpicker_' + parseInt(Math.random() * 1000);
+                                               $(this).data('colorpickerId', id);
+                                               var cal = $(tpl).attr('id', id);
+                                               if (options.flat) {
+                                                       cal.appendTo(this).show();
+                                               } else {
+                                                       cal.appendTo(document.body);
+                                               }
+                                               options.fields = cal
+                                                                                       .find('input')
+                                                                                               .bind('keyup', keyDown)
+                                                                                               .bind('change', change)
+                                                                                               .bind('blur', blur)
+                                                                                               .bind('focus', focus);
+                                               cal
+                                                       .find('span').bind('mousedown', downIncrement).end()
+                                                       .find('>div.colorpicker_current_color').bind('click', restoreOriginal);
+                                               options.selector = cal.find('div.colorpicker_color').bind('mousedown', downSelector);
+                                               options.selectorIndic = options.selector.find('div div');
+                                               options.el = this;
+                                               options.hue = cal.find('div.colorpicker_hue div');
+                                               cal.find('div.colorpicker_hue').bind('mousedown', downHue);
+                                               options.newColor = cal.find('div.colorpicker_new_color');
+                                               options.currentColor = cal.find('div.colorpicker_current_color');
+                                               cal.data('colorpicker', options);
+                                               cal.find('div.colorpicker_submit')
+                                                       .bind('mouseenter', enterSubmit)
+                                                       .bind('mouseleave', leaveSubmit)
+                                                       .bind('click', clickSubmit);
+                                               fillRGBFields(options.color, cal.get(0));
+                                               fillHSBFields(options.color, cal.get(0));
+                                               fillHexFields(options.color, cal.get(0));
+                                               setHue(options.color, cal.get(0));
+                                               setSelector(options.color, cal.get(0));
+                                               setCurrentColor(options.color, cal.get(0));
+                                               setNewColor(options.color, cal.get(0));
+                                               if (options.flat) {
+                                                       cal.css({
+                                                               position: 'relative',
+                                                               display: 'block'
+                                                       });
+                                               } else {
+                                                       $(this).bind(options.eventName, show);
+                                               }
+                                       }
+                               });
+                       },
+                       showPicker: function() {
+                               return this.each( function () {
+                                       if ($(this).data('colorpickerId')) {
+                                               show.apply(this);
+                                       }
+                               });
+                       },
+                       hidePicker: function() {
+                               return this.each( function () {
+                                       if ($(this).data('colorpickerId')) {
+                                               $('#' + $(this).data('colorpickerId')).hide();
+                                       }
+                               });
+                       },
+                       setColor: function(col) {
+                               if (typeof col == 'string') {
+                                       col = HexToHSB(col);
+                               } else if (col.r != undefined && col.g != undefined && col.b != undefined) {
+                                       col = RGBToHSB(col);
+                               } else if (col.h != undefined && col.s != undefined && col.b != undefined) {
+                                       col = fixHSB(col);
+                               } else {
+                                       return this;
+                               }
+                               return this.each(function(){
+                                       if ($(this).data('colorpickerId')) {
+                                               var cal = $('#' + $(this).data('colorpickerId'));
+                                               cal.data('colorpicker').color = col;
+                                               cal.data('colorpicker').origColor = col;
+                                               fillRGBFields(col, cal.get(0));
+                                               fillHSBFields(col, cal.get(0));
+                                               fillHexFields(col, cal.get(0));
+                                               setHue(col, cal.get(0));
+                                               setSelector(col, cal.get(0));
+                                               setCurrentColor(col, cal.get(0));
+                                               setNewColor(col, cal.get(0));
+                                       }
+                               });
+                       }
+               };
+       }();
+       $.fn.extend({
+               ColorPicker: ColorPicker.init,
+               ColorPickerHide: ColorPicker.hidePicker,
+               ColorPickerShow: ColorPicker.showPicker,
+               ColorPickerSetColor: ColorPicker.setColor
+       });
+})(jQuery);
\ No newline at end of file
diff --git a/js2/mwEmbed/libClipEdit/colorpicker/js/eye.js b/js2/mwEmbed/libClipEdit/colorpicker/js/eye.js
new file mode 100644 (file)
index 0000000..8a281dc
--- /dev/null
@@ -0,0 +1,34 @@
+/**
+ *
+ * Zoomimage
+ * Author: Stefan Petre www.eyecon.ro
+ * 
+ */
+(function($){
+       var EYE = window.EYE = function() {
+               var _registered = {
+                       init: []
+               };
+               return {
+                       init: function() {
+                               $.each(_registered.init, function(nr, fn){
+                                       fn.call();
+                               });
+                       },
+                       extend: function(prop) {
+                               for (var i in prop) {
+                                       if (prop[i] != undefined) {
+                                               this[i] = prop[i];
+                                       }
+                               }
+                       },
+                       register: function(fn, type) {
+                               if (!_registered[type]) {
+                                       _registered[type] = [];
+                               }
+                               _registered[type].push(fn);
+                       }
+               };
+       }();
+       $(EYE.init);
+})(jQuery);
diff --git a/js2/mwEmbed/libClipEdit/colorpicker/js/layout.js b/js2/mwEmbed/libClipEdit/colorpicker/js/layout.js
new file mode 100644 (file)
index 0000000..56975f3
--- /dev/null
@@ -0,0 +1,67 @@
+(function($){
+       var initLayout = function() {
+               var hash = window.location.hash.replace('#', '');
+               var currentTab = $('ul.navigationTabs a')
+                                                       .bind('click', showTab)
+                                                       .filter('a[rel=' + hash + ']');
+               if (currentTab.size() == 0) {
+                       currentTab = $('ul.navigationTabs a:first');
+               }
+               showTab.apply(currentTab.get(0));
+               $('#colorpickerHolder').ColorPicker({flat: true});
+               $('#colorpickerHolder2').ColorPicker({
+                       flat: true,
+                       color: '#00ff00',
+                       onSubmit: function(hsb, hex, rgb) {
+                               $('#colorSelector2 div').css('backgroundColor', '#' + hex);
+                       }
+               });
+               $('#colorpickerHolder2>div').css('position', 'absolute');
+               var widt = false;
+               $('#colorSelector2').bind('click', function() {
+                       $('#colorpickerHolder2').stop().animate({height: widt ? 0 : 173}, 500);
+                       widt = !widt;
+               });
+               $('#colorpickerField1, #colorpickerField2, #colorpickerField3').ColorPicker({
+                       onSubmit: function(hsb, hex, rgb, el) {
+                               $(el).val(hex);
+                               $(el).ColorPickerHide();
+                       },
+                       onBeforeShow: function () {
+                               $(this).ColorPickerSetColor(this.value);
+                       }
+               })
+               .bind('keyup', function(){
+                       $(this).ColorPickerSetColor(this.value);
+               });
+               $('#colorSelector').ColorPicker({
+                       color: '#0000ff',
+                       onShow: function (colpkr) {
+                               $(colpkr).fadeIn(500);
+                               return false;
+                       },
+                       onHide: function (colpkr) {
+                               $(colpkr).fadeOut(500);
+                               return false;
+                       },
+                       onChange: function (hsb, hex, rgb) {
+                               $('#colorSelector div').css('backgroundColor', '#' + hex);
+                       }
+               });
+       };
+       
+       var showTab = function(e) {
+               var tabIndex = $('ul.navigationTabs a')
+                                                       .removeClass('active')
+                                                       .index(this);
+               $(this)
+                       .addClass('active')
+                       .blur();
+               $('div.tab')
+                       .hide()
+                               .eq(tabIndex)
+                               .show();
+       };
+       
+       EYE.register(initLayout, 'init');
+})(jQuery)
\ No newline at end of file
diff --git a/js2/mwEmbed/libClipEdit/colorpicker/js/utils.js b/js2/mwEmbed/libClipEdit/colorpicker/js/utils.js
new file mode 100644 (file)
index 0000000..d9be853
--- /dev/null
@@ -0,0 +1,252 @@
+/**
+ *
+ * Utilities
+ * Author: Stefan Petre www.eyecon.ro
+ * 
+ */
+(function($) {
+EYE.extend({
+       getPosition : function(e, forceIt)
+       {
+               var x = 0;
+               var y = 0;
+               var es = e.style;
+               var restoreStyles = false;
+               if (forceIt && jQuery.curCSS(e,'display') == 'none') {
+                       var oldVisibility = es.visibility;
+                       var oldPosition = es.position;
+                       restoreStyles = true;
+                       es.visibility = 'hidden';
+                       es.display = 'block';
+                       es.position = 'absolute';
+               }
+               var el = e;
+               if (el.getBoundingClientRect) { // IE
+                       var box = el.getBoundingClientRect();
+                       x = box.left + Math.max(document.documentElement.scrollLeft, document.body.scrollLeft) - 2;
+                       y = box.top + Math.max(document.documentElement.scrollTop, document.body.scrollTop) - 2;
+               } else {
+                       x = el.offsetLeft;
+                       y = el.offsetTop;
+                       el = el.offsetParent;
+                       if (e != el) {
+                               while (el) {
+                                       x += el.offsetLeft;
+                                       y += el.offsetTop;
+                                       el = el.offsetParent;
+                               }
+                       }
+                       if (jQuery.browser.safari && jQuery.curCSS(e, 'position') == 'absolute' ) {
+                               x -= document.body.offsetLeft;
+                               y -= document.body.offsetTop;
+                       }
+                       el = e.parentNode;
+                       while (el && el.tagName.toUpperCase() != 'BODY' && el.tagName.toUpperCase() != 'HTML') 
+                       {
+                               if (jQuery.curCSS(el, 'display') != 'inline') {
+                                       x -= el.scrollLeft;
+                                       y -= el.scrollTop;
+                               }
+                               el = el.parentNode;
+                       }
+               }
+               if (restoreStyles == true) {
+                       es.display = 'none';
+                       es.position = oldPosition;
+                       es.visibility = oldVisibility;
+               }
+               return {x:x, y:y};
+       },
+       getSize : function(e)
+       {
+               var w = parseInt(jQuery.curCSS(e,'width'), 10);
+               var h = parseInt(jQuery.curCSS(e,'height'), 10);
+               var wb = 0;
+               var hb = 0;
+               if (jQuery.curCSS(e, 'display') != 'none') {
+                       wb = e.offsetWidth;
+                       hb = e.offsetHeight;
+               } else {
+                       var es = e.style;
+                       var oldVisibility = es.visibility;
+                       var oldPosition = es.position;
+                       es.visibility = 'hidden';
+                       es.display = 'block';
+                       es.position = 'absolute';
+                       wb = e.offsetWidth;
+                       hb = e.offsetHeight;
+                       es.display = 'none';
+                       es.position = oldPosition;
+                       es.visibility = oldVisibility;
+               }
+               return {w:w, h:h, wb:wb, hb:hb};
+       },
+       getClient : function(e)
+       {
+               var h, w;
+               if (e) {
+                       w = e.clientWidth;
+                       h = e.clientHeight;
+               } else {
+                       var de = document.documentElement;
+                       w = window.innerWidth || self.innerWidth || (de&&de.clientWidth) || document.body.clientWidth;
+                       h = window.innerHeight || self.innerHeight || (de&&de.clientHeight) || document.body.clientHeight;
+               }
+               return {w:w,h:h};
+       },
+       getScroll : function (e)
+       {
+               var t=0, l=0, w=0, h=0, iw=0, ih=0;
+               if (e && e.nodeName.toLowerCase() != 'body') {
+                       t = e.scrollTop;
+                       l = e.scrollLeft;
+                       w = e.scrollWidth;
+                       h = e.scrollHeight;
+               } else  {
+                       if (document.documentElement) {
+                               t = document.documentElement.scrollTop;
+                               l = document.documentElement.scrollLeft;
+                               w = document.documentElement.scrollWidth;
+                               h = document.documentElement.scrollHeight;
+                       } else if (document.body) {
+                               t = document.body.scrollTop;
+                               l = document.body.scrollLeft;
+                               w = document.body.scrollWidth;
+                               h = document.body.scrollHeight;
+                       }
+                       if (typeof pageYOffset != 'undefined') {
+                               t = pageYOffset;
+                               l = pageXOffset;
+                       }
+                       iw = self.innerWidth||document.documentElement.clientWidth||document.body.clientWidth||0;
+                       ih = self.innerHeight||document.documentElement.clientHeight||document.body.clientHeight||0;
+               }
+               return { t: t, l: l, w: w, h: h, iw: iw, ih: ih };
+       },
+       getMargins : function(e, toInteger)
+       {
+               var t = jQuery.curCSS(e,'marginTop') || '';
+               var r = jQuery.curCSS(e,'marginRight') || '';
+               var b = jQuery.curCSS(e,'marginBottom') || '';
+               var l = jQuery.curCSS(e,'marginLeft') || '';
+               if (toInteger)
+                       return {
+                               t: parseInt(t, 10)||0,
+                               r: parseInt(r, 10)||0,
+                               b: parseInt(b, 10)||0,
+                               l: parseInt(l, 10)
+                       };
+               else
+                       return {t: t, r: r,     b: b, l: l};
+       },
+       getPadding : function(e, toInteger)
+       {
+               var t = jQuery.curCSS(e,'paddingTop') || '';
+               var r = jQuery.curCSS(e,'paddingRight') || '';
+               var b = jQuery.curCSS(e,'paddingBottom') || '';
+               var l = jQuery.curCSS(e,'paddingLeft') || '';
+               if (toInteger)
+                       return {
+                               t: parseInt(t, 10)||0,
+                               r: parseInt(r, 10)||0,
+                               b: parseInt(b, 10)||0,
+                               l: parseInt(l, 10)
+                       };
+               else
+                       return {t: t, r: r,     b: b, l: l};
+       },
+       getBorder : function(e, toInteger)
+       {
+               var t = jQuery.curCSS(e,'borderTopWidth') || '';
+               var r = jQuery.curCSS(e,'borderRightWidth') || '';
+               var b = jQuery.curCSS(e,'borderBottomWidth') || '';
+               var l = jQuery.curCSS(e,'borderLeftWidth') || '';
+               if (toInteger)
+                       return {
+                               t: parseInt(t, 10)||0,
+                               r: parseInt(r, 10)||0,
+                               b: parseInt(b, 10)||0,
+                               l: parseInt(l, 10)||0
+                       };
+               else
+                       return {t: t, r: r,     b: b, l: l};
+       },
+       traverseDOM : function(nodeEl, func)
+       {
+               func(nodeEl);
+               nodeEl = nodeEl.firstChild;
+               while(nodeEl){
+                       EYE.traverseDOM(nodeEl, func);
+                       nodeEl = nodeEl.nextSibling;
+               }
+       },
+       getInnerWidth :  function(el, scroll) {
+               var offsetW = el.offsetWidth;
+               return scroll ? Math.max(el.scrollWidth,offsetW) - offsetW + el.clientWidth:el.clientWidth;
+       },
+       getInnerHeight : function(el, scroll) {
+               var offsetH = el.offsetHeight;
+               return scroll ? Math.max(el.scrollHeight,offsetH) - offsetH + el.clientHeight:el.clientHeight;
+       },
+       getExtraWidth : function(el) {
+               if($.boxModel)
+                       return (parseInt($.curCSS(el, 'paddingLeft'))||0)
+                               + (parseInt($.curCSS(el, 'paddingRight'))||0)
+                               + (parseInt($.curCSS(el, 'borderLeftWidth'))||0)
+                               + (parseInt($.curCSS(el, 'borderRightWidth'))||0);
+               return 0;
+       },
+       getExtraHeight : function(el) {
+               if($.boxModel)
+                       return (parseInt($.curCSS(el, 'paddingTop'))||0)
+                               + (parseInt($.curCSS(el, 'paddingBottom'))||0)
+                               + (parseInt($.curCSS(el, 'borderTopWidth'))||0)
+                               + (parseInt($.curCSS(el, 'borderBottomWidth'))||0);
+               return 0;
+       },
+       isChildOf: function(parentEl, el, container) {
+               if (parentEl == el) {
+                       return true;
+               }
+               if (!el || !el.nodeType || el.nodeType != 1) {
+                       return false;
+               }
+               if (parentEl.contains && !$.browser.safari) {
+                       return parentEl.contains(el);
+               }
+               if ( parentEl.compareDocumentPosition ) {
+                       return !!(parentEl.compareDocumentPosition(el) & 16);
+               }
+               var prEl = el.parentNode;
+               while(prEl && prEl != container) {
+                       if (prEl == parentEl)
+                               return true;
+                       prEl = prEl.parentNode;
+               }
+               return false;
+       },
+       centerEl : function(el, axis)
+       {
+               var clientScroll = EYE.getScroll();
+               var size = EYE.getSize(el);
+               if (!axis || axis == 'vertically')
+                       $(el).css(
+                               {
+                                       top: clientScroll.t + ((Math.min(clientScroll.h,clientScroll.ih) - size.hb)/2) + 'px'
+                               }
+                       );
+               if (!axis || axis == 'horizontally')
+                       $(el).css(
+                               {
+                                       left: clientScroll.l + ((Math.min(clientScroll.w,clientScroll.iw) - size.wb)/2) + 'px'
+                               }
+                       );
+       }
+});
+if (!$.easing.easeout) {
+       $.easing.easeout = function(p, n, firstNum, delta, duration) {
+               return -delta * ((n=n/duration-1)*n*n*n - 1) + firstNum;
+       };
+}
+       
+})(jQuery);
\ No newline at end of file
diff --git a/js2/mwEmbed/libClipEdit/mvClipEdit.js b/js2/mwEmbed/libClipEdit/mvClipEdit.js
new file mode 100644 (file)
index 0000000..31fdaf1
--- /dev/null
@@ -0,0 +1,782 @@
+/*
+       handles clip edit controls
+       'inoutpoints':0,        //should let you set the in and out points of clip
+       'panzoom':0,             //should allow setting keyframes and tweening modes
+       'overlays':0,            //should allow setting "locked to clip" overlay tracks
+       'audio':0                       //should allow controlling the audio volume (with keyframes)
+*/
+// set gMsg object:
+loadGM( {
+       "mwe-crop" : "Crop image",
+       "mwe-apply_crop" : "Apply crop to image",
+       "mwe-reset_crop" : "Reset crop",
+       "mwe-insert_image_page" : "Insert into page",
+       "mwe-insert_into_sequence" : "Insert into sequence",
+       "mwe-preview_insert" : "Preview insert",
+       "mwe-cancel_image_insert" : "Cancel insert",
+       "mwe-sc_fileopts" : "Clip detail edit",
+       "mwe-sc_inoutpoints" : "Set in-out points",
+       "mwe-sc_overlays" : "Overlays",
+       "mwe-sc_audio" : "Audio control",
+       "mwe-sc_duration" : "Duration",
+       "mwe-template_properties" : "Template properties",
+       "mwe-custom_title" : "Custom title",
+       "mwe-edit_properties" : "Edit properties",
+       "mwe-other_properties" : "Other properties",
+       "mwe-resource_page" : "Resource page:",
+       "mwe-set_in_out_points" : "Set in-out points",
+       "mwe-start_time" : "Start time",
+       "mwe-end_time" : "End time",
+       "mwe-preview_inout" : "Preview in-out points",
+       "mwe-edit-tools" : "Edit tools",
+       "mwe-inline-description" : "Caption",
+       "mwe-edit-video-tools" : "Edit video tools:",
+       "mwe-duration" : "Duration:"
+} );
+
+var default_clipedit_values = {
+       'rObj': null,            // the resource object
+       'clip_disp_ct':null,// target clip disp
+       'control_ct':null,       // control container
+       'media_type': null, // media type
+       'parent_ct': null,       // parent container
+
+       'p_rsdObj': null,       // parent remote search object
+       'p_seqObj': null,        // parent sequence Object
+
+       'controlActionsCb' : null, // the object that configures control Action callbacks
+
+       // The set of tools to enable (by default 'all' else an array of tools from mvClipEdit.toolset list below: 
+       'enabled_tools': 'all',
+       'edit_action': null, // the requested edit action
+       'profile': 'inpage' // the given profile either "inpage" or "sequence"
+}
+var mvClipEdit = function( iObj ) {
+       return this.init( iObj );
+};
+mvClipEdit.prototype = {
+
+       selTool:null, // selected tool
+       crop: null, // the crop values
+       base_img_src:null,
+       toolset : ['crop', 'layout'],
+       
+       init:function( iObj ) {
+               // init object:
+               for ( var i in default_clipedit_values ) {
+                       if ( iObj[i] ) {
+                               this[i] = iObj[i];
+                       }
+               }
+
+               // if media type was not supplied detect for resource if possible:
+               // @@todo more advanced detection.
+               if ( !this.media_type && this.rObj && this.rObj.type ) {
+                       if ( this.rObj.type.indexOf( "image/" ) === 0 ) {
+                               this.media_type = 'image';
+                       } else if ( this.rObj.type.indexOf( "video/" ) === 0 ) {
+                               this.media_type = 'video';
+                       } else if ( this.rObj.type.indexOf( "text/" ) === 0 ) {
+                               this.media_type = 'template';
+                       }
+               }
+               // display control:
+               if ( this.profile == 'sequence' ) {
+                       this.doEditTypesMenu();
+                       this.doDisplayEdit();
+               } else {
+                       // check the media_type:
+                       // js_log('mvClipEdit:: media type:' + this.media_type + ' base width: ' + this.rObj.width + ' bh: ' + this.rObj.height);
+                       // could seperate out into media Types objects for now just call method
+                       if ( this.media_type == 'image' ) {
+                               this.setUpImageCtrl();
+                       } else if ( this.media_type == 'video' ) {
+                               this.setUpVideoCtrl();
+                       }
+               }
+       },
+
+       // master edit types object:
+       // maybe we should refactor these into their own classes
+       // more refactor each media type should be its own class inheriting the shared baseEditType object
+       edit_types: {
+               'duration': {
+                       'media':['image', 'template'],
+                       'doEdit':function( _this, target ) {
+                               function doUpdateDur( inputElm ) {
+                                       js_log( "update duration:" + $j( inputElm ).val() );
+                                       // update the parent sequence object:
+                                       _this.rObj.dur = smilParseTime( $j( inputElm ).val() );
+                                       // update the playlist:
+                                       _this.p_seqObj.do_refresh_timeline( true );
+                               }
+                                                       
+                               $j( target ).html(
+                                               '<label for="ce_dur">' + gM( 'mwe-duration' ) + '</label>' +
+                                               '<input name="ce_dur" tabindex="1" maxlength="11" value="' +
+                                                       seconds2npt( _this.rObj.getDuration() ) +
+                                                       '" size="10"/>' +
+                                       '</div>'
+                               ).children( "input[name='ce_dur']" ).change( function() {
+                                        doUpdateDur( this );
+                               } );
+                               // Strange can't chain this binding for some reason...
+                               $j( target ).find( "input[name='ce_dur']" ).upDownTimeInputBind( doUpdateDur );
+                       }
+               },
+               'inoutpoints': {
+                       'media':['video'],
+                       'doEdit':function( _this, target ) {
+                               // do clock mouse scroll duration editor
+                               var end_ntp = ( _this.rObj.embed.end_ntp ) ? _this.rObj.embed.end_ntp : _this.rObj.embed.getDuration();
+                               if ( !end_ntp )
+                                       end_ntp = seconds2npt( _this.rObj.dur );
+
+                               var start_ntp = ( _this.rObj.embed.start_ntp ) ? _this.rObj.embed.start_ntp : seconds2npt( 0 );
+                               if ( !start_ntp )
+                                       seconds2npt( 0 );
+                               // make sure we have an end time                                
+                               if ( end_ntp ) {
+                                       $j( target ).html(
+                                               _this.getSetInOutHtml( {
+                                                       'start_ntp'     : start_ntp,
+                                                       'end_ntp'       : end_ntp
+                                               } )
+                                       );
+                                       _this.setInOutBindings();
+                               }
+                       }
+               },
+               'fileopts': {
+                       'media':['image', 'video', 'template'],
+                       'doEdit':function( _this, target ) {
+                               // if media type is template we have to query to get its URI to get its parameters
+                               if ( _this.media_type == 'template' && !_this.rObj.tVars ) {
+                                       mv_set_loading( '#sub_cliplib_ic' );
+                                       var reqObj = {
+                                               'action':'query',
+                                               'prop':'revisions',
+                                               'titles': _this.rObj.uri,
+                                               'rvprop':'content'
+                                       };
+                                       // get the interface uri from the plObject
+                                       var api_url = _this.p_seqObj.plObj.interface_url;
+                                       // first check
+                                       do_api_req( {
+                                               'data':reqObj,
+                                               'url':api_url
+                                               }, function( data ) {
+                                                       if ( typeof data.query.pages == 'undefined' )
+                                                               return _this.doEditOpts( target );
+                                                       for ( var i in data.query.pages ) {
+                                                               var page = data.query.pages[i];
+                                                               if ( !page['revisions'] || !page['revisions'][0]['*'] ) {
+                                                                       return _this.doEditOpts( target );
+                                                               } else {
+                                                                       var template_rev = page['revisions'][0]['*'];
+                                                               }
+                                                       }
+                                                       var pObj = mw.parser.pNew( template_rev );
+                                                       _this.rObj.tVars = pObj.getTemplateVars();
+                                                       // run the editor now that we have updated the tVars:                                                                                                   
+                                                       _this.doEditOpts( target );
+                                               }
+                                       );
+                               } else {
+                                       _this.doEditOpts( target );
+                               }
+                       }
+               },
+               'overlays': {
+                       'media':['image', 'video'],
+                       'doEdit':function( _this, target ) {
+                               // do clock mouse scroll duration editor
+                               $j( target ).html( '<h3>Current Overlays:</h3>Add,Remove,Modify' );
+                       }
+               },
+               'audio': {
+                       'media':['image', 'video', 'template'],
+                       'doEdit':function( _this, target ) {
+                               // do clock mouse scroll duration editor
+                               $j( target ).html( '<h3>Audio Volume:</h3>' );
+                       }
+               }
+       },
+       doEditOpts:function( target ) {
+               var _this = this;
+               // add html for rObj resource:
+               var o = '<table>' +
+                               '<tr>' +
+                                       '<td colspan="2"><b>' + gM( 'mwe-edit_properties' ) + '</b></td>' +
+                               '</tr>' +
+                               '<tr>' +
+                                       '<td>' +
+                                               gM( 'mwe-custom_title' ) +
+                                       '</td>' +
+                                       '<td><input type="text" size="15" maxwidth="255" value="';
+                                               if ( _this.rObj.title != null )
+                                                       o += _this.rObj.title;
+                                               o += '">' +
+                                       '</td>' +
+                               '</tr>';
+               if ( _this.rObj.tVars ) {
+                       var existing_p = _this.rObj.params;
+                       var testing_a = _this.rObj.tVars;
+                       // debugger;
+                       o += '<tr>' +
+                                       '<td colspan="2"><b>' + gM( 'mwe-template_properties' ) + '</b></td>' +
+                               '</tr>';
+                       for ( var i = 0; i < _this.rObj.tVars.length ; i++ ) {
+                               o += '<tr>' +
+                                       '<td>' +
+                                               _this.rObj.tVars[i] +
+                                       '</td>' +
+                                       '<td><input name="' + _this.rObj.tVars[i] + '" class="ic_tparam" type="text" size="15" maxwidth="255" value="';
+                               if ( _this.rObj.params[ _this.rObj.tVars[i] ] ) {
+                                       o += _this.rObj.params[ _this.rObj.tVars[i] ];
+                               }
+                               o += '">' +
+                                       '</td>' +
+                               '</tr>';
+                       }
+               }
+               if ( typeof wgArticlePath != 'undefined' ) {
+                       var res_src = wgArticlePath.replace( /\$1/, _this.rObj.uri );
+                       var res_title = _this.rObj.uri;
+               } else {
+                       // var res_page =
+                       var res_src = _this.rObj.src;
+                       var res_title = mw.parseUri( _this.rObj.src ).file;
+               }
+               o +=    '<tr>' +
+                                       '<td colspan="2"><b>' + gM( 'mwe-other_properties' ) + '</b></td>' +
+                               '</tr>' +
+                               '<tr>' +
+                                       '<td>' +
+                                               gM( 'mwe-resource_page' ) +
+                                       '</td>' +
+                                       '<td><a href="' + res_src  + '" ' +
+                                               ' target="new">' +
+                                                       res_title + '</a>' +
+                                       '</td>' +
+                               '</tr>';
+               o += '</table>';
+
+               $j( target ).html ( o );
+
+               // add update bindings
+               $j( target + ' .ic_tparam' ).change( function() {
+                       js_log( "updated tparam::" + $j( this ).attr( "name" ) );
+                       // update param value:
+                       _this.rObj.params[ $j( this ).attr( "name" ) ] = $j( this ).val();
+                       // re-parse & update template
+                       var template_wiki_text = '{{' + _this.rObj.uri;
+                       for ( var i = 0; i < _this.rObj.tVars.length ; i++ ) {
+
+                               template_wiki_text += "\n|" + _this.rObj.tVars[i] + ' = ' +  _this.rObj.params[ _this.rObj.tVars[i] ]  ;
+                       }
+                       template_wiki_text += "\n}}";
+                       var reqObj = {
+                                       'action':'parse',
+                                       'title' : _this.p_seqObj.plObj.mTitle,
+                                       'text'  :       template_wiki_text
+                       };
+                       $j( _this.rObj.embed ).html( mv_get_loading_img() );
+
+                       var api_url = _this.p_seqObj.plObj.interface_url;
+                       do_api_req( {
+                               'data':reqObj,
+                               'url':api_url
+                       }, function( data ) {
+                               if ( data.parse.text['*'] ) {
+                                       // update the target
+                                       $j( _this.rObj.embed ).html( data.parse.text['*'] );
+                               }
+                       } )
+               } )
+
+               // update doFocusBindings
+               if ( _this.p_seqObj )
+                       _this.p_seqObj.doFocusBindings();
+       },
+       doEditTypesMenu:function() {
+               var _this = this;
+               // add in subMenus if set
+               // check for submenu and add to item container
+               var o = '';
+               var tabc = '';
+               o += '<div id="mv_submenu_clipedit">';
+               o += '<ul>';
+               var first_tab = false;
+               $j.each( this.edit_types, function( sInx, editType ) {
+                       // check if the given editType is valid for our given media type
+                       var include = false;
+                       for ( var i = 0; i < editType.media.length; i++ ) {
+                               if ( editType.media[i] == _this.media_type ) {
+                                       include = true;
+                                       if ( !first_tab )
+                                               first_tab = sInx;
+                               }
+                       }
+                       if ( include ) {
+                               o +=    '<li>' +
+                                               '<a id="mv_smi_' + sInx + '" href="#sc_' + sInx + '">' + gM( 'mwe-sc_' + sInx ) + '</a>' +
+                                       '</li>';
+                               tabc += '<div id="sc_' + sInx + '" style="overflow:auto;" ></div>';
+                       }
+               } );
+               o += '</ul>' + tabc;
+               o += '</div>';
+               // add sub menu container with menu html:
+               $j( '#' + this.control_ct ).html( o ) ;
+               // set up bindings:
+               $j( '#mv_submenu_clipedit' ).tabs( {
+                       selected: 0,
+                       select: function( event, ui ) {
+                               _this.doDisplayEdit( $j( ui.tab ).attr( 'id' ).replace( 'mv_smi_', '' ) );
+                       }
+               } ).addClass( 'ui-tabs-vertical ui-helper-clearfix' );
+               // close left:
+               $j( "#mv_submenu_clipedit li" ).removeClass( 'ui-corner-top' ).addClass( 'ui-corner-left' );
+               // update the default edit display:
+               _this.doDisplayEdit( first_tab );
+       },
+       doDisplayEdit:function( edit_type ) {
+               if ( !edit_type )
+                       return false;
+               js_log( 'doDisplayEdit: ' + edit_type );
+
+               // do edit interface for that edit type:
+               if ( this.edit_types[ edit_type ].doEdit )
+                       this.edit_types[ edit_type ].doEdit( this, '#sc_' + edit_type );
+       },
+       setUpVideoCtrl:function() {
+               js_log( 'setUpVideoCtrl:f' );
+               var _this = this;
+               var eb = $j( '#embed_vid' ).get( 0 );
+               // turn on preview to avoid onDone actions
+               eb.preview_mode = true;
+               $j( '#' + this.control_ct ).html( '<h3>' + gM( 'mwe-edit-video-tools' ) + '</h3>' );
+               if ( eb.supportsURLTimeEncoding() ) {
+                       if ( eb.end_ntp ) {
+                               $j( '#' + this.control_ct ).append(
+                                       _this.getSetInOutHtml( {
+                                               'start_ntp'     : eb.start_ntp,
+                                               'end_ntp'       : eb.end_ntp
+                                       } )
+                               );
+                               _this.setInOutBindings();
+                       }
+               }
+               // if in a sequence we have no need for insertDesc
+               if ( !_this.p_seqObj ) {
+                       $j( '#' + this.control_ct ).append(     _this.getInsertDescHtml() );
+               }
+               // update control actions
+               this.updateInsertControlActions();
+       },
+       setInOutBindings:function() {
+               var _this = this;
+               // setup a top level shortcut: 
+               var $tp = $j( '#' + this.control_ct );
+
+               var start_sec = npt2seconds( $tp.find( '.startInOut' ).val() );
+               var end_sec   = npt2seconds( $tp.find( '.endInOut' ).val() );
+
+               // if we don't have 0 as start then assume we are in a range request and give some buffer area:
+               var min_slider =  ( start_sec - 60 < 0 ) ? 0 : start_sec - 60;
+               if ( min_slider != 0 ) {
+                       var max_slider =  end_sec + 60;
+               } else {
+                       max_slider = end_sec;
+               }
+
+               $tp.find( '.inOutSlider' ).slider( {
+                       range: true,
+                       min: min_slider,
+                       max: max_slider,
+                       animate: true,
+                       values: [start_sec, end_sec],
+                       slide: function( event, ui ) {
+                               // js_log(" vals:"+  seconds2npt( ui.values[0] ) + ' : ' + seconds2npt( ui.values[1]) );
+                               $tp.find( '.startInOut' ).val( seconds2npt( ui.values[0] ) );
+                               $tp.find( '.endInOut' ).val( seconds2npt( ui.values[1] ) );
+                       },
+                       change:function( event, ui ) {
+                               do_video_time_update( seconds2npt( ui.values[0] ), seconds2npt( ui.values[1] ) );
+                       }
+               } );
+               
+               // bind up and down press when focus on start or end 
+               $tp.find( '.startInOut' ).upDownTimeInputBind( function( inputElm ) {
+                       var s_sec = npt2seconds( $j( inputElm ).val() );
+                       var e_sec = npt2seconds( $tp.find( '.endInOut' ).val() )
+                       if ( s_sec > e_sec )
+                               $j( inputElm ).val( seconds2npt( e_sec - 1 ) );
+                       // update the slider: 
+                       var values = $tp.find( '.inOutSlider' ).slider( 'option', 'values' );
+                       js_log( 'in slider len: ' + $tp.find( '.inOutSlider' ).length );
+                       // set to 5 
+                       $tp.find( '.inOutSlider' ).slider( 'value', 10 );
+                       debugger;
+                       $tp.find( '.inOutSlider' ).slider( 'option', 'values', [s_sec, e_sec] );
+                       var values = $tp.find( '.inOutSlider' ).slider( 'option', 'values' );
+                       js_log( 'values (after update):' + values );
+               } );
+               $tp.find( '.endInOut' ).upDownTimeInputBind( function( inputElm ) {
+                       var s_sec = npt2seconds( $tp.find( '.startInOut' ).val() );
+                       var e_sec = npt2seconds( $j( inputElm ).val() );
+                       if ( e_sec < s_sec )
+                               $j( inputElm ).val(  seconds2npt( s_sec + 1 ) );
+                       // update the slider: 
+                       $tp.find( '.inOutSlider' ).slider( 'option', 'values', [ s_sec, e_sec ] );
+               } );
+               
+               // preview button:
+               $j( '#' + this.control_ct + ' .inOutPreviewClip' ).btnBind().click( function() {
+                       $j( '#embed_vid' ).get( 0 ).stop();
+                       $j( '#embed_vid' ).get( 0 ).play();
+               } );
+
+       },
+       getSetInOutHtml:function( setInt ) {
+               return '<strong>' + gM( 'mwe-set_in_out_points' ) + '</strong>' +
+                       '<table border="0" style="background: transparent; width:94%;height:50px;">' +
+                               '<tr>' +
+                                       '<td style="width:90px">' +
+                                               gM( 'mwe-start_time' ) +
+                                               '<input class="ui-widget-content ui-corner-all startInOut" size="9" value="' + setInt.start_ntp + '">' +
+                                       '</td>' +
+                                       '<td>' +
+                                               '<div class="inOutSlider"></div>' +
+                                       '</td>' +
+                                       '<td style="width:90px;text-align:right;">' +
+                                               gM( 'mwe-end_time' ) +
+                                               '<input class="ui-widget-content ui-corner-all endInOut" size="9" value="' + setInt.end_ntp + '">' +
+                                       '</td>' +
+                               '</tr>' +
+                       '</table>' +
+                       $j.btnHtml( gM( 'mwe-preview_inout' ), 'inOutPreviewClip', 'video' );
+       },
+       getInsertDescHtml:function() {
+               var o = '<h3>' + gM( 'mwe-inline-description' ) + '</h3>' +
+                                       '<textarea style="width:95%" id="mv_inline_img_desc" rows="5" cols="30">';
+               if ( this.p_rsdObj ) {
+                       // if we have a parent remote search driver let it parse the inline description
+                       o += this.rObj.pSobj.getInlineDescWiki( this.rObj );
+               }
+               o += '</textarea><br>';
+               // js_log('getInsertDescHtml: ' + o );
+               return o;
+       },
+       updateInsertControlActions:function() {
+               var _this = this;
+               var b_target =   _this.p_rsdObj.target_container + '~ .ui-dialog-buttonpane';
+               // empty the ui-dialog-buttonpane bar:
+               $j( b_target ).empty();
+               for ( var cbType in _this.controlActionsCb ) {
+                       switch( cbType ) {
+                               case 'insert_seq':
+                                       $j( b_target ).append( $j.btnHtml( gM( 'mwe-insert_into_sequence' ), 'mv_insert_sequence', 'check' ) + ' ' )
+                                               .children( '.mv_insert_sequence' )
+                                               .btnBind()
+                                               .click( function() {
+                                                       _this.applyEdit();
+                                                       _this.controlActionsCb['insert_seq'](  _this.rObj );
+                                               } );
+                               break;
+                               case 'insert':
+                                       $j( b_target ).append(  $j.btnHtml( gM( 'mwe-insert_image_page' ), 'mv_insert_image_page', 'check' ) + ' ' )
+                                               .children( '.mv_insert_image_page' )
+                                               .btnBind()
+                                               .click( function() {
+                                                       _this.applyEdit();
+                                                       _this.controlActionsCb['insert'](  _this.rObj );
+                                               } ).show( 'slow' );
+                               break;
+                               case 'preview':
+                                       $j( b_target ).append( $j.btnHtml( gM( 'mwe-preview_insert' ), 'mv_preview_insert', 'refresh' ) + ' ' )
+                                               .children( '.mv_preview_insert' )
+                                               .btnBind()
+                                               .click( function() {
+                                                       _this.applyEdit();
+                                                       _this.controlActionsCb['preview'](  _this.rObj );
+                                               } ).show( 'slow' );
+                               break;
+                               case 'cancel':
+                                       $j( b_target ).append( $j.btnHtml( gM( 'mwe-cancel_image_insert' ), 'mv_cancel_img_edit', 'close' ) + ' ' )
+                                               .children( '.mv_cancel_img_edit' )
+                                               .btnBind()
+                                               .click( function() {
+                                                       // no cancel action;
+                                                       _this.controlActionsCb['cancel'](  _this.rObj );
+                                               } ).show( 'slow' );
+                               break;
+                       }
+               }
+       },
+       applyEdit:function() {
+               var _this = this;
+               js_log( 'applyEdit::' + this.media_type );
+               if ( this.media_type == 'image' ) {
+                       this.applyCrop();
+               } else if ( this.media_type == 'video' ) {
+                       this.applyVideoAdj();
+               }
+               // copy over the desc text to the resource object
+               _this.rObj['inlineDesc'] = $j( '#mv_inline_img_desc' ).val();
+       },
+       appendTool: function( $target, tool_id ) {
+               var _this = this;
+               switch( tool_id ) {
+                       case 'layout':
+                               $target.append( '' +
+                                       '<span style="float:left;">Layout:</span>' +
+                                               '<input type="radio" name="mv_layout" id="mv_layout_left" style="float:left"></input>'+
+                                                       '<div id="mv_layout_left_img" title="' + gM( 'mwe-layout_left' ) + '"></div>' +
+                                               '<input type="radio" name="mv_layout" id="mv_layout_right" style="float:left"></input>'+
+                                                       '<div id="mv_layout_right_img" title="' + gM( 'mwe-layout_left' ) + '"></div>' +
+                                       '<hr style="clear:both" /><br/>'
+                               );
+                               // make sure the default is reflected:
+                               if ( ! _this.rObj.layout )
+                                       _this.rObj.layout = 'right';
+                               $j( '#mv_layout_' + _this.rObj.layout )[0].checked = true;
+               
+                               // left radio click
+                               $j( '#mv_layout_left,#mv_layout_left_img' ).click( function() {
+                                       $j( '#mv_layout_right' )[0].checked = false;
+                                       $j( '#mv_layout_left' )[0].checked = true;
+                                       _this.rObj.layout = 'left';
+                               } );
+                               // right radio click
+                               $j( '#mv_layout_right,#mv_layout_right_img' ).click( function() {
+                                       $j( '#mv_layout_left' )[0].checked = false;
+                                       $j( '#mv_layout_right' )[0].checked = true;
+                                       _this.rObj.layout = 'right';
+                               } );
+                       break;
+                       case 'crop':
+                               $target.append( '' +
+                                       '<div class="mv_edit_button mv_crop_button_base" id="mv_crop_button" alt="crop" title="' + gM( 'mwe-crop' ) + '"/>' +
+                                               '<a href="#" class="mv_crop_msg">' + gM( 'mwe-crop' ) + '</a> ' +
+                                               '<span style="display:none" class="mv_crop_msg_load">' + gM( 'mwe-loading_txt' ) + '</span> ' +
+                                               '<a href="#" style="display:none" class="mv_apply_crop">' + gM( 'mwe-apply_crop' ) + '</a> ' +
+                                               '<a href="#" style="display:none" class="mv_reset_crop">' + gM( 'mwe-reset_crop' ) + '</a> ' +
+                                       '<hr style="clear:both"/><br>'
+                               );
+                               // add binding: 
+                               $j( '#mv_crop_button,.mv_crop_msg,.mv_apply_crop' ).click( function() {
+                                       js_log( 'click:mv_crop_button: base width: ' + _this.rObj.width + ' bh: ' + _this.rObj.height );
+                                       if ( $j( '#mv_crop_button' ).hasClass( 'mv_crop_button_selected' ) ) {
+                                               _this.applyCrop();
+                                       } else {
+                                               js_log( 'click:turn on' );
+                                               _this.enableCrop();
+                                       }
+                               } );
+                               $j( '.mv_reset_crop' ).click( function() {
+                                       $j( '.mv_apply_crop,.mv_reset_crop' ).hide();
+                                       $j( '.mv_crop_msg' ).show();
+                                       $j( '#mv_crop_button' ).removeClass( 'mv_crop_button_selected' ).addClass( 'mv_crop_button_base' ).attr( 'title', gM( 'mwe-crop' ) );
+                                       _this.rObj.crop = null;
+                                       $j( '#' + _this.clip_disp_ct ).empty().html(
+                                               '<img src="' + _this.rObj.edit_url + '" id="rsd_edit_img">'
+                                       );
+                               } );
+                       break;
+                       case 'scale':
+                               /*scale:
+                                '<div class="mv_edit_button mv_scale_button_base" id="mv_scale_button" alt="crop" title="'+gM('mwe-scale')+'"></div>'+
+                                               '<a href="#" class="mv_scale_msg">' + gM('mwe-scale') + '</a><br>'+
+                                               '<a href="#" style="display:none" class="mv_apply_scale">' + gM('mwe-apply_scale') + '</a> '+
+                                               '<a href="#" style="display:none" class="mv_reset_scale">' + gM('mwe-reset_scale') + '</a><br> '+
+               
+                               */
+                       break;
+               }
+       },
+       setUpImageCtrl:function() {
+               var _this = this;
+               var $tool_target = $j( '#' + this.control_ct );
+               // by default apply Crop tool
+               if ( _this.enabled_tools == 'all' || _this.enabled_tools.length > 0 ) {
+                       $tool_target.append( '<h3>' + gM( 'mwe-edit-tools' ) + '</h3>' );
+                       for ( var i in _this.toolset ) {
+                               var toolid = _this.toolset[i];
+                               if ( $j.inArray( toolid, _this.enabled_tools ) != -1 || _this.enabled_tools == 'all' )
+                                       _this.appendTool( $tool_target, toolid );
+                       }
+               }
+               // add the insert description text field: 
+               $tool_target.append( _this.getInsertDescHtml() );
+               // add the actions to the 'button bar'
+               _this.updateInsertControlActions();
+       },
+       applyVideoAdj:function() {
+               js_log( 'applyVideoAdj::' );
+               $tp = $j( '#' + this.control_ct );
+
+               // be sure to "stop the video (some plugins can't have DOM elements on top of them)
+               $j( '#embed_vid' ).get( 0 ).stop();
+
+               // update video related keys
+               this.rObj['start_time'] = $tp.find( '.startInOut' ).val();
+               this.rObj['end_time']   = $tp.find( '.endInOut' ).val() ;
+
+               // do the local video adjust
+               if ( typeof this.rObj.pSobj['applyVideoAdj'] != 'undefined' ) {
+                       this.rObj.pSobj.applyVideoAdj( this.rObj );
+               }
+       },
+       applyCrop:function() {
+               var _this = this;
+               $j( '.mv_apply_crop' ).hide();
+               $j( '.mv_crop_msg' ).show();
+               $j( '#mv_crop_button' ).removeClass( 'mv_crop_button_selected' ).addClass( 'mv_crop_button_base' ).attr( 'title', gM( 'mwe-crop' ) );
+               js_log( 'click:turn off' );
+               var cat = _this.rObj;
+               if ( _this.rObj.crop ) {
+                       // empty out and display cropped:
+                       $j( '#' + _this.clip_disp_ct ).empty().html(
+                               '<div id="mv_cropcotainer" style="overflow:hidden;position:absolute;' +
+                                       'width:' + _this.rObj.crop.w + 'px;' +
+                                       'height:' + _this.rObj.crop.h + 'px;">' +
+                                       '<div id="mv_crop_img" style="position:absolute;' +
+                                               'top:-' + _this.rObj.crop.y + 'px;' +
+                                               'left:-' + _this.rObj.crop.x + 'px;">' +
+                                               '<img src="' + _this.rObj.edit_url  + '">' +
+                                       '</div>' +
+                               '</div>'
+                       );
+               }
+               return true;
+       },
+       // right now enableCrop loads "just in time"
+       // @@todo we really need an "auto loader" type system.
+       enableCrop:function() {
+               var _this = this;
+               $j( '.mv_crop_msg' ).hide();
+               $j( '.mv_crop_msg_load' ).show();
+               var doEnableCrop = function() {
+                       $j( '.mv_crop_msg_load' ).hide();
+                       $j( '.mv_reset_crop,.mv_apply_crop' ).show();
+                       $j( '#mv_crop_button' ).removeClass( 'mv_crop_button_base' ).addClass( 'mv_crop_button_selected' ).attr( 'title', gM( 'mwe-crop_done' ) );
+                       $j( '#' + _this.clip_disp_ct + ' img' ).Jcrop( {
+                                onSelect: function( c ) {
+                                        js_log( 'on select:' + c.x + ',' + c.y + ',' + c.x2 + ',' + c.y2 + ',' + c.w + ',' + c.h );
+                                        _this.rObj.crop = c;
+                                },
+                                onChange: function( c ) {
+                                }
+                       } );
+                       // temporary hack (@@todo need to debug why rsd_res_item gets moved )
+                       $j( '#clip_edit_disp .rsd_res_item' ).css( {
+                               'top':'0px',
+                               'left':'0px'
+                       } );
+               }
+               // load the jcrop library if needed:
+               mvJsLoader.doLoad( [
+                       '$j.Jcrop'
+               ], function() {
+                       doEnableCrop();
+               } );
+       }
+}
+
+// mv_lock_vid_updates defined in mv_stream.js (we need to do some more refactoring )
+if ( typeof mv_lock_vid_updates == 'undefined' )
+       mv_lock_vid_updates = false;
+
+function add_adjust_hooks( mvd_id, adj_callback ) {
+
+       var start_sec = npt2seconds( $j( '#mv_start_hr_' + mvd_id ).val() );
+       var end_sec   = npt2seconds( $j( '#mv_end_hr_' + mvd_id ).val()  );
+
+       // if we don't have 0 as start then assume we are in a range request and give some buffer area:
+       var min_slider =  ( start_sec - 60 < 0 ) ? 0 : start_sec - 60;
+       if ( min_slider != 0 ) {
+               var max_slider =  end_sec + 60;
+       } else {
+               max_slider = end_sec;
+       }
+       // pre-destroy just in case:
+       $j( '#mvd_form_' + mvd_id + ' .inOutSlider' ).slider( 'destroy' ).slider( {
+               range: true,
+               min: min_slider,
+               max: max_slider,
+               values: [start_sec, end_sec],
+               slide: function( event, ui ) {
+                       js_log( " vals:" +  seconds2npt( ui.values[0] ) + ' : ' + seconds2npt( ui.values[1] ) );
+                       $j( '#mv_start_hr_' + mvd_id ).val( seconds2npt( ui.values[0] ) );
+                       $j( '#mv_end_hr_' + mvd_id ).val( seconds2npt( ui.values[1] ) );
+               },
+               change:function( event, ui ) {
+                       do_video_time_update( seconds2npt( ui.values[0] ), seconds2npt( ui.values[1] ) );
+               }
+       } );
+       $j( '.mv_adj_hr' ).change( function() {
+               // preserve track duration for nav and seq:
+               // ie seems to crash so no interface updates for IE for the time being
+               if ( !$j.browser.msie ) {
+                       if ( mvd_id == 'nav' || mvd_id == 'seq' ) {
+                               add_adjust_hooks( mvd_id ); // (no adj_callback)
+                       } else {
+                               add_adjust_hooks( mvd_id )
+                       }
+               }
+               // update the video time for onChange
+               do_video_time_update( $j( '#mv_start_hr_' + mvd_id ).val(), $j( '#mv_end_hr_' + mvd_id ).val() );
+       } );
+}
+
+function do_video_time_update( start_time, end_time, mvd_id )  {
+       js_log( 'do_video_time_update: ' + start_time + ' ' + end_time );
+       if ( mv_lock_vid_updates == false ) {
+               // update the vid title:
+               $j( '#mv_videoPlayerTime' ).html( start_time + ' to ' + end_time );
+               var ebvid = $j( '#embed_vid' ).get( 0 );
+               if ( ebvid ) {
+                       if ( ebvid.isPaused() )
+                               ebvid.stop();
+                       ebvid.updateVideoTime( start_time, end_time );
+                       js_log( 'update thumb: ' + start_time );
+                       ebvid.updateThumbTimeNTP( start_time );
+               }
+       }
+}
+
+// some custom jquery bindings: 
+( function( $ ) {
+       $.fn.upDownTimeInputBind = function( inputCB ) {
+               $( this.selector ).unbind( 'focus' ).focus( function() {
+                       var doDelayCall = true;
+                       $( this ).addClass( 'ui-state-focus' );
+                       // bind up down keys
+                       $( this ).unbind( 'keydown' ).keydown( function ( e ) {
+                               var sec = npt2seconds( $j( this ).val() );
+                               var k = e.which;
+                               if ( k == 38 ) {// up                                                                                           
+                                       $( this ).val( seconds2npt( sec + 1 ) );
+                               } else if ( k == 40 ) { // down                 
+                                       var sval = ( ( sec - 1 ) < 0 ) ? 0 : ( sec - 1 )
+                                       $( this ).val(  seconds2npt( sval ) );
+                               }
+                               // set the delay updates:
+                               if ( k == 38 || k == 40 ) {
+                                       var _inputElm = this;
+                                       if ( doDelayCall ) {
+                                               setTimeout( function() {
+                                                       inputCB( _inputElm );
+                                                       doDelayCall = true;
+                                               }, 500 );
+                                               doDelayCall = false;
+                                       }
+                               }
+                       } );
+               } ).unbind( 'blur' ).blur( function() {
+                       $( this ).removeClass( 'ui-state-focus' );
+               } );
+       }
+} )( jQuery );
diff --git a/js2/mwEmbed/libClipEdit/pixastic-editor/editor.js b/js2/mwEmbed/libClipEdit/pixastic-editor/editor.js
new file mode 100644 (file)
index 0000000..6789531
--- /dev/null
@@ -0,0 +1,968 @@
+
+var PixasticEditor = (function () {
+
+       var $frame;     // iframe container element
+       var $editor;    // editor container element
+
+       // various UI structures
+       var accordionElements = {};
+       var tabElements = {};
+       var activeTabId;
+       var $activeTabContent;
+
+       var isRunning = false;
+
+       var $loadingScreen;
+
+       var $imageCanvas;       // the canvas holding the current state of the image
+       var $displayCanvas;     // the canvas element displayed on the screen, also the working canvas (where preview operations are performed)
+       var imageCtx;
+
+       var imageWidth = 0;     // dimensions of the current image state
+       var imageHeight = 0;
+
+       var undoImages = [];    // canvas elements holding previous image states
+       var undoLevels = 10;
+
+       var doc;
+
+       var $;
+
+       // test for valid file formats for toDataURL()
+       // we do that by calling it with each of the mime types in testFormats
+       // and then doing string checking on the resulting data: URI to see if it succeeded
+       var saveFormats = [];
+       var testFormats = [["image/jpeg", "JPEG"], ["image/png", "PNG"]];
+       var testCanvas = document.createElement("canvas");
+       if (testCanvas.toDataURL) {
+               testCanvas.width = testCanvas.height = 1;
+               for (var i=0;i<testFormats.length;i++) {
+                       var data = testCanvas.toDataURL(testFormats[i][0]);
+                       if (data.substr(0, 5 + testFormats[i][0].length) == "data:" + testFormats[i][0])
+                               saveFormats.push({mime:testFormats[i][0], name:testFormats[i][1]});
+               }
+       }
+
+
+       // pops up an error dialog with the specified text (errTxt),
+       // if no context is provided, the name of the calling function is used.
+       // The final message is returned for easy throwing of actual errors
+       function errorDialog(errTxt, context) {
+               if (!($editor && $editor.get && $editor.get(0)))
+                       throw new Error("errorDialog(): $editor doesn't exist");
+
+               var caller = errorDialog.caller.toString().split(" ")[1];
+               caller = caller.substring(0, caller.indexOf("("));
+               context = context || caller;
+               errTxt = context + "(): " + errTxt;
+               var dialog = $j("<div></div>", doc)
+                       .addClass("error-dialog")
+                       .attr("title", "Oops!")
+                       .html(errTxt)
+                       .dialog();
+               // the dialog is added outside the Pixastic container, so get it back in.
+               var dialogParent = $j(dialog.get(0).parentNode);
+               dialogParent.appendTo($editor);
+
+               return errTxt;
+       }
+       
+       function enableTab(id, refresh) {
+               if (id == activeTabId && !refresh)
+                       return;
+
+               activeTabId = id;
+
+               var activeIndex = 0;
+
+               if ($activeTabContent) {
+                       if ($activeTabContent.get(0)) {
+                               var $parent = $j($activeTabContent.get(0).parentNode);
+                               activeIndex = $parent.data("accordionindex");
+                               if ($parent.data("ondeactivate")) {
+                                       $parent.data("ondeactivate")();
+                               }
+                               if ($parent.data("previewCheckbox"))
+                                       $parent.data("previewCheckbox").attr("checked", false);
+                               $parent.data("uidesc").previewEnabled = false;
+                               if ($parent.data("uidesc").forcePreview)
+                                       $parent.data("uidesc").previewEnabled = true;
+                       }
+               }
+
+
+               for (var a in accordionElements) {
+                       if (accordionElements.hasOwnProperty(a)) {
+                               accordionElements[a].accordion("option", "animated", false);
+                               accordionElements[a].accordion("activate", -1);
+                               accordionElements[a].hide();
+                               tabElements[a].removeClass("active");
+
+                       }
+               }
+
+               accordionElements[id].accordion("option", "animated", false);
+               accordionElements[id].accordion("activate", refresh ? activeIndex : 0);
+               tabElements[id].addClass("active");
+               accordionElements[id].show();
+               accordionElements[id].accordion("option", "animated", "slide");
+               resetDisplayCanvas();
+       }
+
+       // revert to a previous image state
+       function undo(idx) {
+               var undoImage = undoImages[idx];
+
+               if (!undoImage) 
+                       throw new Error(errorDialog("Invalid undo state"));
+               if (!($imageCanvas && $imageCanvas.get && $imageCanvas.get(0)))
+                       throw new Error(errorDialog("$imageCanvas doesn't exist"));
+
+               var canvas = $imageCanvas.get(0);
+               addUndo(canvas);
+               canvas.width = imageWidth = undoImage.width;
+               canvas.height = imageHeight = undoImage.height;
+               canvas.getContext("2d").drawImage(undoImage,0,0);
+
+               enableTab(activeTabId, true);
+               resetDisplayCanvas();
+       }
+
+       function addUndo(canvasElement) {
+               if (!canvasElement)
+                       throw new Error(errorDialog("No undo image state provided"));
+
+               if (undoImages.length == undoLevels) {
+                       undoImages.shift();
+               }
+               var undoCanvas = document.createElement("canvas");
+               undoCanvas.width = canvasElement.width;
+               undoCanvas.height = canvasElement.height;
+               undoCanvas.getContext("2d").drawImage(canvasElement,0,0);
+               $j(undoCanvas).addClass("undo-canvas");
+               undoImages.push(undoCanvas);
+               updateUndoList();
+       }
+
+       function updateUndoList() {
+               var $listCtr = $j("#undo-bar", doc)
+                       .html("");
+
+               var ctrHeight = $listCtr.height();
+
+               var $testCanvas = $j("<canvas></canvas>", doc)
+                       .addClass("undo-canvas-small")
+                       .addClass("far-far-away")
+                       .appendTo("body");
+
+               var canvasHeight = $testCanvas.height();
+               var canvasWidth = $testCanvas.width();
+               var canvasCSSHeight = canvasHeight + parseInt($testCanvas.css("margin-top"),10) + parseInt($testCanvas.css("margin-bottom"),10);
+
+               $testCanvas.remove();
+
+               var undoRatio = canvasWidth / canvasHeight;
+
+               for (var i=undoImages.length-1;i>=0;i--) {
+                       (function(){
+                               var canvas = document.createElement("canvas");
+                               $j(canvas)
+                                       .addClass("undo-canvas-small")
+                                       .attr("width", canvasWidth)
+                                       .attr("height", canvasHeight);
+
+                               var image = undoImages[i];
+                               $j(image).show();
+                               
+                               var undoWidth, undoHeight;
+                               var imageRatio = image.width / image.height;
+
+                               if (imageRatio > undoRatio) {   // image too wide
+                                       undoWidth = canvasWidth;
+                                       undoHeight = canvasWidth / imageRatio;
+                               } else {
+                                       undoWidth = canvasHeight * imageRatio;
+                                       undoHeight = canvasHeight;
+                               }
+
+                               var restWidth = canvasWidth - undoWidth;
+                               var restHeight = canvasHeight - undoHeight;
+
+                               canvas.getContext("2d").drawImage(
+                                       image,
+                                       0,0,image.width,image.height,
+                                       restWidth*0.5, restHeight*0.5,
+                                       undoWidth, undoHeight
+                               );
+
+
+                               $link = $j("<a href='#'></a>", doc)
+                                       .addClass("undo-link")
+                                       .appendTo($listCtr)
+                                       .mouseover(function(){ $j(this).addClass("hover") })
+                                       .mouseout(function(){ $j(this).removeClass("hover") });
+                               $j(canvas).appendTo($link);
+
+                               var displayShowing;
+                               var undoIndex = i;
+                               $link.click(function() {
+                                       $j(image).hide();
+                                       $j(image).remove();
+                                       undo(undoIndex);
+                                       if (displayShowing)
+                                               $displayCanvas.show();
+                                       $j(".jcrop-holder", doc).show();
+                               });
+
+                               $link.mouseover(function() {
+                                       displayShowing = $displayCanvas.css("display") != "none";
+                                       var $imagectr = $j("#image-container", doc);
+
+                                       $j(".jcrop-holder", doc).hide();
+                                       $displayCanvas.hide();
+                                       $j(image).appendTo($imagectr);
+
+                                       var h1 = $j("#image-area", doc).height();
+                                       var h2 = image.height;
+                                       var m = Math.max(0, (h1 - h2) / 2);
+                                       $imagectr.css("marginTop", m);
+                       
+                                       $imagectr.height(image.height);
+                               });
+
+                               $link.mouseout(function() {
+                                       $j(image).remove();
+                                       if (displayShowing)
+                                               $displayCanvas.show();
+                                       $j(".jcrop-holder", doc).show();
+                                       updateDisplayCanvas();
+                               });
+
+
+                               $j(canvas).attr("title", "Click to revert to this previous image");
+
+                       })();
+               }
+       }
+
+
+       function applyAction(id, options, afteraction) {
+               if (!Pixastic.Actions[id])
+                       throw new Error("applyAction(): unknown action [" + id + "]");
+
+               $j("#action-bar-overlay", doc).show();
+
+               setTimeout(function() {
+                       options.leaveDOM = true;
+                       var canvasElement = $imageCanvas.get(0);
+                       addUndo(canvasElement)
+       
+                       var res = Pixastic.process(
+                               canvasElement, id, options,
+                               function(resCanvas) {
+                                       canvasElement.width = imageWidth = resCanvas.width;
+                                       canvasElement.height = imageHeight = resCanvas.height;
+       
+                                       var ctx = canvasElement.getContext("2d");
+                                       ctx.clearRect(0,0,imageWidth,imageHeight);
+                                       ctx.drawImage(resCanvas,0,0);
+                                       $imageCanvas = $j(canvasElement);
+                                       resetDisplayCanvas();
+       
+                                       $j("#action-bar-overlay", doc).hide();
+
+                                       if (afteraction)
+                                               afteraction();
+                               }
+                       );
+                       if (!res)
+                               throw new Error("applyAction(): Pixastic.process() failed for action [" + id + "]");
+               },1);
+       }
+
+
+       function previewAction(id, options, afteraction) {
+               if (!Pixastic.Actions[id])
+                       throw new Error("applyAction(): unknown action [" + id + "]");
+
+               $j("#action-bar-overlay", doc).show();
+
+               resetDisplayCanvas();
+
+               options.leaveDOM = true;
+               var canvasElement = $displayCanvas.get(0);
+
+               var res = Pixastic.process(
+                       canvasElement, id, options,
+                       function(resCanvas) {
+
+                               canvasElement.width = resCanvas.width;
+                               canvasElement.height = resCanvas.height;
+
+                               var ctx = canvasElement.getContext("2d");
+                               ctx.clearRect(0,0,canvasElement.width,canvasElement.height);
+                               ctx.drawImage(resCanvas,0,0);
+                               updateDisplayCanvas();
+                               updateOverlay();
+
+                               $j("#action-bar-overlay", doc).hide();
+
+                               if (afteraction)
+                                       afteraction();
+                       }
+               );
+       }
+
+       var onwindowresize = function() {
+               updateDisplayCanvas();
+               updateOverlay();
+       }
+
+       var baseUrl = ""
+
+       function buildEditor() {
+               var styles = [
+                       "jquery-ui-1.7.1.custom.css",
+                       "jquery.Jcrop.css",
+                       "pixastic.css"
+               ];
+
+               for (var i=0;i<styles.length;i++) {
+                       var s = doc.createElement("link");
+                       s.href = baseUrl + styles[i];
+                       s.type = "text/css";
+                       s.rel = "stylesheet";
+                       doc.getElementsByTagName("head")[0].appendChild( s );
+               }
+
+               undoImages = [];
+               accordionElements = {};
+               tabElements = {};
+               activeTabId = -1;
+               $activeTabContent = null;
+
+               // setup DOM UI skeleton
+               $editor = $j("<div />", doc)
+                       .attr("id", "pixastic-editor")
+                       .appendTo($j(doc.body));
+
+               $editor.append(
+                       $j("<div id='background' />", doc),
+                       $j("<div id='edit-ctr-1' />", doc).append(
+                               $j("<div id='edit-ctr-2' />", doc).append(
+                                       $j("<div id='controls-bar' />", doc).append(
+                                               $j("<div id='action-bar' />", doc).append(
+                                                       $j("<div id='action-bar-overlay' />", doc)
+                                               ),
+                                               $j("<div id='undo-bar' />", doc)
+                                       ),
+                                       $j("<div id='image-area' />", doc).append(
+                                               $j("<div id='image-area-sub' />", doc).append(
+                                                       $j("<div id='image-container' />", doc),
+                                                       $j("<div id='image-overlay-container' />", doc).append(
+                                                               $j("<div id='image-overlay' />", doc)
+                                                       )
+                                               )
+                                       )
+                               )
+                       ),
+                       $j("<div id='main-bar' />", doc),
+                       $j("<div id='powered-by-pixastic'><a href=\"http://www.pixastic.com/\" target=\"_blank\">Powered by Pixastic</a></div>", doc)
+               );
+
+               $j("#image-container", doc).append(
+                       $displayCanvas = $j("<canvas />", doc)
+                               .addClass("display-canvas")
+               );
+
+               // loop through all  defined UI action controls
+               var tabs = PixasticEditor.UI.data.tabs;
+
+               for (var i=0;i<tabs.length;i++) {
+                       (function() {
+       
+                       var tab = tabs[i];
+
+                       var $tabElement = $j("<a href=\"#\">" + tab.title + "</a>", doc)
+                               .attr("id", "main-tab-button-" + tab.id)
+                               .addClass("main-tab")
+                               .click(function() {
+                                       enableTab(tab.id);
+                               })
+                               .mouseover(function(){ $j(this).addClass("hover") })
+                               .mouseout(function(){ $j(this).removeClass("hover") });
+       
+                       $j("#main-bar", doc).append($tabElement);
+
+                       tabElements[tab.id] = $tabElement;
+
+                       var $menu = $j("<div/>", doc);
+                       accordionElements[tab.id] = $menu;
+
+                       for (var j=0;j<tab.actions.length;j++) {
+                               (function() {
+
+                               var action = tab.actions[j];
+
+                               var $actionElement = $j("<div><h3><a href=\"#\">" + action.title + "</a></h3></div>", doc)
+
+                               $menu.append($actionElement);
+
+                               var $content = $j("<div></div>", doc)
+                                       .attr("id", "pixastic-action-tab-content-" + action.id)
+                                       .appendTo($actionElement);
+
+                               var controlOptions = [];
+
+                               action.previewEnabled = false;
+                               if (action.forcePreview)
+                                       action.previewEnabled = true;
+
+                               function togglePreview(enable, doAction) {
+                                       if (enable && !action.previewEnabled && doAction)
+                                               doAction(true);
+                                       if (!enable && action.previewEnabled)
+                                               resetDisplayCanvas();
+                       
+                                       action.previewEnabled = enable;
+                               }
+
+                               var reset = function() {
+                                       for (var i in controlOptions) {
+                                               if (controlOptions.hasOwnProperty(i)) {
+                                                       controlOptions[i].reset();
+                                               }
+                                       }
+                                       if (action.previewEnabled)
+                                               doAction(true);
+                               }
+                               var doAction = function(isPreview) {
+                                       var options = {};
+                                       for (var i in controlOptions) {
+                                               if (controlOptions.hasOwnProperty(i)) {
+                                                       options[i] = controlOptions[i].valueField.val();
+                                               }
+                                       }
+
+                                       var afteraction = function() {
+                                               if (action.onafteraction)
+                                                       action.onafteraction(action, isPreview);
+                                               if (!isPreview)
+                                                       resetDisplayCanvas();
+       
+                                               if (!isPreview && !action.forcePreview) {
+                                                       $j("#pixastic-input-preview-" + action.id, doc).attr("checked", false);
+                                                       togglePreview(false);
+                                                       reset();
+                                               }
+                                       }
+
+                                       if (isPreview) {
+                                               previewAction(action.id, options, afteraction);
+                                       } else {
+                                               applyAction(action.id, options, afteraction);
+                                       }
+
+                               }
+
+                               var hadInputs = false;
+
+                               if (action.controls) {
+                                       var onChange = function() {};
+                                       if (action.isAction && action.preview) {
+                                               onChange = function() {
+                                                       if (action.previewEnabled)
+                                                               doAction(true)
+                                               };
+                                       }
+
+                                       for (var k=0;k<action.controls.length;k++) {
+                                               var control = action.controls[k];
+                                               if (typeof control.defaultValue != "function") {
+                                                       (function(){
+                                                       var defVal = control.defaultValue;
+                                                       control.defaultValue = function() {
+                                                               return defVal;
+                                                       }
+                                                       })();
+                                               }
+                                               var controlId = action.id + "-" + control.option;
+
+                                               if (control.type != "output")
+                                                       hadInputs = true;
+
+                                               switch (control.type) {
+                                                       case "number" :
+                                                               switch (control.ui) {
+                                                                       case "slider" : 
+                                                                               var slider = PixasticEditor.UI.makeSlider(
+                                                                                       control.label, controlId, 
+                                                                                       control.range[0], control.range[1], control.step, control.defaultValue, onChange
+                                                                               );
+               
+                                                                               slider.container.appendTo($content);
+                                                                               controlOptions[control.option] = slider;
+                                                                               break;
+                                                                       case "text" : 
+                                                                               var text = PixasticEditor.UI.makeNumericInput(
+                                                                                       control.label, control.labelRight, controlId, 
+                                                                                       control.range[0], control.range[1], control.step, control.defaultValue, onChange
+                                                                               );
+                                                                               text.container.appendTo($content);
+                                                                               controlOptions[control.option] = text;
+                                                                               break;
+                                                               }
+                                                               break;
+                                                       case "boolean" :
+                                                               switch (control.ui) {
+                                                                       case "checkbox" : 
+                                                                               var checkbox = PixasticEditor.UI.makeCheckbox(
+                                                                                       control.label, controlId, control.defaultValue, onChange
+                                                                               );
+               
+                                                                               checkbox.container.appendTo($content);
+                                                                               controlOptions[control.option] = checkbox;
+                                                                               break;
+                                                               }
+                                                       case "string" :
+                                                               switch (control.ui) {
+                                                                       case "select" : 
+                                                                               var select = PixasticEditor.UI.makeSelect(
+                                                                                       control.label, controlId, control.values, control.defaultValue, onChange
+                                                                               );
+               
+                                                                               select.container.appendTo($content);
+                                                                               controlOptions[control.option] = select;
+                                                                               break;
+                                                               }
+                                                               break;
+                                                       case "output" :
+                                                               var outputText = $j("<div></div>", doc)
+                                                                       .addClass("ui-action-output")
+                                                                       .html(control.content)
+                                                                       .appendTo($content);
+                                                               break;
+                                               }
+                                       }
+                               }
+
+                               if (action.isAction) {
+
+                                       var $applyButton = PixasticEditor.UI.makeButton("Apply")
+                                               .addClass("pixastic-option-button-apply")
+                                               .click(function() {doAction();});
+
+                                       $content.append($applyButton);
+
+                                       if (hadInputs) {
+                                               var $resetButton = PixasticEditor.UI.makeButton("Reset")
+                                                       .addClass("pixastic-option-button-reset")
+                                                       .click(reset);
+       
+                                               $content.append($resetButton)
+                                       }
+
+                                       if (action.preview && !action.forcePreview) {
+                                               var $checkctr = $j("<div></div>", doc)
+                                                       .addClass("ui-checkbox-container")
+                                                       .addClass("ui-preview-checkbox-container");
+
+                                               var $label = $j("<label></label>", doc)
+                                                       .addClass("ui-checkbox-label")
+                                                       .attr("for", "pixastic-input-preview-" + action.id)
+                                                       .html("Preview:")
+                                                       .appendTo($checkctr);
+
+                                               var $checkbox = $j("<input type=\"checkbox\"></input>", doc)
+                                                       .addClass("ui-checkbox")
+                                                       .attr("id", "pixastic-input-preview-" + action.id)
+                                                       .appendTo($checkctr)
+                                                       .change(function() {
+                                                               togglePreview(this.checked, doAction)
+                                                       });
+
+                                               $content.append($checkctr);
+
+                                               $content.data("previewCheckbox", $checkbox);
+                                       }
+
+                               }
+
+
+                               if (typeof action.content == "function") {
+                                       action.content($content);
+                               }
+
+                               // stupid hack to make it possible to get $content in change event (below)
+                               $j("<span></span>", doc).appendTo($content);
+
+                               $content.data("controlOptions", controlOptions);
+                               $content.data("onactivate", action.onactivate);
+                               $content.data("ondeactivate", action.ondeactivate);
+                               $content.data("onoverlayupdate", action.onoverlayupdate);
+                               $content.data("accordionindex", j);
+                               $content.data("uidesc", action);
+
+                               })();
+                       }
+       
+                       $j("#action-bar", doc).append($menu);
+
+                       $menu.hide().accordion({
+                               header: "h3",
+                               autoHeight : false,
+                               collapsible : true,
+                               active: -1
+                       })
+                       .bind("accordionchange", 
+                               function(event, ui) {
+                                       resetDisplayCanvas();
+
+                                       // oldContent / newContent are arrays of whatever elements are present in the content area
+                                       // We need the parent element (the one holding the content) but if there is no content, how do we get it?
+                                       // fixed above by always appending a <span> but that's ugly and needs to be done in some other way
+                                       if (ui.oldContent.get(0)) {
+                                               var $parent = $j(ui.oldContent.get(0).parentNode);
+                                               if ($parent.data("ondeactivate")) {
+                                                       $parent.data("ondeactivate")();
+                                               }
+                                       }
+                                       $activeTabContent = ui.newContent;
+
+                                       if (ui.newContent.get(0)) {
+                                               var $parent = $j(ui.newContent.get(0).parentNode);
+                                               if ($parent.data("previewCheckbox"))
+                                                       $parent.data("previewCheckbox").attr("checked", false);
+                                               $parent.data("uidesc").previewEnabled = false;
+                                               if ($parent.data("uidesc").forcePreview)
+                                                       $parent.data("uidesc").previewEnabled = true;
+
+                                               var controlOptions = $parent.data("controlOptions");
+                                               for (var i in controlOptions) {
+                                                       if (controlOptions.hasOwnProperty(i)) {
+                                                               controlOptions[i].reset();
+                                                       }
+                                               }
+                                               if ($parent.data("onactivate")) {
+                                                       $parent.data("onactivate")();
+                                               }
+                                       }
+                                       updateDisplayCanvas();
+
+                               }
+                       );
+
+       
+                       })();
+               }
+
+               $j(window).bind("resize", onwindowresize);
+       }
+
+       function showLoadingScreen() {
+               if ($loadingScreen) {
+                       $loadingScreen.show();
+                       return;
+               }
+               $loadingScreen = $j("<div id=\"loading-screen\" />")
+               var $ctr = $j("<div id=\"loading-screen-cell\" />");
+               $j("<div />")
+                       .addClass("spinner")
+                       .appendTo($ctr);
+               $loadingScreen.append($ctr);
+               $loadingScreen.appendTo("body");
+       }
+
+       function hideLoadingScreen() {
+               setTimeout(function() {
+                       $loadingScreen.hide();
+               }, 1);
+       }
+
+       var oldScrollLeft;
+       var oldScrollTop;
+       var oldOverflow;
+
+       // fire it up
+       function init(callback) {
+               isRunning = true;
+
+               showLoadingScreen();
+
+               oldScrollLeft = document.body.scrollLeft;
+               oldScrollTop = document.body.scrollTop;
+               oldOverflow = document.body.style.overflow;
+
+               document.body.scrollLeft = 0;
+               document.body.scrollTop = 0;
+               document.body.style.overflow = "hidden";
+
+               $frame = $j("<iframe />");
+               $frame.hide();
+               $frame.css({
+                       position : "absolute",
+                       left : document.body.scrollLeft + "px",
+                       top : document.body.scrollTop + "px",
+                       width : "100%",
+                       height : "100%",
+                       zIndex : "11"
+               });
+               $frame.load(function(){
+                       doc = $frame.get(0).contentDocument;
+
+                       buildEditor();
+                       callback();
+                       $frame.show();
+                       hideLoadingScreen();
+                       setTimeout(function(){
+                               updateDisplayCanvas();
+                       },10);
+               });
+               $frame.appendTo("body");
+       }
+
+       // unload the editor, remove all elements added to the page and restore whatever properties we messed with
+       function unload() {
+               $j(window).unbind("resize", onwindowresize);
+               $frame.hide();
+               $editor.hide();
+               $editor.remove();
+               $frame.remove();
+
+               document.body.scrollLeft = oldScrollLeft;
+               document.body.scrollTop = oldScrollTop;
+               document.body.style.overflow = oldOverflow;
+
+               isRunning = false;
+       }
+
+
+       // resets the display canvas (clears the canvas and repaints the current state)
+       // then updates display and overlay
+       function resetDisplayCanvas() {
+               if (!($displayCanvas && $displayCanvas.get))    throw new Error(errorDialog("$displayCanvas doesn't exist"));
+               if (!($imageCanvas && $imageCanvas.get))        throw new Error(errorDialog("$imageCanvas doesn't exist"));
+
+               var display = $displayCanvas.get(0);
+               var image = $imageCanvas.get(0);
+
+               if (!display)   throw new Error(errorDialog("resetDisplayCanvas(): No elements in $displayCanvas"));
+               if (!image)     throw new Error(errorDialog("resetDisplayCanvas(): No elements in $imageCanvas"));
+
+               display.width = imageWidth;
+               display.height = imageHeight;
+               display.getContext("2d").drawImage( image, 0, 0 );
+
+               updateDisplayCanvas();
+               updateOverlay();
+       }
+
+       // updates the display by resetting the height and margin of the image container
+       // this is mainly to keep vertical centering
+       function updateDisplayCanvas() {
+               var $imageCtr = $j("#image-container", doc);
+               var $editArea = $j("#image-area", doc);
+
+               if (!$imageCtr.get(0))          throw new Error(errorDialog("updateDisplayCanvas(): $imageCtr doesn't exist"));
+               if (!$displayCanvas.get(0))     throw new Error(errorDialog("updateDisplayCanvas(): $displayCanvas doesn't exist"));
+               if (!$editArea.get(0))          throw new Error(errorDialog("updateDisplayCanvas(): $editArea doesn't exist"));
+
+               var h2 = $displayCanvas.get(0).height;
+               var h1 = $j("#image-area", doc).height();
+               var m = Math.max(0, (h1 - h2) / 2);
+               $imageCtr.height(h2);
+               $imageCtr.css("marginTop", m);
+       }
+
+       // basically the same as updateDisplayCanvas but for the image overlay
+       function updateOverlay() {
+               var $overlay = $j("#image-overlay-container", doc);
+               var $imagectr = $j("#image-container", doc);
+               $overlay.height($imagectr.height());
+               $overlay.css("marginTop", $imagectr.css("marginTop"));
+
+               if ($activeTabContent && $activeTabContent.get(0)) {
+                       var $tabContent = $j($activeTabContent.get(0).parentNode);
+                       if (typeof $tabContent.data("onoverlayupdate") == "function")
+                               $tabContent.data("onoverlayupdate")();
+               }
+       }
+
+       var imageIsLoading = false;
+       var originalImageElement;
+       var $tmpImg;
+
+       function loadImage(imgEl) {
+               if (imageIsLoading) 
+                       return;
+
+               imageIsLoading = true;
+
+               originalImageElement = imgEl;
+
+               $imageCanvas = $j("<canvas />", doc);
+               imageCtx = $imageCanvas.get(0).getContext("2d");
+
+               imageWidth = 0;
+               imageHeight = 0;
+               $imageCanvas.attr("width", 0);
+               $imageCanvas.attr("height", 0);
+
+               if (imgEl.tagName.toLowerCase() == "img" && !imgEl._pixasticCanvas) {
+                       var onload = function(el) {
+                               imageWidth = el.offsetWidth;
+                               imageHeight = el.offsetHeight;
+                               $imageCanvas.attr("width", imageWidth);
+                               $imageCanvas.attr("height", imageHeight);
+                               imageCtx.drawImage(el,0,0);
+                               $tmpImg.remove();
+                               imageIsLoading = false;
+                               enableTab("reshape");
+                               setTimeout(function() {
+                                       resetDisplayCanvas();
+                               }, 10);
+                       }
+                       $tmpImg = $j("<img />", doc)
+                               .css("position", "absolute")
+                               .css("left", "-9999px")
+                               .css("top", "-9999px")
+                               .appendTo("body")
+                               .load(function(){onload(this);})
+                               .error(function(){
+                                       throw new Error("Could not load temporary copy image. Is provided image valid?");
+                                       unload();
+                               })
+                               .attr("src", imgEl.src);
+                               if ($tmpImg.attr("complete")) {
+                                       onload($tmpImg.get(0));
+                               }
+               } else {
+                       var $canvas = imgEl._pixasticCanvas || imgEl;
+                       imageWidth = $canvas.attr("width");
+                       imageHeight = $canvas.attr("height");
+                       $imageCanvas.attr("width", imageWidth);
+                       $imageCanvas.attr("height", imageHeight);
+                       imageCtx.drawImage($canvas.get(0), 0, 0);
+                       imageIsLoading = false;
+                       enableTab("reshape");
+                       resetDisplayCanvas();
+               }
+       }
+
+       // return public interface
+       return {
+               /*
+               // don't call. For now we must load the image immediately via load()
+               loadImage : function(imgEl) {
+                       if (!isRunning) return false;
+                       loadImage(imgEl);
+               },
+               */
+               saveToPage : function() {
+                       if (!isRunning) throw new Error("PixasticEditor::saveToPage(): Editor is not running");
+
+                       var $canvas = PixasticEditor.getImageCanvas();
+                       var img = PixasticEditor.getOriginalImage();
+                       if (img.tagName.toLowerCase() == "canvas") {
+                               img.width = $canvas.attr("width");
+                               img.height = $canvas.attr("height");
+                               img.getContext("2d").drawImage($canvas.get(0), 0, 0);
+                       } else {
+                               img.src = PixasticEditor.getDataURI();
+                       }
+                       img._pixasticCanvas = PixasticEditor.getImageCanvas();
+               },
+               load : function(img, customBaseUrl) {
+                       if (isRunning) return false;
+
+                       if (!img)
+                               throw new Error("Must be called with an image or canvas as its first argument", "PixasticEditor::load")
+
+                       $ = PixasticEditor.jQuery;
+
+                       baseUrl = customBaseUrl || "http://www.pixastic.com/editor-test/";
+
+                       init(function() {
+                               if (img && img.tagName.toLowerCase() == "img" || img.tagName.toLowerCase() == "canvas") {
+                                       loadImage(img);
+                               }
+                       });
+               },
+
+               unload : function() {
+                       if (!isRunning) throw new Error("PixasticEditor::unload(): Editor is not running");
+                       unload();
+               },
+
+               getDocument : function() {
+                       if (!isRunning) throw new Error("PixasticEditor::getDocument(): Editor is not running");
+
+                       return doc;
+               },
+
+               validSaveFormats : function() {
+                       return saveFormats;
+               },
+
+               getOriginalImage : function() {
+                       if (!isRunning) throw new Error("PixasticEditor::getOriginalImage(): Editor is not running");
+                       return originalImageElement;
+               },
+
+               getDataURI : function(mime) {
+                       if (!isRunning) throw new Error("PixasticEditor::getDataURI(): Editor is not running");
+
+                       if (!($imageCanvas && $imageCanvas.get && $imageCanvas.get(0)))
+                               throw new Error(errorDialog("$imageCanvas doesn't exist", "getImageCanvas"));
+
+                       return $imageCanvas.get(0).toDataURL(mime||"image/png");
+               },
+
+               getImageCanvas : function() {
+                       if (!isRunning) throw new Error("PixasticEditor::getImageCanvas(): Editor is not running");
+
+                       if (!($imageCanvas && $imageCanvas.get && $imageCanvas.get(0)))
+                               throw new Error(errorDialog("$imageCanvas doesn't exist", "getImageCanvas"));
+
+                       return $imageCanvas;
+               },
+               getOverlay : function() {
+                       if (!isRunning) throw new Error("PixasticEditor::getOverlay(): Editor is not running");
+
+                       return $j("#image-overlay", doc);
+               },
+               getDisplayCanvas : function() {
+                       if (!isRunning) throw new Error("PixasticEditor::getDisplayCanvas(): Editor is not running");
+
+                       if (!($displayCanvas && $displayCanvas.get && $displayCanvas.get(0)))
+                               throw new Error(errorDialog("$displayCanvas doesn't exist", "getDisplayCanvas"));
+                       return $displayCanvas;
+               },
+               getDisplayWidth : function() {
+                       if (!isRunning) throw new Error("PixasticEditor::getDisplayWidth(): Editor is not running");
+
+                       return displayWidth;
+               },
+               getDisplayHeight : function() {
+                       if (!isRunning) throw new Error("PixasticEditor::getDisplayHeight(): Editor is not running");
+
+                       return displayHeight;
+               },
+               getImageWidth : function() {
+                       if (!isRunning) throw new Error("PixasticEditor::getImageWidth(): Editor is not running");
+
+                       return imageWidth;
+               },
+               getImageHeight : function() {
+                       if (!isRunning) throw new Error("PixasticEditor::getImageHeight(): Editor is not running");
+
+                       return imageHeight;
+               },
+               errorDialog : function() {
+                       if (!isRunning) throw new Error("PixasticEditor::errorDialog(): Editor is not running");
+
+                       return errorDialog.apply(null, arguments);
+               }
+       }
+
+})();
\ No newline at end of file
diff --git a/js2/mwEmbed/libClipEdit/pixastic-editor/pixastic.all.js b/js2/mwEmbed/libClipEdit/pixastic-editor/pixastic.all.js
new file mode 100644 (file)
index 0000000..bee153a
--- /dev/null
@@ -0,0 +1,3169 @@
+/*
+ * Pixastic Lib - Core Functions - v0.1.3
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+var Pixastic = (function() {
+
+
+       function addEvent(el, event, handler) {
+               if (el.addEventListener)
+                       el.addEventListener(event, handler, false); 
+               else if (el.attachEvent)
+                       el.attachEvent("on" + event, handler); 
+       }
+
+       function onready(handler) {
+               var handlerDone = false;
+               var execHandler = function() {
+                       if (!handlerDone) {
+                               handlerDone = true;
+                               handler();
+                       }
+               }
+               document.write("<"+"script defer src=\"//:\" id=\"__onload_ie_sumbox__\"></"+"script>");
+               var script = document.getElementById("__onload_ie_sumbox__");
+               script.onreadystatechange = function() {
+                       if (script.readyState == "complete") {
+                               script.parentNode.removeChild(script);
+                               execHandler();
+                       }
+               }
+               if (document.addEventListener)
+                       document.addEventListener("DOMContentLoaded", execHandler, false); 
+               addEvent(window, "load", execHandler);
+       }
+
+       function init() {
+               if (!Pixastic.parseOnLoad) return;
+               var imgEls = getElementsByClass("pixastic", null, "img");
+               var canvasEls = getElementsByClass("pixastic", null, "canvas");
+               var elements = imgEls.concat(canvasEls);
+               for (var i=0;i<elements.length;i++) {
+                       (function() {
+
+                       var el = elements[i];
+                       var actions = [];
+                       var classes = el.className.split(" ");
+                       for (var c=0;c<classes.length;c++) {
+                               var cls = classes[c];
+                               if (cls.substring(0,9) == "pixastic-") {
+                                       var actionName = cls.substring(9);
+                                       if (actionName != "")
+                                               actions.push(actionName);
+                               }
+                       }
+                       if (actions.length) {
+                               if (el.tagName.toLowerCase() == "img") {
+                                       var dataImg = new Image();
+                                       dataImg.src = el.src;
+                                       if (dataImg.complete) {
+                                               for (var a=0;a<actions.length;a++) {
+                                                       var res = Pixastic.applyAction(el, el, actions[a], null);
+                                                       if (res) 
+                                                               el = res;
+                                               }
+                                       } else {
+                                               dataImg.onload = function() {
+                                                       for (var a=0;a<actions.length;a++) {
+                                                               var res = Pixastic.applyAction(el, el, actions[a], null)
+                                                               if (res) 
+                                                                       el = res;
+                                                       }
+                                               }
+                                       }
+                               } else {
+                                       setTimeout(function() {
+                                               for (var a=0;a<actions.length;a++) {
+                                                       var res = Pixastic.applyAction(
+                                                               el, el, actions[a], null
+                                                       );
+                                                       if (res) 
+                                                               el = res;
+                                               }
+                                       },1);
+                               }
+                       }
+
+                       })();
+               }
+       }
+
+//     if (typeof pixastic_no_onready == "undefined") // yuck.
+//             onready(init);
+
+       // getElementsByClass by Dustin Diaz, http://www.dustindiaz.com/getelementsbyclass/
+       function getElementsByClass(searchClass,node,tag) {
+               var classElements = new Array();
+               if ( node == null )
+                       node = document;
+               if ( tag == null )
+                       tag = '*';
+
+               var els = node.getElementsByTagName(tag);
+               var elsLen = els.length;
+               var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
+               for (i = 0, j = 0; i < elsLen; i++) {
+                       if ( pattern.test(els[i].className) ) {
+                               classElements[j] = els[i];
+                               j++;
+                       }
+               }
+               return classElements;
+       }
+
+       var debugElement;
+
+       function writeDebug(text, level) {
+               if (!Pixastic.debug) return;
+               try {
+                       switch (level) {
+                               case "warn" : 
+                                       console.warn("Pixastic:", text);
+                                       break;
+                               case "error" :
+                                       console.error("Pixastic:", text);
+                                       break;
+                               default:
+                                       console.log("Pixastic:", text);
+                       }
+               } catch(e) {
+               }
+               if (!debugElement) {
+                       
+               }
+       }
+
+
+       return {
+
+               parseOnLoad : false,
+
+               debug : false,
+               
+               applyAction : function(img, dataImg, actionName, options) {
+
+                       options = options || {};
+
+                       var imageIsCanvas = (img.tagName.toLowerCase() == "canvas");
+                       if (imageIsCanvas && Pixastic.Client.isIE()) {
+                               if (Pixastic.debug) writeDebug("Tried to process a canvas element but browser is IE.");
+                               return false;
+                       }
+
+                       var canvas, ctx;
+                       if (Pixastic.Client.hasCanvas()) {
+                               canvas = document.createElement("canvas");
+                               ctx = canvas.getContext("2d");
+                       }
+
+                       var w = parseInt(img.offsetWidth);
+                       var h = parseInt(img.offsetHeight);
+
+                       if (imageIsCanvas) {
+                               w = img.width;
+                               h = img.height;
+                       }
+
+                       if (actionName.indexOf("(") > -1) {
+                               var tmp = actionName;
+                               actionName = tmp.substr(0, tmp.indexOf("("));
+                               var arg = tmp.match(/\((.*?)\)/);
+                               if (arg[1]) {
+                                       arg = arg[1].split(";");
+                                       for (var a=0;a<arg.length;a++) {
+                                               thisArg = arg[a].split("=");
+                                               if (thisArg.length == 2) {
+                                                       if (thisArg[0] == "rect") {
+                                                               var rectVal = thisArg[1].split(",");
+                                                               options[thisArg[0]] = {
+                                                                       left : parseInt(rectVal[0],10)||0,
+                                                                       top : parseInt(rectVal[1],10)||0,
+                                                                       width : parseInt(rectVal[2],10)||0,
+                                                                       height : parseInt(rectVal[3],10)||0
+                                                               }
+                                                       } else {
+                                                               options[thisArg[0]] = thisArg[1];
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+
+                       if (!options.rect) {
+                               options.rect = {
+                                       left : 0, top : 0, width : w, height : h
+                               };
+                       }
+                       var validAction = false;
+                       if (Pixastic.Actions[actionName] && typeof Pixastic.Actions[actionName].process == "function") {
+                               validAction = true;
+                       }
+                       if (!validAction) {
+                               if (Pixastic.debug) writeDebug("Invalid action \"" + actionName + "\". Maybe file not included?");
+                               return false;
+                       }
+                       if (!Pixastic.Actions[actionName].checkSupport()) {
+                               if (Pixastic.debug) writeDebug("Action \"" + actionName + "\" not supported by this browser.");
+                               return false;
+                       }
+
+                       if (Pixastic.Client.hasCanvas()) {
+                               canvas.width = w;
+                               canvas.height = h;
+                               canvas.style.width = w+"px";
+                               canvas.style.height = h+"px";
+                               ctx.drawImage(dataImg,0,0,w,h);
+
+                               if (!img.__pixastic_org_image) {
+                                       canvas.__pixastic_org_image = img;
+                                       canvas.__pixastic_org_width = w;
+                                       canvas.__pixastic_org_height = h;
+                               } else {
+                                       canvas.__pixastic_org_image = img.__pixastic_org_image;
+                                       canvas.__pixastic_org_width = img.__pixastic_org_width;
+                                       canvas.__pixastic_org_height = img.__pixastic_org_height;
+                               }
+
+                       } else if (Pixastic.Client.isIE() && typeof img.__pixastic_org_style == "undefined") {
+                               img.__pixastic_org_style = img.style.cssText;
+                       }
+
+                       var params = {
+                               image : img,
+                               canvas : canvas,
+                               width : w,
+                               height : h,
+                               useData : true,
+                               options : options
+                       }
+
+                       // Ok, let's do it!
+
+                       var res = Pixastic.Actions[actionName].process(params);
+
+                       if (!res) {
+                               return false;
+                       }
+
+                       if (Pixastic.Client.hasCanvas()) {
+                               if (params.useData) {
+                                       if (Pixastic.Client.hasCanvasImageData()) {
+                                               canvas.getContext("2d").putImageData(params.canvasData, options.rect.left, options.rect.top);
+
+                                               // Opera doesn't seem to update the canvas until we draw something on it, lets draw a 0x0 rectangle.
+                                               canvas.getContext("2d").fillRect(0,0,0,0);
+                                       }
+                               }
+
+                               if (!options.leaveDOM) {
+                                       // copy properties and stuff from the source image
+                                       canvas.title = img.title;
+                                       canvas.imgsrc = img.imgsrc;
+                                       if (!imageIsCanvas) canvas.alt  = img.alt;
+                                       if (!imageIsCanvas) canvas.imgsrc = img.src;
+                                       canvas.className = img.className;
+                                       canvas.style.cssText = img.style.cssText;
+                                       canvas.name = img.name;
+                                       canvas.tabIndex = img.tabIndex;
+                                       canvas.id = img.id;
+                                       if (img.parentNode && img.parentNode.replaceChild) {
+                                               img.parentNode.replaceChild(canvas, img);
+                                       }
+                               }
+
+                               options.resultCanvas = canvas;
+
+                               return canvas;
+                       }
+
+                       return img;
+               },
+
+               prepareData : function(params, getCopy) {
+                       var ctx = params.canvas.getContext("2d");
+                       var rect = params.options.rect;
+                       var dataDesc = ctx.getImageData(rect.left, rect.top, rect.width, rect.height);
+                       var data = dataDesc.data;
+                       if (!getCopy) params.canvasData = dataDesc;
+                       return data;
+               },
+
+               // load the image file
+               process : function(img, actionName, options, callback)
+               {
+                       if (img.tagName.toLowerCase() == "img") {
+                               var dataImg = new Image();
+                               dataImg.src = img.src;
+                               if (dataImg.complete) {
+                                       var res = Pixastic.applyAction(img, dataImg, actionName, options);
+                                       if (callback) callback(res);
+                                       return res;
+                               } else {
+                                       dataImg.onload = function() {
+                                               var res = Pixastic.applyAction(img, dataImg, actionName, options)
+                                               if (callback) callback(res);
+                                       }
+                               }
+                       }
+                       if (img.tagName.toLowerCase() == "canvas") {
+                               var res = Pixastic.applyAction(img, img, actionName, options);
+                               if (callback) callback(res);
+                               return res;
+                       }
+               },
+
+               revert : function(img) {
+                       if (Pixastic.Client.hasCanvas()) {
+                               if (img.tagName.toLowerCase() == "canvas" && img.__pixastic_org_image) {
+                                       img.width = img.__pixastic_org_width;
+                                       img.height = img.__pixastic_org_height;
+                                       img.getContext("2d").drawImage(img.__pixastic_org_image, 0, 0);
+
+                                       if (img.parentNode && img.parentNode.replaceChild) {
+                                               img.parentNode.replaceChild(img.__pixastic_org_image, img);
+                                       }
+
+                                       return img;
+                               }
+                       } else if (Pixastic.Client.isIE() && typeof img.__pixastic_org_style != "undefined") {
+                               img.style.cssText = img.__pixastic_org_style;
+                       }
+               },
+
+               Client : {
+                       hasCanvas : (function() {
+                               var c = document.createElement("canvas");
+                               var val = false;
+                               try {
+                                       val = !!((typeof c.getContext == "function") && c.getContext("2d"));
+                               } catch(e) {}
+                               return function() {
+                                       return val;
+                               }
+                       })(),
+
+                       hasCanvasImageData : (function() {
+                               var c = document.createElement("canvas");
+                               var val = false;
+                               var ctx;
+                               try {
+                                       if (typeof c.getContext == "function" && (ctx = c.getContext("2d"))) {
+                                               val = (typeof ctx.getImageData == "function");
+                                       }
+                               } catch(e) {}
+                               return function() {
+                                       return val;
+                               }
+                       })(),
+
+                       isIE : function() {
+                               return !!document.all && !!window.attachEvent && !window.opera;
+                       }
+               },
+
+               Actions : {}
+       }
+
+
+})();
+/*
+ * Pixastic Lib - jQuery plugin
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+if (typeof jQuery != "undefined" && jQuery && jQuery.fn) {
+       jQuery.fn.pixastic = function(action, options) {
+               var newElements = [];
+               this.each(
+                       function () {
+                               if (this.tagName.toLowerCase() == "img" && !this.complete) {
+                                       return;
+                               }
+                               var res = Pixastic.process(this, action, options);
+                               if (res) {
+                                       newElements.push(res);
+                               }
+                       }
+               );
+               if (newElements.length > 0)
+                       return jQuery(newElements);
+               else
+                       return this;
+       };
+
+};
+/*
+ * Pixastic Lib - Blend - v0.1.1
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.blend = {
+
+       process : function(params) {
+               var amount = parseFloat(params.options.amount);
+               var mode = (params.options.mode || "normal").toLowerCase();
+               var image = params.options.image;
+
+               amount = Math.max(0,Math.min(1,amount));
+
+               if (!image) return false;
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var rect = params.options.rect;
+                       var data = Pixastic.prepareData(params);
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       params.useData = false;
+
+                       var otherCanvas = document.createElement("canvas");
+                       otherCanvas.width = params.canvas.width;
+                       otherCanvas.height = params.canvas.height;
+                       var otherCtx = otherCanvas.getContext("2d");
+                       otherCtx.drawImage(image,0,0);
+
+                       var params2 = {canvas:otherCanvas,options:params.options};
+                       var data2 = Pixastic.prepareData(params2);
+                       var dataDesc2 = params2.canvasData;
+
+                       var p = w*h;
+                       var pix = p*4;
+                       var pix1, pix2;
+                       var r1, g1, b1;
+                       var r2, g2, b2;
+                       var r3, g3, b3;
+                       var r4, g4, b4;
+
+                       var dataChanged = false;
+
+                       switch (mode) {
+                               case "normal" : 
+                                       //while (p--) {
+                                       //      data2[pix-=4] = data2[pix];
+                                       //      data2[pix1=pix+1] = data2[pix1];
+                                       //      data2[pix2=pix+2] = data2[pix2];
+                                       //}
+                                       break;
+
+                               case "multiply" : 
+                                       while (p--) {
+                                               data2[pix-=4] = data[pix] * data2[pix] / 255;
+                                               data2[pix1=pix+1] = data[pix1] * data2[pix1] / 255;
+                                               data2[pix2=pix+2] = data[pix2] * data2[pix2] / 255;
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "lighten" : 
+                                       while (p--) {
+                                               if ((r1 = data[pix-=4]) > data2[pix])
+                                                       data2[pix] = r1;
+                                               if ((g1 = data[pix1=pix+1]) > data2[pix1])
+                                                       data2[pix1] = g1;
+                                               if ((b1 = data[pix2=pix+2]) > data2[pix2])
+                                                       data2[pix2] = b1;
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "darken" : 
+                                       while (p--) {
+                                               if ((r1 = data[pix-=4]) < data2[pix])
+                                                       data2[pix] = r1;
+                                               if ((g1 = data[pix1=pix+1]) < data2[pix1])
+                                                       data2[pix1] = g1;
+                                               if ((b1 = data[pix2=pix+2]) < data2[pix2])
+                                                       data2[pix2] = b1;
+
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "darkercolor" : 
+                                       while (p--) {
+                                               if (((r1 = data[pix-=4])*0.3+(g1 = data[pix1=pix+1])*0.59+(b1 = data[pix2=pix+2])*0.11) <= (data2[pix]*0.3+data2[pix1]*0.59+data2[pix2]*0.11)) {
+                                                       data2[pix] = r1;
+                                                       data2[pix1] = g1;
+                                                       data2[pix2] = b1;
+                                               }
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "lightercolor" : 
+                                       while (p--) {
+                                               if (((r1 = data[pix-=4])*0.3+(g1 = data[pix1=pix+1])*0.59+(b1 = data[pix2=pix+2])*0.11) > (data2[pix]*0.3+data2[pix1]*0.59+data2[pix2]*0.11)) {
+                                                       data2[pix] = r1;
+                                                       data2[pix1] = g1;
+                                                       data2[pix2] = b1;
+                                               }
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "lineardodge" : 
+                                       otherCtx.globalCompositeOperation = "source-over";
+                                       otherCtx.drawImage(params.canvas, 0, 0);
+                                       otherCtx.globalCompositeOperation = "lighter";
+                                       otherCtx.drawImage(image, 0, 0);
+
+                                       /*
+                                       while (p--) {
+                                               if ((r3 = data[pix-=4] + data2[pix]) > 255)
+                                                       data2[pix] = 255;
+                                               else
+                                                       data2[pix] = r3;
+                                               if ((g3 = data[pix1=pix+1] + data2[pix1]) > 255)
+                                                       data2[pix1] = 255;
+                                               else
+                                                       data2[pix1] = g3;
+                                               if ((b3 = data[pix2=pix+2] + data2[pix2]) > 255)
+                                                       data2[pix2] = 255;
+                                               else
+                                                       data2[pix2] = b3;
+                                       }
+                                       dataChanged = true;
+                                       */
+
+                                       break;
+
+                               case "linearburn" : 
+                                       while (p--) {
+                                               if ((r3 = data[pix-=4] + data2[pix]) < 255)
+                                                       data2[pix] = 0;
+                                               else
+                                                       data2[pix] = (r3 - 255);
+                                               if ((g3 = data[pix1=pix+1] + data2[pix1]) < 255)
+                                                       data2[pix1] = 0;
+                                               else
+                                                       data2[pix1] = (g3 - 255);
+                                               if ((b3 = data[pix2=pix+2] + data2[pix2]) < 255)
+                                                       data2[pix2] = 0;
+                                               else
+                                                       data2[pix2] = (b3 - 255);
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "difference" : 
+                                       while (p--) {
+                                               if ((r3 = data[pix-=4] - data2[pix]) < 0)
+                                                       data2[pix] = -r3;
+                                               else
+                                                       data2[pix] = r3;
+                                               if ((g3 = data[pix1=pix+1] - data2[pix1]) < 0)
+                                                       data2[pix1] = -g3;
+                                               else
+                                                       data2[pix1] = g3;
+                                               if ((b3 = data[pix2=pix+2] - data2[pix2]) < 0)
+                                                       data2[pix2] = -b3;
+                                               else
+                                                       data2[pix2] = b3;
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "screen" : 
+                                       while (p--) {
+                                               data2[pix-=4] = (255 - ( ((255-data2[pix])*(255-data[pix])) >> 8));
+                                               data2[pix1=pix+1] = (255 - ( ((255-data2[pix1])*(255-data[pix1])) >> 8));
+                                               data2[pix2=pix+2] = (255 - ( ((255-data2[pix2])*(255-data[pix2])) >> 8));
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "exclusion" : 
+                                       var div_2_255 = 2 / 255;
+                                       while (p--) {
+                                               data2[pix-=4] = (r1 = data[pix]) - (r1 * div_2_255 - 1) * data2[pix];
+                                               data2[pix1=pix+1] = (g1 = data[pix1]) - (g1 * div_2_255 - 1) * data2[pix1];
+                                               data2[pix2=pix+2] = (b1 = data[pix2]) - (b1 * div_2_255 - 1) * data2[pix2];
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "overlay" : 
+                                       var div_2_255 = 2 / 255;
+                                       while (p--) {
+                                               if ((r1 = data[pix-=4]) < 128)
+                                                       data2[pix] = data2[pix]*r1*div_2_255;
+                                               else
+                                                       data2[pix] = 255 - (255-data2[pix])*(255-r1)*div_2_255;
+
+                                               if ((g1 = data[pix1=pix+1]) < 128)
+                                                       data2[pix1] = data2[pix1]*g1*div_2_255;
+                                               else
+                                                       data2[pix1] = 255 - (255-data2[pix1])*(255-g1)*div_2_255;
+
+                                               if ((b1 = data[pix2=pix+2]) < 128)
+                                                       data2[pix2] = data2[pix2]*b1*div_2_255;
+                                               else
+                                                       data2[pix2] = 255 - (255-data2[pix2])*(255-b1)*div_2_255;
+
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "softlight" : 
+                                       var div_2_255 = 2 / 255;
+                                       while (p--) {
+                                               if ((r1 = data[pix-=4]) < 128)
+                                                       data2[pix] = ((data2[pix]>>1) + 64) * r1 * div_2_255;
+                                               else
+                                                       data2[pix] = 255 - (191 - (data2[pix]>>1)) * (255-r1) * div_2_255;
+
+                                               if ((g1 = data[pix1=pix+1]) < 128)
+                                                       data2[pix1] = ((data2[pix1]>>1)+64) * g1 * div_2_255;
+                                               else
+                                                       data2[pix1] = 255 - (191 - (data2[pix1]>>1)) * (255-g1) * div_2_255;
+
+                                               if ((b1 = data[pix2=pix+2]) < 128)
+                                                       data2[pix2] = ((data2[pix2]>>1)+64) * b1 * div_2_255;
+                                               else
+                                                       data2[pix2] = 255 - (191 - (data2[pix2]>>1)) * (255-b1) * div_2_255;
+
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "hardlight" : 
+                                       var div_2_255 = 2 / 255;
+                                       while (p--) {
+                                               if ((r2 = data2[pix-=4]) < 128)
+                                                       data2[pix] = data[pix] * r2 * div_2_255;
+                                               else
+                                                       data2[pix] = 255 - (255-data[pix]) * (255-r2) * div_2_255;
+
+                                               if ((g2 = data2[pix1=pix+1]) < 128)
+                                                       data2[pix1] = data[pix1] * g2 * div_2_255;
+                                               else
+                                                       data2[pix1] = 255 - (255-data[pix1]) * (255-g2) * div_2_255;
+
+                                               if ((b2 = data2[pix2=pix+2]) < 128)
+                                                       data2[pix2] = data[pix2] * b2 * div_2_255;
+                                               else
+                                                       data2[pix2] = 255 - (255-data[pix2]) * (255-b2) * div_2_255;
+
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "colordodge" : 
+                                       while (p--) {
+                                               if ((r3 = (data[pix-=4]<<8)/(255-(r2 = data2[pix]))) > 255 || r2 == 255)
+                                                       data2[pix] = 255;
+                                               else
+                                                       data2[pix] = r3;
+
+                                               if ((g3 = (data[pix1=pix+1]<<8)/(255-(g2 = data2[pix1]))) > 255 || g2 == 255)
+                                                       data2[pix1] = 255;
+                                               else
+                                                       data2[pix1] = g3;
+
+                                               if ((b3 = (data[pix2=pix+2]<<8)/(255-(b2 = data2[pix2]))) > 255 || b2 == 255)
+                                                       data2[pix2] = 255;
+                                               else
+                                                       data2[pix2] = b3;
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "colorburn" : 
+                                       while (p--) {
+                                               if ((r3 = 255-((255-data[pix-=4])<<8)/data2[pix]) < 0 || data2[pix] == 0)
+                                                       data2[pix] = 0;
+                                               else
+                                                       data2[pix] = r3;
+
+                                               if ((g3 = 255-((255-data[pix1=pix+1])<<8)/data2[pix1]) < 0 || data2[pix1] == 0)
+                                                       data2[pix1] = 0;
+                                               else
+                                                       data2[pix1] = g3;
+
+                                               if ((b3 = 255-((255-data[pix2=pix+2])<<8)/data2[pix2]) < 0 || data2[pix2] == 0)
+                                                       data2[pix2] = 0;
+                                               else
+                                                       data2[pix2] = b3;
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "linearlight" : 
+                                       while (p--) {
+                                               if ( ((r3 = 2*(r2=data2[pix-=4])+data[pix]-256) < 0) || (r2 < 128 && r3 < 0)) {
+                                                       data2[pix] = 0
+                                               } else {
+                                                       if (r3 > 255)
+                                                               data2[pix] = 255;
+                                                       else
+                                                               data2[pix] = r3;
+                                               }
+                                               if ( ((g3 = 2*(g2=data2[pix1=pix+1])+data[pix1]-256) < 0) || (g2 < 128 && g3 < 0)) {
+                                                       data2[pix1] = 0
+                                               } else {
+                                                       if (g3 > 255)
+                                                               data2[pix1] = 255;
+                                                       else
+                                                               data2[pix1] = g3;
+                                               }
+                                               if ( ((b3 = 2*(b2=data2[pix2=pix+2])+data[pix2]-256) < 0) || (b2 < 128 && b3 < 0)) {
+                                                       data2[pix2] = 0
+                                               } else {
+                                                       if (b3 > 255)
+                                                               data2[pix2] = 255;
+                                                       else
+                                                               data2[pix2] = b3;
+                                               }
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "vividlight" : 
+                                       while (p--) {
+                                               if ((r2=data2[pix-=4]) < 128) {
+                                                       if (r2) {
+                                                               if ((r3 = 255 - ((255-data[pix])<<8) / (2*r2)) < 0) 
+                                                                       data2[pix] = 0;
+                                                               else
+                                                                       data2[pix] = r3
+                                                       } else {
+                                                               data2[pix] = 0;
+                                                       }
+                                               } else if ((r3 = (r4=2*r2-256)) < 255) {
+                                                       if ((r3 = (data[pix]<<8)/(255-r4)) > 255) 
+                                                               data2[pix] = 255;
+                                                       else
+                                                               data2[pix] = r3;
+                                               } else {
+                                                       if (r3 < 0) 
+                                                               data2[pix] = 0;
+                                                       else
+                                                               data2[pix] = r3
+                                               }
+
+                                               if ((g2=data2[pix1=pix+1]) < 128) {
+                                                       if (g2) {
+                                                               if ((g3 = 255 - ((255-data[pix1])<<8) / (2*g2)) < 0) 
+                                                                       data2[pix1] = 0;
+                                                               else
+                                                                       data2[pix1] = g3;
+                                                       } else {
+                                                               data2[pix1] = 0;
+                                                       }
+                                               } else if ((g3 = (g4=2*g2-256)) < 255) {
+                                                       if ((g3 = (data[pix1]<<8)/(255-g4)) > 255)
+                                                               data2[pix1] = 255;
+                                                       else
+                                                               data2[pix1] = g3;
+                                               } else {
+                                                       if (g3 < 0) 
+                                                               data2[pix1] = 0;
+                                                       else
+                                                               data2[pix1] = g3;
+                                               }
+
+                                               if ((b2=data2[pix2=pix+2]) < 128) {
+                                                       if (b2) {
+                                                               if ((b3 = 255 - ((255-data[pix2])<<8) / (2*b2)) < 0) 
+                                                                       data2[pix2] = 0;
+                                                               else
+                                                                       data2[pix2] = b3;
+                                                       } else {
+                                                               data2[pix2] = 0;
+                                                       }
+                                               } else if ((b3 = (b4=2*b2-256)) < 255) {
+                                                       if ((b3 = (data[pix2]<<8)/(255-b4)) > 255) 
+                                                               data2[pix2] = 255;
+                                                       else
+                                                               data2[pix2] = b3;
+                                               } else {
+                                                       if (b3 < 0) 
+                                                               data2[pix2] = 0;
+                                                       else
+                                                               data2[pix2] = b3;
+                                               }
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "pinlight" : 
+                                       while (p--) {
+                                               if ((r2=data2[pix-=4]) < 128)
+                                                       if ((r1=data[pix]) < (r4=2*r2))
+                                                               data2[pix] = r1;
+                                                       else
+                                                               data2[pix] = r4;
+                                               else
+                                                       if ((r1=data[pix]) > (r4=2*r2-256))
+                                                               data2[pix] = r1;
+                                                       else
+                                                               data2[pix] = r4;
+
+                                               if ((g2=data2[pix1=pix+1]) < 128)
+                                                       if ((g1=data[pix1]) < (g4=2*g2))
+                                                               data2[pix1] = g1;
+                                                       else
+                                                               data2[pix1] = g4;
+                                               else
+                                                       if ((g1=data[pix1]) > (g4=2*g2-256))
+                                                               data2[pix1] = g1;
+                                                       else
+                                                               data2[pix1] = g4;
+
+                                               if ((r2=data2[pix2=pix+2]) < 128)
+                                                       if ((r1=data[pix2]) < (r4=2*r2))
+                                                               data2[pix2] = r1;
+                                                       else
+                                                               data2[pix2] = r4;
+                                               else
+                                                       if ((r1=data[pix2]) > (r4=2*r2-256))
+                                                               data2[pix2] = r1;
+                                                       else
+                                                               data2[pix2] = r4;
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "hardmix" : 
+                                       while (p--) {
+                                               if ((r2 = data2[pix-=4]) < 128)
+                                                       if (255 - ((255-data[pix])<<8)/(2*r2) < 128 || r2 == 0)
+                                                               data2[pix] = 0;
+                                                       else
+                                                               data2[pix] = 255;
+                                               else if ((r4=2*r2-256) < 255 && (data[pix]<<8)/(255-r4) < 128)
+                                                       data2[pix] = 0;
+                                               else
+                                                       data2[pix] = 255;
+
+                                               if ((g2 = data2[pix1=pix+1]) < 128)
+                                                       if (255 - ((255-data[pix1])<<8)/(2*g2) < 128 || g2 == 0)
+                                                               data2[pix1] = 0;
+                                                       else
+                                                               data2[pix1] = 255;
+                                               else if ((g4=2*g2-256) < 255 && (data[pix1]<<8)/(255-g4) < 128)
+                                                       data2[pix1] = 0;
+                                               else
+                                                       data2[pix1] = 255;
+
+                                               if ((b2 = data2[pix2=pix+2]) < 128)
+                                                       if (255 - ((255-data[pix2])<<8)/(2*b2) < 128 || b2 == 0)
+                                                               data2[pix2] = 0;
+                                                       else
+                                                               data2[pix2] = 255;
+                                               else if ((b4=2*b2-256) < 255 && (data[pix2]<<8)/(255-b4) < 128)
+                                                       data2[pix2] = 0;
+                                               else
+                                                       data2[pix2] = 255;
+                                       }
+                                       dataChanged = true;
+                                       break;
+                       }
+
+                       if (dataChanged) 
+                               otherCtx.putImageData(dataDesc2,0,0);
+
+                       var ctx = params.canvas.getContext("2d");
+                       ctx.save();
+                       ctx.globalAlpha = amount;
+                       ctx.drawImage(
+                               otherCanvas,
+                               0,0,rect.width,rect.height,
+                               rect.left,rect.top,rect.width,rect.height
+                       );
+                       ctx.globalAlpha = 1;
+                       ctx.restore();
+
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}/*
+ * Pixastic Lib - Blur filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.blur = {
+       process : function(params) {
+
+               if (typeof params.options.fixMargin == "undefined")
+                       params.options.fixMargin = true;
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var dataCopy = Pixastic.prepareData(params, true)
+
+                       /*
+                       var kernel = [
+                               [0.5,   1,      0.5],
+                               [1,     2,      1],
+                               [0.5,   1,      0.5]
+                       ];
+                       */
+
+                       var kernel = [
+                               [0,     1,      0],
+                               [1,     2,      1],
+                               [0,     1,      0]
+                       ];
+
+                       var weight = 0;
+                       for (var i=0;i<3;i++) {
+                               for (var j=0;j<3;j++) {
+                                       weight += kernel[i][j];
+                               }
+                       }
+
+                       weight = 1 / (weight*2);
+
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+
+                               var prevY = (y == 1) ? 0 : y-2;
+                               var nextY = (y == h) ? y - 1 : y;
+
+                               var offsetYPrev = prevY*w*4;
+                               var offsetYNext = nextY*w*4;
+
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x*4-4);
+
+                                       var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
+                                       var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
+       
+                                       data[offset] = (
+                                               /*
+                                               dataCopy[offsetPrev - 4]
+                                               + dataCopy[offsetPrev+4] 
+                                               + dataCopy[offsetNext - 4]
+                                               + dataCopy[offsetNext+4]
+                                               + 
+                                               */
+                                               (dataCopy[offsetPrev]
+                                               + dataCopy[offset-4]
+                                               + dataCopy[offset+4]
+                                               + dataCopy[offsetNext])         * 2
+                                               + dataCopy[offset]              * 4
+                                               ) * weight;
+
+                                       data[offset+1] = (
+                                               /*
+                                               dataCopy[offsetPrev - 3]
+                                               + dataCopy[offsetPrev+5] 
+                                               + dataCopy[offsetNext - 3] 
+                                               + dataCopy[offsetNext+5]
+                                               + 
+                                               */
+                                               (dataCopy[offsetPrev+1]
+                                               + dataCopy[offset-3]
+                                               + dataCopy[offset+5]
+                                               + dataCopy[offsetNext+1])       * 2
+                                               + dataCopy[offset+1]            * 4
+                                               ) * weight;
+
+                                       data[offset+2] = (
+                                               /*
+                                               dataCopy[offsetPrev - 2] 
+                                               + dataCopy[offsetPrev+6] 
+                                               + dataCopy[offsetNext - 2] 
+                                               + dataCopy[offsetNext+6]
+                                               + 
+                                               */
+                                               (dataCopy[offsetPrev+2]
+                                               + dataCopy[offset-2]
+                                               + dataCopy[offset+6]
+                                               + dataCopy[offsetNext+2])       * 2
+                                               + dataCopy[offset+2]            * 4
+                                               ) * weight;
+
+                               } while (--x);
+                       } while (--y);
+
+                       return true;
+
+               } else if (Pixastic.Client.isIE()) {
+                       params.image.style.filter += " progid:DXImageTransform.Microsoft.Blur(pixelradius=1.5)";
+
+                       if (params.options.fixMargin) {
+                               params.image.style.marginLeft = (parseInt(params.image.style.marginLeft,10)||0) - 2 + "px";
+                               params.image.style.marginTop = (parseInt(params.image.style.marginTop,10)||0) - 2 + "px";
+                       }
+
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
+       }
+}/*
+ * Pixastic Lib - Blur Fast - v0.1.1
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.blurfast = {
+       process : function(params) {
+
+               var amount = parseFloat(params.options.amount)||0;
+               var clear = !!(params.options.clear && params.options.clear != "false");
+
+               amount = Math.max(0,Math.min(5,amount));
+
+               if (Pixastic.Client.hasCanvas()) {
+                       var rect = params.options.rect;
+
+                       var ctx = params.canvas.getContext("2d");
+                       ctx.save();
+                       ctx.beginPath();
+                       ctx.rect(rect.left, rect.top, rect.width, rect.height);
+                       ctx.clip();
+
+                       var scale = 2;
+                       var smallWidth = Math.round(params.width / scale);
+                       var smallHeight = Math.round(params.height / scale);
+
+                       var copy = document.createElement("canvas");
+                       copy.width = smallWidth;
+                       copy.height = smallHeight;
+
+                       var clear = false;
+                       var steps = Math.round(amount * 20);
+
+                       var copyCtx = copy.getContext("2d");
+                       for (var i=0;i<steps;i++) {
+                               var scaledWidth = Math.max(1,Math.round(smallWidth - i));
+                               var scaledHeight = Math.max(1,Math.round(smallHeight - i));
+       
+                               copyCtx.clearRect(0,0,smallWidth,smallHeight);
+       
+                               copyCtx.drawImage(
+                                       params.canvas,
+                                       0,0,params.width,params.height,
+                                       0,0,scaledWidth,scaledHeight
+                               );
+       
+                               if (clear)
+                                       ctx.clearRect(rect.left,rect.top,rect.width,rect.height);
+       
+                               ctx.drawImage(
+                                       copy,
+                                       0,0,scaledWidth,scaledHeight,
+                                       0,0,params.width,params.height
+                               );
+                       }
+
+                       ctx.restore();
+
+                       params.useData = false;
+                       return true;
+               } else if (Pixastic.Client.isIE()) {
+                       var radius = 10 * amount;
+                       params.image.style.filter += " progid:DXImageTransform.Microsoft.Blur(pixelradius=" + radius + ")";
+
+                       if (params.options.fixMargin || 1) {
+                               params.image.style.marginLeft = (parseInt(params.image.style.marginLeft,10)||0) - Math.round(radius) + "px";
+                               params.image.style.marginTop = (parseInt(params.image.style.marginTop,10)||0) - Math.round(radius) + "px";
+                       }
+
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvas() || Pixastic.Client.isIE());
+       }
+}
+/*
+ * Pixastic Lib - Brightness/Contrast filter - v0.1.1
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.brightness = {
+
+       process : function(params) {
+
+               var brightness = parseInt(params.options.brightness,10) || 0;
+               var contrast = parseFloat(params.options.contrast)||0;
+               var legacy = !!(params.options.legacy && params.options.legacy != "false");
+
+               if (legacy) {
+                       brightness = Math.min(150,Math.max(-150,brightness));
+               } else {
+                       var brightMul = 1 + Math.min(150,Math.max(-150,brightness)) / 150;
+               }
+               contrast = Math.max(0,contrast+1);
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       var p = w*h;
+                       var pix = p*4, pix1, pix2;
+
+                       var mul, add;
+                       if (contrast != 1) {
+                               if (legacy) {
+                                       mul = contrast;
+                                       add = (brightness - 128) * contrast + 128;
+                               } else {
+                                       mul = brightMul * contrast;
+                                       add = - contrast * 128 + 128;
+                               }
+                       } else {  // this if-then is not necessary anymore, is it?
+                               if (legacy) {
+                                       mul = 1;
+                                       add = brightness;
+                               } else {
+                                       mul = brightMul;
+                                       add = 0;
+                               }
+                       }
+                       var r, g, b;
+                       while (p--) {
+                               if ((r = data[pix-=4] * mul + add) > 255 )
+                                       data[pix] = 255;
+                               else if (r < 0)
+                                       data[pix] = 0;
+                               else
+                                       data[pix] = r;
+
+                               if ((g = data[pix1=pix+1] * mul + add) > 255 ) 
+                                       data[pix1] = 255;
+                               else if (g < 0)
+                                       data[pix1] = 0;
+                               else
+                                       data[pix1] = g;
+
+                               if ((b = data[pix2=pix+2] * mul + add) > 255 ) 
+                                       data[pix2] = 255;
+                               else if (b < 0)
+                                       data[pix2] = 0;
+                               else
+                                       data[pix2] = b;
+                       }
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}
+
+/*
+ * Pixastic Lib - Color adjust filter - v0.1.1
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.coloradjust = {
+
+       process : function(params) {
+               var red = parseFloat(params.options.red) || 0;
+               var green = parseFloat(params.options.green) || 0;
+               var blue = parseFloat(params.options.blue) || 0;
+
+               red = Math.round(red*255);
+               green = Math.round(green*255);
+               blue = Math.round(blue*255);
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var rect = params.options.rect;
+
+                       var p = rect.width*rect.height;
+                       var pix = p*4, pix1, pix2;
+
+                       var r, g, b;
+                       while (p--) {
+                               pix -= 4;
+
+                               if (red) {
+                                       if ((r = data[pix] + red) < 0 ) 
+                                               data[pix] = 0;
+                                       else if (r > 255 ) 
+                                               data[pix] = 255;
+                                       else
+                                               data[pix] = r;
+                               }
+
+                               if (green) {
+                                       if ((g = data[pix1=pix+1] + green) < 0 ) 
+                                               data[pix1] = 0;
+                                       else if (g > 255 ) 
+                                               data[pix1] = 255;
+                                       else
+                                               data[pix1] = g;
+                               }
+
+                               if (blue) {
+                                       if ((b = data[pix2=pix+2] + blue) < 0 ) 
+                                               data[pix2] = 0;
+                                       else if (b > 255 ) 
+                                               data[pix2] = 255;
+                                       else
+                                               data[pix2] = b;
+                               }
+                       }
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvasImageData());
+       }
+}
+/*
+ * Pixastic Lib - Histogram - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+
+Pixastic.Actions.colorhistogram = {
+
+       array256 : function(default_value) {
+               arr = [];
+               for (var i=0; i<256; i++) { arr[i] = default_value; }
+               return arr
+       },
+       process : function(params) {
+               var values = [];
+               if (typeof params.options.returnValue != "object") {
+                       params.options.returnValue = {rvals:[], gvals:[], bvals:[]};
+               }
+               var paint = !!(params.options.paint);
+
+               var returnValue = params.options.returnValue;
+               if (typeof returnValue.values != "array") {
+                       returnValue.rvals = [];
+                       returnValue.gvals = [];
+                       returnValue.bvals = [];
+               }
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       params.useData = false;
+                       var rvals = this.array256(0);
+                       var gvals = this.array256(0);
+                       var bvals = this.array256(0);
+                       var rect = params.options.rect;
+
+                       var p = rect.width*rect.height;
+                       var pix = p*4;
+                       while (p--) {
+                               rvals[data[pix-=4]]++;
+                               gvals[data[pix+1]]++;
+                               bvals[data[pix+2]]++;
+                       }
+                       returnValue.rvals = rvals;
+                       returnValue.gvals = gvals;
+                       returnValue.bvals = bvals;
+
+                       if (paint) {
+                               var ctx = params.canvas.getContext("2d");
+                               var vals = [rvals, gvals, bvals];
+                               for (var v=0;v<3;v++) {
+                                       var yoff = (v+1) * params.height / 3;
+                                       var maxValue = 0;
+                                       for (var i=0;i<256;i++) {
+                                               if (vals[v][i] > maxValue)
+                                                       maxValue = vals[v][i];
+                                       }
+                                       var heightScale = params.height / 3 / maxValue;
+                                       var widthScale = params.width / 256;
+                                       if (v==0) ctx.fillStyle = "rgba(255,0,0,0.5)";
+                                       else if (v==1) ctx.fillStyle = "rgba(0,255,0,0.5)";
+                                       else if (v==2) ctx.fillStyle = "rgba(0,0,255,0.5)";
+                                       for (var i=0;i<256;i++) {
+                                               ctx.fillRect(
+                                                       i * widthScale, params.height - heightScale * vals[v][i] - params.height + yoff,
+                                                       widthScale, vals[v][i] * heightScale
+                                               );
+                                       }
+                               }
+                       }
+                       return true;
+               }
+       },
+
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}/*
+ * Pixastic Lib - Crop - v0.1.1
+ * Copyright (c) 2008-2009 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.crop = {
+       process : function(params) {
+               if (Pixastic.Client.hasCanvas()) {
+                       var rect = params.options.rect;
+
+                       var width = rect.width;
+                       var height = rect.height;
+                       var top = rect.top;
+                       var left = rect.left;
+
+                       if (typeof params.options.left != "undefined")
+                               left = parseInt(params.options.left,10);
+                       if (typeof params.options.top != "undefined")
+                               top = parseInt(params.options.top,10);
+                       if (typeof params.options.height != "undefined")
+                               width = parseInt(params.options.width,10);
+                       if (typeof params.options.height != "undefined")
+                               height = parseInt(params.options.height,10);
+
+                       if (left < 0) left = 0;
+                       if (left > params.width-1) left = params.width-1;
+
+                       if (top < 0) top = 0;
+                       if (top > params.height-1) top = params.height-1;
+
+                       if (width < 1) width = 1;
+                       if (left + width > params.width)
+                               width = params.width - left;
+
+                       if (height < 1) height = 1;
+                       if (top + height > params.height)
+                               height = params.height - top;
+
+                       var copy = document.createElement("canvas");
+                       copy.width = params.width;
+                       copy.height = params.height;
+                       copy.getContext("2d").drawImage(params.canvas,0,0);
+
+                       params.canvas.width = width;
+                       params.canvas.height = height;
+                       params.canvas.getContext("2d").clearRect(0,0,width,height);
+
+                       params.canvas.getContext("2d").drawImage(copy,
+                               left,top,width,height,
+                               0,0,width,height
+                       );
+
+                       params.useData = false;
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvas();
+       }
+}
+
+
+/*
+ * Pixastic Lib - Desaturation filter - v0.1.1
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.desaturate = {
+
+       process : function(params) {
+               var useAverage = !!(params.options.average && params.options.average != "false");
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       var p = w*h;
+                       var pix = p*4, pix1, pix2;
+
+                       if (useAverage) {
+                               while (p--) 
+                                       data[pix-=4] = data[pix1=pix+1] = data[pix2=pix+2] = (data[pix]+data[pix1]+data[pix2])/3
+                       } else {
+                               while (p--)
+                                       data[pix-=4] = data[pix1=pix+1] = data[pix2=pix+2] = (data[pix]*0.3 + data[pix1]*0.59 + data[pix2]*0.11);
+                       }
+                       return true;
+               } else if (Pixastic.Client.isIE()) {
+                       params.image.style.filter += " gray";
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
+       }
+}/*
+ * Pixastic Lib - Edge detection filter - v0.1.1
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.edges = {
+       process : function(params) {
+
+               var mono = !!(params.options.mono && params.options.mono != "false");
+               var invert = !!(params.options.invert && params.options.invert != "false");
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var dataCopy = Pixastic.prepareData(params, true)
+
+                       var c = -1/8;
+                       var kernel = [
+                               [c,     c,      c],
+                               [c,     1,      c],
+                               [c,     c,      c]
+                       ];
+
+                       weight = 1/c;
+
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+
+                               var nextY = (y == h) ? y - 1 : y;
+                               var prevY = (y == 1) ? 0 : y-2;
+
+                               var offsetYPrev = prevY*w*4;
+                               var offsetYNext = nextY*w*4;
+
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x*4-4);
+
+                                       var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
+                                       var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
+       
+                                       var r = ((dataCopy[offsetPrev-4]
+                                               + dataCopy[offsetPrev]
+                                               + dataCopy[offsetPrev+4]
+                                               + dataCopy[offset-4]
+                                               + dataCopy[offset+4]
+                                               + dataCopy[offsetNext-4]
+                                               + dataCopy[offsetNext]
+                                               + dataCopy[offsetNext+4]) * c
+                                               + dataCopy[offset]
+                                               ) 
+                                               * weight;
+       
+                                       var g = ((dataCopy[offsetPrev-3]
+                                               + dataCopy[offsetPrev+1]
+                                               + dataCopy[offsetPrev+5]
+                                               + dataCopy[offset-3]
+                                               + dataCopy[offset+5]
+                                               + dataCopy[offsetNext-3]
+                                               + dataCopy[offsetNext+1]
+                                               + dataCopy[offsetNext+5]) * c
+                                               + dataCopy[offset+1])
+                                               * weight;
+       
+                                       var b = ((dataCopy[offsetPrev-2]
+                                               + dataCopy[offsetPrev+2]
+                                               + dataCopy[offsetPrev+6]
+                                               + dataCopy[offset-2]
+                                               + dataCopy[offset+6]
+                                               + dataCopy[offsetNext-2]
+                                               + dataCopy[offsetNext+2]
+                                               + dataCopy[offsetNext+6]) * c
+                                               + dataCopy[offset+2])
+                                               * weight;
+
+                                       if (mono) {
+                                               var brightness = (r*0.3 + g*0.59 + b*0.11)||0;
+                                               if (invert) brightness = 255 - brightness;
+                                               if (brightness < 0 ) brightness = 0;
+                                               if (brightness > 255 ) brightness = 255;
+                                               r = g = b = brightness;
+                                       } else {
+                                               if (invert) {
+                                                       r = 255 - r;
+                                                       g = 255 - g;
+                                                       b = 255 - b;
+                                               }
+                                               if (r < 0 ) r = 0;
+                                               if (g < 0 ) g = 0;
+                                               if (b < 0 ) b = 0;
+                                               if (r > 255 ) r = 255;
+                                               if (g > 255 ) g = 255;
+                                               if (b > 255 ) b = 255;
+                                       }
+
+                                       data[offset] = r;
+                                       data[offset+1] = g;
+                                       data[offset+2] = b;
+
+                               } while (--x);
+                       } while (--y);
+
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}/*
+ * Pixastic Lib - Edge detection 2 - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ * 
+ * Contribution by Oliver Hunt (http://nerget.com/, http://nerget.com/canvas/edgeDetection.js). Thanks Oliver!
+ *
+ */
+
+Pixastic.Actions.edges2 = {
+       process : function(params) {
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var dataCopy = Pixastic.prepareData(params, true)
+
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       var w4 = w * 4;
+                       var pixel = w4 + 4; // Start at (1,1)
+                       var hm1 = h - 1;
+                       var wm1 = w - 1;
+                       for (var y = 1; y < hm1; ++y) {
+                               // Prepare initial cached values for current row
+                               var centerRow = pixel - 4;
+                               var priorRow = centerRow - w4;
+                               var nextRow = centerRow + w4;
+                               
+                               var r1 = - dataCopy[priorRow]   - dataCopy[centerRow]   - dataCopy[nextRow];
+                               var g1 = - dataCopy[++priorRow] - dataCopy[++centerRow] - dataCopy[++nextRow];
+                               var b1 = - dataCopy[++priorRow] - dataCopy[++centerRow] - dataCopy[++nextRow];
+                               
+                               var rp = dataCopy[priorRow += 2];
+                               var gp = dataCopy[++priorRow];
+                               var bp = dataCopy[++priorRow];
+                               
+                               var rc = dataCopy[centerRow += 2];
+                               var gc = dataCopy[++centerRow];
+                               var bc = dataCopy[++centerRow];
+                               
+                               var rn = dataCopy[nextRow += 2];
+                               var gn = dataCopy[++nextRow];
+                               var bn = dataCopy[++nextRow];
+                               
+                               var r2 = - rp - rc - rn;
+                               var g2 = - gp - gc - gn;
+                               var b2 = - bp - bc - bn;
+                               
+                               // Main convolution loop
+                               for (var x = 1; x < wm1; ++x) {
+                                       centerRow = pixel + 4;
+                                       priorRow = centerRow - w4;
+                                       nextRow = centerRow + w4;
+                                       
+                                       var r = 127 + r1 - rp - (rc * -8) - rn;
+                                       var g = 127 + g1 - gp - (gc * -8) - gn;
+                                       var b = 127 + b1 - bp - (bc * -8) - bn;
+                                       
+                                       r1 = r2;
+                                       g1 = g2;
+                                       b1 = b2;
+                                       
+                                       rp = dataCopy[  priorRow];
+                                       gp = dataCopy[++priorRow];
+                                       bp = dataCopy[++priorRow];
+                                       
+                                       rc = dataCopy[  centerRow];
+                                       gc = dataCopy[++centerRow];
+                                       bc = dataCopy[++centerRow];
+                                       
+                                       rn = dataCopy[  nextRow];
+                                       gn = dataCopy[++nextRow];
+                                       bn = dataCopy[++nextRow];
+                                       
+                                       r += (r2 = - rp - rc - rn);
+                                       g += (g2 = - gp - gc - gn);
+                                       b += (b2 = - bp - bc - bn);
+
+                                       if (r > 255) r = 255;
+                                       if (g > 255) g = 255;
+                                       if (b > 255) b = 255;
+                                       if (r < 0) r = 0;
+                                       if (g < 0) g = 0;
+                                       if (b < 0) b = 0;
+
+                                       data[pixel] = r;
+                                       data[++pixel] = g;
+                                       data[++pixel] = b;
+                                       //data[++pixel] = 255; // alpha
+
+                                       pixel+=2;
+                               }
+                               pixel += 8;
+                       }
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}/*
+ * Pixastic Lib - Emboss filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.emboss = {
+       process : function(params) {
+
+               var strength = parseFloat(params.options.strength)||1;
+               var greyLevel = typeof params.options.greyLevel != "undefined" ? parseInt(params.options.greyLevel) : 180;
+               var direction = params.options.direction||"topleft";
+               var blend = !!(params.options.blend && params.options.blend != "false");
+
+               var dirY = 0;
+               var dirX = 0;
+
+               switch (direction) {
+                       case "topleft":                 // top left
+                               dirY = -1;
+                               dirX = -1;
+                               break;
+                       case "top":                     // top
+                               dirY = -1;
+                               dirX = 0;
+                               break;
+                       case "topright":                        // top right
+                               dirY = -1;
+                               dirX = 1;
+                               break;
+                       case "right":                   // right
+                               dirY = 0;
+                               dirX = 1;
+                               break;
+                       case "bottomright":                     // bottom right
+                               dirY = 1;
+                               dirX = 1;
+                               break;
+                       case "bottom":                  // bottom
+                               dirY = 1;
+                               dirX = 0;
+                               break;
+                       case "bottomleft":                      // bottom left
+                               dirY = 1;
+                               dirX = -1;
+                               break;
+                       case "left":                    // left
+                               dirY = 0;
+                               dirX = -1;
+                               break;
+               }
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var dataCopy = Pixastic.prepareData(params, true)
+
+                       var invertAlpha = !!params.options.invertAlpha;
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+
+                               var otherY = dirY;
+                               if (y + otherY < 1) otherY = 0;
+                               if (y + otherY > h) otherY = 0;
+
+                               var offsetYOther = (y-1+otherY)*w*4;
+
+                               var x = w;
+                               do {
+                                               var offset = offsetY + (x-1)*4;
+
+                                               var otherX = dirX;
+                                               if (x + otherX < 1) otherX = 0;
+                                               if (x + otherX > w) otherX = 0;
+
+                                               var offsetOther = offsetYOther + (x-1+otherX)*4;
+
+                                               var dR = dataCopy[offset] - dataCopy[offsetOther];
+                                               var dG = dataCopy[offset+1] - dataCopy[offsetOther+1];
+                                               var dB = dataCopy[offset+2] - dataCopy[offsetOther+2];
+
+                                               var dif = dR;
+                                               var absDif = dif > 0 ? dif : -dif;
+
+                                               var absG = dG > 0 ? dG : -dG;
+                                               var absB = dB > 0 ? dB : -dB;
+
+                                               if (absG > absDif) {
+                                                       dif = dG;
+                                               }
+                                               if (absB > absDif) {
+                                                       dif = dB;
+                                               }
+
+                                               dif *= strength;
+
+                                               if (blend) {
+                                                       var r = data[offset] + dif;
+                                                       var g = data[offset+1] + dif;
+                                                       var b = data[offset+2] + dif;
+
+                                                       data[offset] = (r > 255) ? 255 : (r < 0 ? 0 : r);
+                                                       data[offset+1] = (g > 255) ? 255 : (g < 0 ? 0 : g);
+                                                       data[offset+2] = (b > 255) ? 255 : (b < 0 ? 0 : b);
+                                               } else {
+                                                       var grey = greyLevel - dif;
+                                                       if (grey < 0) {
+                                                               grey = 0;
+                                                       } else if (grey > 255) {
+                                                               grey = 255;
+                                                       }
+
+                                                       data[offset] = data[offset+1] = data[offset+2] = grey;
+                                               }
+
+                               } while (--x);
+                       } while (--y);
+                       return true;
+
+               } else if (Pixastic.Client.isIE()) {
+                       params.image.style.filter += " progid:DXImageTransform.Microsoft.emboss()";
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
+       }
+
+}
+/*
+ * Pixastic Lib - Flip - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.flip = {
+       process : function(params) {
+               var rect = params.options.rect;
+               var copyCanvas = document.createElement("canvas");
+               copyCanvas.width = rect.width;
+               copyCanvas.height = rect.height;
+               copyCanvas.getContext("2d").drawImage(params.image, rect.left, rect.top, rect.width, rect.height, 0, 0, rect.width, rect.height);
+
+               var ctx = params.canvas.getContext("2d");
+               ctx.clearRect(rect.left, rect.top, rect.width, rect.height);
+
+               if (params.options.axis == "horizontal") {
+                       ctx.scale(-1,1);
+                       ctx.drawImage(copyCanvas, -rect.left-rect.width, rect.top, rect.width, rect.height)
+               } else {
+                       ctx.scale(1,-1);
+                       ctx.drawImage(copyCanvas, rect.left, -rect.top-rect.height, rect.width, rect.height)
+               }
+
+               params.useData = false;
+
+               return true;            
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvas();
+       }
+}
+
+/*
+ * Pixastic Lib - Horizontal flip - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.fliph = {
+       process : function(params) {
+               if (Pixastic.Client.hasCanvas()) {
+                       var rect = params.options.rect;
+                       var copyCanvas = document.createElement("canvas");
+                       copyCanvas.width = rect.width;
+                       copyCanvas.height = rect.height;
+                       copyCanvas.getContext("2d").drawImage(params.image, rect.left, rect.top, rect.width, rect.height, 0, 0, rect.width, rect.height);
+
+                       var ctx = params.canvas.getContext("2d");
+                       ctx.clearRect(rect.left, rect.top, rect.width, rect.height);
+                       ctx.scale(-1,1);
+                       ctx.drawImage(copyCanvas, -rect.left-rect.width, rect.top, rect.width, rect.height)
+                       params.useData = false;
+
+                       return true;            
+
+               } else if (Pixastic.Client.isIE()) {
+                       params.image.style.filter += " fliph";
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvas() || Pixastic.Client.isIE());
+       }
+}
+
+/*
+ * Pixastic Lib - Vertical flip - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.flipv = {
+       process : function(params) {
+               if (Pixastic.Client.hasCanvas()) {
+                       var rect = params.options.rect;
+                       var copyCanvas = document.createElement("canvas");
+                       copyCanvas.width = rect.width;
+                       copyCanvas.height = rect.height;
+                       copyCanvas.getContext("2d").drawImage(params.image, rect.left, rect.top, rect.width, rect.height, 0, 0, rect.width, rect.height);
+
+                       var ctx = params.canvas.getContext("2d");
+                       ctx.clearRect(rect.left, rect.top, rect.width, rect.height);
+                       ctx.scale(1,-1);
+                       ctx.drawImage(copyCanvas, rect.left, -rect.top-rect.height, rect.width, rect.height)
+                       params.useData = false;
+
+                       return true;            
+
+               } else if (Pixastic.Client.isIE()) {
+                       params.image.style.filter += " flipv";
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvas() || Pixastic.Client.isIE());
+       }
+}
+
+/*
+ * Pixastic Lib - Glow - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+
+Pixastic.Actions.glow = {
+       process : function(params) {
+
+               var amount = (parseFloat(params.options.amount)||0);
+               var blurAmount = parseFloat(params.options.radius)||0;
+
+               amount = Math.min(1,Math.max(0,amount));
+               blurAmount = Math.min(5,Math.max(0,blurAmount));
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var rect = params.options.rect;
+
+                       var blurCanvas = document.createElement("canvas");
+                       blurCanvas.width = params.width;
+                       blurCanvas.height = params.height;
+                       var blurCtx = blurCanvas.getContext("2d");
+                       blurCtx.drawImage(params.canvas,0,0);
+
+                       var scale = 2;
+                       var smallWidth = Math.round(params.width / scale);
+                       var smallHeight = Math.round(params.height / scale);
+
+                       var copy = document.createElement("canvas");
+                       copy.width = smallWidth;
+                       copy.height = smallHeight;
+
+                       var clear = true;
+                       var steps = Math.round(blurAmount * 20);
+
+                       var copyCtx = copy.getContext("2d");
+                       for (var i=0;i<steps;i++) {
+                               var scaledWidth = Math.max(1,Math.round(smallWidth - i));
+                               var scaledHeight = Math.max(1,Math.round(smallHeight - i));
+       
+                               copyCtx.clearRect(0,0,smallWidth,smallHeight);
+       
+                               copyCtx.drawImage(
+                                       blurCanvas,
+                                       0,0,params.width,params.height,
+                                       0,0,scaledWidth,scaledHeight
+                               );
+       
+                               blurCtx.clearRect(0,0,params.width,params.height);
+       
+                               blurCtx.drawImage(
+                                       copy,
+                                       0,0,scaledWidth,scaledHeight,
+                                       0,0,params.width,params.height
+                               );
+                       }
+
+                       var data = Pixastic.prepareData(params);
+                       var blurData = Pixastic.prepareData({canvas:blurCanvas,options:params.options});
+                       var w = rect.width;
+                       var h = rect.height;
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x*4-4);
+
+                                       var r = data[offset] + amount * blurData[offset];
+                                       var g = data[offset+1] + amount * blurData[offset+1];
+                                       var b = data[offset+2] + amount * blurData[offset+2];
+       
+                                       if (r > 255) r = 255;
+                                       if (g > 255) g = 255;
+                                       if (b > 255) b = 255;
+                                       if (r < 0) r = 0;
+                                       if (g < 0) g = 0;
+                                       if (b < 0) b = 0;
+
+                                       data[offset] = r;
+                                       data[offset+1] = g;
+                                       data[offset+2] = b;
+
+                               } while (--x);
+                       } while (--y);
+
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}
+
+
+
+/*
+ * Pixastic Lib - Histogram - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.histogram = {
+       process : function(params) {
+
+               var average = !!(params.options.average && params.options.average != "false");
+               var paint = !!(params.options.paint && params.options.paint != "false");
+               var color = params.options.color || "rgba(255,255,255,0.5)";
+               var values = [];
+               if (typeof params.options.returnValue != "object") {
+                       params.options.returnValue = {values:[]};
+               }
+               var returnValue = params.options.returnValue;
+               if (typeof returnValue.values != "array") {
+                       returnValue.values = [];
+               }
+               values = returnValue.values;
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       params.useData = false;
+
+                       for (var i=0;i<256;i++) {
+                               values[i] = 0;
+                       }
+
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x*4-4);
+                                       var brightness = average ? 
+                                               Math.round((data[offset]+data[offset+1]+data[offset+2])/3)
+                                               : Math.round(data[offset]*0.3 + data[offset+1]*0.59 + data[offset+2]*0.11);
+                                       values[brightness]++;
+
+                               } while (--x);
+                       } while (--y);
+
+                       if (paint) {
+                               var maxValue = 0;
+                               for (var i=0;i<256;i++) {
+                                       if (values[i] > maxValue) {
+                                               maxValue = values[i];
+                                       }
+                               }
+                               var heightScale = params.height / maxValue;
+                               var widthScale = params.width / 256;
+                               var ctx = params.canvas.getContext("2d");
+                               ctx.fillStyle = color;
+                               for (var i=0;i<256;i++) {
+                                       ctx.fillRect(
+                                               i * widthScale, params.height - heightScale * values[i],
+                                               widthScale, values[i] * heightScale
+                                       );
+                               }
+                       }
+
+                       returnValue.values = values;
+
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}
+/*
+ * Pixastic Lib - HSL Adjust  - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.hsl = {
+       process : function(params) {
+
+               var hue = parseInt(params.options.hue,10)||0;
+               var saturation = (parseInt(params.options.saturation,10)||0) / 100;
+               var lightness = (parseInt(params.options.lightness,10)||0) / 100;
+
+
+               // this seems to give the same result as Photoshop
+               if (saturation < 0) {
+                       var satMul = 1+saturation;
+               } else {
+                       var satMul = 1+saturation*2;
+               }
+
+               hue = (hue%360) / 360;
+               var hue6 = hue * 6;
+
+               var rgbDiv = 1 / 255;
+
+               var light255 = lightness * 255;
+               var lightp1 = 1 + lightness;
+               var lightm1 = 1 - lightness;
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       var w4 = w*4;
+                       var y = h;
+
+                       do {
+                               var offsetY = (y-1)*w4;
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x*4-4);
+
+                                       var r = data[offset];
+                                       var g = data[offset+1];
+                                       var b = data[offset+2];
+
+                                       if (hue != 0 || saturation != 0) {
+                                               // ok, here comes rgb to hsl + adjust + hsl to rgb, all in one jumbled mess. 
+                                               // It's not so pretty, but it's been optimized to get somewhat decent performance.
+                                               // The transforms were originally adapted from the ones found in Graphics Gems, but have been heavily modified.
+                                               var vs = r;
+                                               if (g > vs) vs = g;
+                                               if (b > vs) vs = b;
+                                               var ms = r;
+                                               if (g < ms) ms = g;
+                                               if (b < ms) ms = b;
+                                               var vm = (vs-ms);
+                                               var l = (ms+vs)/255 * 0.5;
+                                               if (l > 0) {
+                                                       if (vm > 0) {
+                                                               if (l <= 0.5) {
+                                                                       var s = vm / (vs+ms) * satMul;
+                                                                       if (s > 1) s = 1;
+                                                                       var v = (l * (1+s));
+                                                               } else {
+                                                                       var s = vm / (510-vs-ms) * satMul;
+                                                                       if (s > 1) s = 1;
+                                                                       var v = (l+s - l*s);
+                                                               }
+                                                               if (r == vs) {
+                                                                       if (g == ms)
+                                                                               var h = 5 + ((vs-b)/vm) + hue6;
+                                                                       else
+                                                                               var h = 1 - ((vs-g)/vm) + hue6;
+                                                               } else if (g == vs) {
+                                                                       if (b == ms)
+                                                                               var h = 1 + ((vs-r)/vm) + hue6;
+                                                                       else
+                                                                               var h = 3 - ((vs-b)/vm) + hue6;
+                                                               } else {
+                                                                       if (r == ms)
+                                                                               var h = 3 + ((vs-g)/vm) + hue6;
+                                                                       else
+                                                                               var h = 5 - ((vs-r)/vm) + hue6;
+                                                               }
+                                                               if (h < 0) h+=6;
+                                                               if (h >= 6) h-=6;
+                                                               var m = (l+l-v);
+                                                               var sextant = h>>0;
+                                                               switch (sextant) {
+                                                                       case 0: r = v*255; g = (m+((v-m)*(h-sextant)))*255; b = m*255; break;
+                                                                       case 1: r = (v-((v-m)*(h-sextant)))*255; g = v*255; b = m*255; break;
+                                                                       case 2: r = m*255; g = v*255; b = (m+((v-m)*(h-sextant)))*255; break;
+                                                                       case 3: r = m*255; g = (v-((v-m)*(h-sextant)))*255; b = v*255; break;
+                                                                       case 4: r = (m+((v-m)*(h-sextant)))*255; g = m*255; b = v*255; break;
+                                                                       case 5: r = v*255; g = m*255; b = (v-((v-m)*(h-sextant)))*255; break;
+                                                               }
+                                                       }
+                                               }
+                                       }
+
+                                       if (lightness < 0) {
+                                               r *= lightp1;
+                                               g *= lightp1;
+                                               b *= lightp1;
+                                       } else if (lightness > 0) {
+                                               r = r * lightm1 + light255;
+                                               g = g * lightm1 + light255;
+                                               b = b * lightm1 + light255;
+                                       }
+
+                                       if (r < 0) r = 0;
+                                       if (g < 0) g = 0;
+                                       if (b < 0) b = 0;
+                                       if (r > 255) r = 255;
+                                       if (g > 255) g = 255;
+                                       if (b > 255) b = 255;
+
+                                       data[offset] = r;
+                                       data[offset+1] = g;
+                                       data[offset+2] = b;
+
+                               } while (--x);
+                       } while (--y);
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+
+}
+/*
+ * Pixastic Lib - Invert filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.invert = {
+       process : function(params) {
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+
+                       var invertAlpha = !!params.options.invertAlpha;
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x-1)*4;
+                                       data[offset] = 255 - data[offset];
+                                       data[offset+1] = 255 - data[offset+1];
+                                       data[offset+2] = 255 - data[offset+2];
+                                       if (invertAlpha) data[offset+3] = 255 - data[offset+3];
+                               } while (--x);
+                       } while (--y);
+
+                       return true;
+               } else if (Pixastic.Client.isIE()) {
+                       params.image.style.filter += " invert";
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
+       }
+}
+/*
+ * Pixastic Lib - Laplace filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.laplace = {
+       process : function(params) {
+
+               var strength = 1.0;
+               var invert = !!(params.options.invert && params.options.invert != "false");
+               var contrast = parseFloat(params.options.edgeStrength)||0;
+
+               var greyLevel = parseInt(params.options.greyLevel)||0;
+
+               contrast = -contrast;
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var dataCopy = Pixastic.prepareData(params, true)
+
+                       var kernel = [
+                               [-1,    -1,     -1],
+                               [-1,    8,      -1],
+                               [-1,    -1,     -1]
+                       ];
+
+                       var weight = 1/8;
+
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+
+                               var nextY = (y == h) ? y - 1 : y;
+                               var prevY = (y == 1) ? 0 : y-2;
+
+                               var offsetYPrev = prevY*w*4;
+                               var offsetYNext = nextY*w*4;
+
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x*4-4);
+
+                                       var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
+                                       var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
+       
+                                       var r = ((-dataCopy[offsetPrev-4]
+                                               - dataCopy[offsetPrev]
+                                               - dataCopy[offsetPrev+4]
+                                               - dataCopy[offset-4]
+                                               - dataCopy[offset+4]
+                                               - dataCopy[offsetNext-4]
+                                               - dataCopy[offsetNext]
+                                               - dataCopy[offsetNext+4])
+                                               + dataCopy[offset] * 8) 
+                                               * weight;
+       
+                                       var g = ((-dataCopy[offsetPrev-3]
+                                               - dataCopy[offsetPrev+1]
+                                               - dataCopy[offsetPrev+5]
+                                               - dataCopy[offset-3]
+                                               - dataCopy[offset+5]
+                                               - dataCopy[offsetNext-3]
+                                               - dataCopy[offsetNext+1]
+                                               - dataCopy[offsetNext+5])
+                                               + dataCopy[offset+1] * 8)
+                                               * weight;
+       
+                                       var b = ((-dataCopy[offsetPrev-2]
+                                               - dataCopy[offsetPrev+2]
+                                               - dataCopy[offsetPrev+6]
+                                               - dataCopy[offset-2]
+                                               - dataCopy[offset+6]
+                                               - dataCopy[offsetNext-2]
+                                               - dataCopy[offsetNext+2]
+                                               - dataCopy[offsetNext+6])
+                                               + dataCopy[offset+2] * 8)
+                                               * weight;
+
+                                       var brightness = ((r + g + b)/3) + greyLevel;
+
+                                       if (contrast != 0) {
+                                               if (brightness > 127) {
+                                                       brightness += ((brightness + 1) - 128) * contrast;
+                                               } else if (brightness < 127) {
+                                                       brightness -= (brightness + 1) * contrast;
+                                               }
+                                       }
+                                       if (invert) {
+                                               brightness = 255 - brightness;
+                                       }
+                                       if (brightness < 0 ) brightness = 0;
+                                       if (brightness > 255 ) brightness = 255;
+
+                                       data[offset] = data[offset+1] = data[offset+2] = brightness;
+
+                               } while (--x);
+                       } while (--y);
+
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}
+
+/*
+ * Pixastic Lib - Lighten filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.lighten = {
+
+       process : function(params) {
+               var amount = parseFloat(params.options.amount) || 0;
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x-1)*4;
+
+                                       var r = data[offset];
+                                       var g = data[offset+1];
+                                       var b = data[offset+2];
+
+                                       r += r*amount;
+                                       g += g*amount;
+                                       b += b*amount;
+
+                                       if (r < 0 ) r = 0;
+                                       if (g < 0 ) g = 0;
+                                       if (b < 0 ) b = 0;
+                                       if (r > 255 ) r = 255;
+                                       if (g > 255 ) g = 255;
+                                       if (b > 255 ) b = 255;
+
+                                       data[offset] = r;
+                                       data[offset+1] = g;
+                                       data[offset+2] = b;
+
+                               } while (--x);
+                       } while (--y);
+                       return true;
+
+               } else if (Pixastic.Client.isIE()) {
+                       var img = params.image;
+                       if (amount < 0) {
+                               img.style.filter += " light()";
+                               img.filters[img.filters.length-1].addAmbient(
+                                       255,255,255,
+                                       100 * -amount
+                               );
+                       } else if (amount > 0) {
+                               img.style.filter += " light()";
+                               img.filters[img.filters.length-1].addAmbient(
+                                       255,255,255,
+                                       100
+                               );
+                               img.filters[img.filters.length-1].addAmbient(
+                                       255,255,255,
+                                       100 * amount
+                               );
+                       }
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
+       }
+}
+/*
+ * Pixastic Lib - Mosaic filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.mosaic = {
+
+       process : function(params) {
+               var blockSize = Math.max(1,parseInt(params.options.blockSize,10));
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+                       var w4 = w*4;
+                       var y = h;
+
+                       var ctx = params.canvas.getContext("2d");
+
+                       var pixel = document.createElement("canvas");
+                       pixel.width = pixel.height = 1;
+                       var pixelCtx = pixel.getContext("2d");
+
+                       var copy = document.createElement("canvas");
+                       copy.width = w;
+                       copy.height = h;
+                       var copyCtx = copy.getContext("2d");
+                       copyCtx.drawImage(params.canvas,rect.left,rect.top,w,h, 0,0,w,h);
+
+                       for (var y=0;y<h;y+=blockSize) {
+                               for (var x=0;x<w;x+=blockSize) {
+                                       var blockSizeX = blockSize;
+                                       var blockSizeY = blockSize;
+               
+                                       if (blockSizeX + x > w)
+                                               blockSizeX = w - x;
+                                       if (blockSizeY + y > h)
+                                               blockSizeY = h - y;
+
+                                       pixelCtx.drawImage(copy, x, y, blockSizeX, blockSizeY, 0, 0, 1, 1);
+                                       var data = pixelCtx.getImageData(0,0,1,1).data;
+                                       ctx.fillStyle = "rgb(" + data[0] + "," + data[1] + "," + data[2] + ")";
+                                       ctx.fillRect(rect.left + x, rect.top + y, blockSize, blockSize);
+                               }
+                       }
+                       params.useData = false;
+
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvasImageData());
+       }
+}/*
+ * Pixastic Lib - Noise filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.noise = {
+
+       process : function(params) {
+               var amount = 0;
+               var strength = 0;
+               var mono = false;
+
+               if (typeof params.options.amount != "undefined")
+                       amount = parseFloat(params.options.amount)||0;
+               if (typeof params.options.strength != "undefined")
+                       strength = parseFloat(params.options.strength)||0;
+               if (typeof params.options.mono != "undefined")
+                       mono = !!(params.options.mono && params.options.mono != "false");
+
+               amount = Math.max(0,Math.min(1,amount));
+               strength = Math.max(0,Math.min(1,strength));
+
+               var noise = 128 * strength;
+               var noise2 = noise / 2;
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+                       var w4 = w*4;
+                       var y = h;
+                       var random = Math.random;
+
+                       do {
+                               var offsetY = (y-1)*w4;
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x-1)*4;
+                                       if (random() < amount) {
+                                               if (mono) {
+                                                       var pixelNoise = - noise2 + random() * noise;
+                                                       var r = data[offset] + pixelNoise;
+                                                       var g = data[offset+1] + pixelNoise;
+                                                       var b = data[offset+2] + pixelNoise;
+                                               } else {
+                                                       var r = data[offset] - noise2 + (random() * noise);
+                                                       var g = data[offset+1] - noise2 + (random() * noise);
+                                                       var b = data[offset+2] - noise2 + (random() * noise);
+                                               }
+
+                                               if (r < 0 ) r = 0;
+                                               if (g < 0 ) g = 0;
+                                               if (b < 0 ) b = 0;
+                                               if (r > 255 ) r = 255;
+                                               if (g > 255 ) g = 255;
+                                               if (b > 255 ) b = 255;
+
+                                               data[offset] = r;
+                                               data[offset+1] = g;
+                                               data[offset+2] = b;
+                                       }
+                               } while (--x);
+                       } while (--y);
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}
+
+/*
+ * Pixastic Lib - Posterize effect - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.posterize = {
+
+       process : function(params) {
+
+               
+               var numLevels = 256;
+               if (typeof params.options.levels != "undefined")
+                       numLevels = parseInt(params.options.levels,10)||1;
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+
+                       numLevels = Math.max(2,Math.min(256,numLevels));
+       
+                       var numAreas = 256 / numLevels;
+                       var numValues = 256 / (numLevels-1);
+
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x-1)*4;
+
+                                       var r = numValues * ((data[offset] / numAreas)>>0);
+                                       var g = numValues * ((data[offset+1] / numAreas)>>0);
+                                       var b = numValues * ((data[offset+2] / numAreas)>>0);
+
+                                       if (r > 255) r = 255;
+                                       if (g > 255) g = 255;
+                                       if (b > 255) b = 255;
+
+                                       data[offset] = r;
+                                       data[offset+1] = g;
+                                       data[offset+2] = b;
+
+                               } while (--x);
+                       } while (--y);
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}
+
+
+/*
+ * Pixastic Lib - Pointillize filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.pointillize = {
+
+       process : function(params) {
+               var radius = Math.max(1,parseInt(params.options.radius,10));
+               var density = Math.min(5,Math.max(0,parseFloat(params.options.density)||0));
+               var noise = Math.max(0,parseFloat(params.options.noise)||0);
+               var transparent = !!(params.options.transparent && params.options.transparent != "false");
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+                       var w4 = w*4;
+                       var y = h;
+
+                       var ctx = params.canvas.getContext("2d");
+                       var canvasWidth = params.canvas.width;
+                       var canvasHeight = params.canvas.height;
+
+                       var pixel = document.createElement("canvas");
+                       pixel.width = pixel.height = 1;
+                       var pixelCtx = pixel.getContext("2d");
+
+                       var copy = document.createElement("canvas");
+                       copy.width = w;
+                       copy.height = h;
+                       var copyCtx = copy.getContext("2d");
+                       copyCtx.drawImage(params.canvas,rect.left,rect.top,w,h, 0,0,w,h);
+
+                       var diameter = radius * 2;
+
+                       if (transparent)
+                               ctx.clearRect(rect.left, rect.top, rect.width, rect.height);
+
+                       var noiseRadius = radius * noise;
+
+                       var dist = 1 / density;
+
+                       for (var y=0;y<h+radius;y+=diameter*dist) {
+                               for (var x=0;x<w+radius;x+=diameter*dist) {
+                                       rndX = noise ? (x+((Math.random()*2-1) * noiseRadius))>>0 : x;
+                                       rndY = noise ? (y+((Math.random()*2-1) * noiseRadius))>>0 : y;
+
+                                       var pixX = rndX - radius;
+                                       var pixY = rndY - radius;
+                                       if (pixX < 0) pixX = 0;
+                                       if (pixY < 0) pixY = 0;
+
+                                       var cx = rndX + rect.left;
+                                       var cy = rndY + rect.top;
+                                       if (cx < 0) cx = 0;
+                                       if (cx > canvasWidth) cx = canvasWidth;
+                                       if (cy < 0) cy = 0;
+                                       if (cy > canvasHeight) cy = canvasHeight;
+
+                                       var diameterX = diameter;
+                                       var diameterY = diameter;
+
+                                       if (diameterX + pixX > w)
+                                               diameterX = w - pixX;
+                                       if (diameterY + pixY > h)
+                                               diameterY = h - pixY;
+                                       if (diameterX < 1) diameterX = 1;
+                                       if (diameterY < 1) diameterY = 1;
+
+                                       pixelCtx.drawImage(copy, pixX, pixY, diameterX, diameterY, 0, 0, 1, 1);
+                                       var data = pixelCtx.getImageData(0,0,1,1).data;
+
+                                       ctx.fillStyle = "rgb(" + data[0] + "," + data[1] + "," + data[2] + ")";
+                                       ctx.beginPath();
+                                       ctx.arc(cx, cy, radius, 0, Math.PI*2, true);
+                                       ctx.closePath();
+                                       ctx.fill();
+                               }
+                       }
+
+                       params.useData = false;
+
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvasImageData());
+       }
+}/*
+ * Pixastic Lib - Resize - v0.1.0
+ * Copyright (c) 2009 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.resize = {
+       process : function(params) {
+               if (Pixastic.Client.hasCanvas()) {
+                       var width = parseInt(params.options.width,10);
+                       var height = parseInt(params.options.height,10);
+                       var canvas = params.canvas;
+
+                       if (width < 1) width = 1;
+                       if (width < 2) width = 2;
+
+                       var copy = document.createElement("canvas");
+                       copy.width = width;
+                       copy.height = height;
+
+                       copy.getContext("2d").drawImage(canvas,0,0,width,height);
+                       canvas.width = width;
+                       canvas.height = height;
+
+                       canvas.getContext("2d").drawImage(copy,0,0);
+
+                       params.useData = false;
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvas();
+       }
+}
+
+
+/*
+ * Pixastic Lib - Remove noise - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.removenoise = {
+       process : function(params) {
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+
+                               var nextY = (y == h) ? y - 1 : y;
+                               var prevY = (y == 1) ? 0 : y-2;
+
+                               var offsetYPrev = prevY*w*4;
+                               var offsetYNext = nextY*w*4;
+
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x*4-4);
+
+                                       var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
+                                       var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
+
+                                       var minR, maxR, minG, maxG, minB, maxB;
+
+                                       minR = maxR = data[offsetPrev];
+                                       var r1 = data[offset-4], r2 = data[offset+4], r3 = data[offsetNext];
+                                       if (r1 < minR) minR = r1;
+                                       if (r2 < minR) minR = r2;
+                                       if (r3 < minR) minR = r3;
+                                       if (r1 > maxR) maxR = r1;
+                                       if (r2 > maxR) maxR = r2;
+                                       if (r3 > maxR) maxR = r3;
+
+                                       minG = maxG = data[offsetPrev+1];
+                                       var g1 = data[offset-3], g2 = data[offset+5], g3 = data[offsetNext+1];
+                                       if (g1 < minG) minG = g1;
+                                       if (g2 < minG) minG = g2;
+                                       if (g3 < minG) minG = g3;
+                                       if (g1 > maxG) maxG = g1;
+                                       if (g2 > maxG) maxG = g2;
+                                       if (g3 > maxG) maxG = g3;
+
+                                       minB = maxB = data[offsetPrev+2];
+                                       var b1 = data[offset-2], b2 = data[offset+6], b3 = data[offsetNext+2];
+                                       if (b1 < minB) minB = b1;
+                                       if (b2 < minB) minB = b2;
+                                       if (b3 < minB) minB = b3;
+                                       if (b1 > maxB) maxB = b1;
+                                       if (b2 > maxB) maxB = b2;
+                                       if (b3 > maxB) maxB = b3;
+
+                                       if (data[offset] > maxR) {
+                                               data[offset] = maxR;
+                                       } else if (data[offset] < minR) {
+                                               data[offset] = minR;
+                                       }
+                                       if (data[offset+1] > maxG) {
+                                               data[offset+1] = maxG;
+                                       } else if (data[offset+1] < minG) {
+                                               data[offset+1] = minG;
+                                       }
+                                       if (data[offset+2] > maxB) {
+                                               data[offset+2] = maxB;
+                                       } else if (data[offset+2] < minB) {
+                                               data[offset+2] = minB;
+                                       }
+
+                               } while (--x);
+                       } while (--y);
+
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}/*
+ * Pixastic Lib - Rotate - v0.1.0
+ * Copyright (c) 2009 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.rotate = {
+       process : function(params) {
+               if (Pixastic.Client.hasCanvas()) {
+                       var canvas = params.canvas;
+
+                       var width = params.width;
+                       var height = params.height;
+
+                       var copy = document.createElement("canvas");
+                       copy.width = width;
+                       copy.height = height;
+                       copy.getContext("2d").drawImage(canvas,0,0,width,height);
+
+                       var angle = -parseFloat(params.options.angle) * Math.PI / 180;
+
+                       var dimAngle = angle;
+                       if (dimAngle > Math.PI*0.5)
+                               dimAngle = Math.PI - dimAngle;
+                       if (dimAngle < -Math.PI*0.5)
+                               dimAngle = -Math.PI - dimAngle;
+
+                       var diag = Math.sqrt(width*width + height*height);
+
+                       var diagAngle1 = Math.abs(dimAngle) - Math.abs(Math.atan2(height, width));
+                       var diagAngle2 = Math.abs(dimAngle) + Math.abs(Math.atan2(height, width));
+
+                       var newWidth = Math.abs(Math.cos(diagAngle1) * diag);
+                       var newHeight = Math.abs(Math.sin(diagAngle2) * diag);
+
+                       canvas.width = newWidth;
+                       canvas.height = newHeight;
+
+                       var ctx = canvas.getContext("2d");
+                       ctx.translate(newWidth/2, newHeight/2);
+                       ctx.rotate(angle);
+                       ctx.drawImage(copy,-width/2,-height/2);
+
+                       params.useData = false;
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvas();
+       }
+}
+
+
+/*
+ * Pixastic Lib - Sepia filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.sepia = {
+
+       process : function(params) {
+               var mode = (parseInt(params.options.mode,10)||0);
+               if (mode < 0) mode = 0;
+               if (mode > 1) mode = 1;
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x-1)*4;
+
+                                       if (mode) {
+                                               // a bit faster, but not as good
+                                               var d = data[offset] * 0.299 + data[offset+1] * 0.587 + data[offset+2] * 0.114;
+                                               var r = (d + 39);
+                                               var g = (d + 14);
+                                               var b = (d - 36);
+                                       } else {
+                                               // Microsoft
+                                               var or = data[offset];
+                                               var og = data[offset+1];
+                                               var ob = data[offset+2];
+       
+                                               var r = (or * 0.393 + og * 0.769 + ob * 0.189);
+                                               var g = (or * 0.349 + og * 0.686 + ob * 0.168);
+                                               var b = (or * 0.272 + og * 0.534 + ob * 0.131);
+                                       }
+
+                                       if (r < 0) r = 0; if (r > 255) r = 255;
+                                       if (g < 0) g = 0; if (g > 255) g = 255;
+                                       if (b < 0) b = 0; if (b > 255) b = 255;
+
+                                       data[offset] = r;
+                                       data[offset+1] = g;
+                                       data[offset+2] = b;
+
+                               } while (--x);
+                       } while (--y);
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}/*
+ * Pixastic Lib - Sharpen filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.sharpen = {
+       process : function(params) {
+
+               var strength = 0;
+               if (typeof params.options.amount != "undefined")
+                       strength = parseFloat(params.options.amount)||0;
+
+               if (strength < 0) strength = 0;
+               if (strength > 1) strength = 1;
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var dataCopy = Pixastic.prepareData(params, true)
+
+                       var mul = 15;
+                       var mulOther = 1 + 3*strength;
+
+                       var kernel = [
+                               [0,     -mulOther,      0],
+                               [-mulOther,     mul,    -mulOther],
+                               [0,     -mulOther,      0]
+                       ];
+
+                       var weight = 0;
+                       for (var i=0;i<3;i++) {
+                               for (var j=0;j<3;j++) {
+                                       weight += kernel[i][j];
+                               }
+                       }
+
+                       weight = 1 / weight;
+
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       mul *= weight;
+                       mulOther *= weight;
+
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+
+                               var nextY = (y == h) ? y - 1 : y;
+                               var prevY = (y == 1) ? 0 : y-2;
+
+                               var offsetYPrev = prevY*w4;
+                               var offsetYNext = nextY*w4;
+
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x*4-4);
+
+                                       var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
+                                       var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
+
+                                       var r = ((
+                                               - dataCopy[offsetPrev]
+                                               - dataCopy[offset-4]
+                                               - dataCopy[offset+4]
+                                               - dataCopy[offsetNext])         * mulOther
+                                               + dataCopy[offset]      * mul
+                                               );
+
+                                       var g = ((
+                                               - dataCopy[offsetPrev+1]
+                                               - dataCopy[offset-3]
+                                               - dataCopy[offset+5]
+                                               - dataCopy[offsetNext+1])       * mulOther
+                                               + dataCopy[offset+1]    * mul
+                                               );
+
+                                       var b = ((
+                                               - dataCopy[offsetPrev+2]
+                                               - dataCopy[offset-2]
+                                               - dataCopy[offset+6]
+                                               - dataCopy[offsetNext+2])       * mulOther
+                                               + dataCopy[offset+2]    * mul
+                                               );
+
+
+                                       if (r < 0 ) r = 0;
+                                       if (g < 0 ) g = 0;
+                                       if (b < 0 ) b = 0;
+                                       if (r > 255 ) r = 255;
+                                       if (g > 255 ) g = 255;
+                                       if (b > 255 ) b = 255;
+
+                                       data[offset] = r;
+                                       data[offset+1] = g;
+                                       data[offset+2] = b;
+
+                               } while (--x);
+                       } while (--y);
+
+                       return true;
+
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}
+/*
+ * Pixastic Lib - Solarize filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.solarize = {
+
+       process : function(params) {
+               var useAverage = !!(params.options.average && params.options.average != "false");
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x-1)*4;
+
+                                       var r = data[offset];
+                                       var g = data[offset+1];
+                                       var b = data[offset+2];
+
+                                       if (r > 127) r = 255 - r;
+                                       if (g > 127) g = 255 - g;
+                                       if (b > 127) b = 255 - b;
+
+                                       data[offset] = r;
+                                       data[offset+1] = g;
+                                       data[offset+2] = b;
+
+                               } while (--x);
+                       } while (--y);
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvasImageData());
+       }
+}/*
+ * Pixastic Lib - USM - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+
+Pixastic.Actions.unsharpmask = {
+       process : function(params) {
+
+               var amount = (parseFloat(params.options.amount)||0);
+               var blurAmount = parseFloat(params.options.radius)||0;
+               var threshold = parseFloat(params.options.threshold)||0;
+
+               amount = Math.min(500,Math.max(0,amount)) / 2;
+               blurAmount = Math.min(5,Math.max(0,blurAmount)) / 10;
+               threshold = Math.min(255,Math.max(0,threshold));
+
+               threshold--;
+               var thresholdNeg = -threshold;
+
+               amount *= 0.016;
+               amount++;
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var rect = params.options.rect;
+
+                       var blurCanvas = document.createElement("canvas");
+                       blurCanvas.width = params.width;
+                       blurCanvas.height = params.height;
+                       var blurCtx = blurCanvas.getContext("2d");
+                       blurCtx.drawImage(params.canvas,0,0);
+
+                       var scale = 2;
+                       var smallWidth = Math.round(params.width / scale);
+                       var smallHeight = Math.round(params.height / scale);
+
+                       var copy = document.createElement("canvas");
+                       copy.width = smallWidth;
+                       copy.height = smallHeight;
+
+                       var steps = Math.round(blurAmount * 20);
+
+                       var copyCtx = copy.getContext("2d");
+                       for (var i=0;i<steps;i++) {
+                               var scaledWidth = Math.max(1,Math.round(smallWidth - i));
+                               var scaledHeight = Math.max(1,Math.round(smallHeight - i));
+
+                               copyCtx.clearRect(0,0,smallWidth,smallHeight);
+
+                               copyCtx.drawImage(
+                                       blurCanvas,
+                                       0,0,params.width,params.height,
+                                       0,0,scaledWidth,scaledHeight
+                               );
+       
+                               blurCtx.clearRect(0,0,params.width,params.height);
+       
+                               blurCtx.drawImage(
+                                       copy,
+                                       0,0,scaledWidth,scaledHeight,
+                                       0,0,params.width,params.height
+                               );
+                       }
+
+                       var data = Pixastic.prepareData(params);
+                       var blurData = Pixastic.prepareData({canvas:blurCanvas,options:params.options});
+                       var w = rect.width;
+                       var h = rect.height;
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x*4-4);
+
+                                       var difR = data[offset] - blurData[offset];
+                                       if (difR > threshold || difR < thresholdNeg) {
+                                               var blurR = blurData[offset];
+                                               blurR = amount * difR + blurR;
+                                               data[offset] = blurR > 255 ? 255 : (blurR < 0 ? 0 : blurR);
+                                       }
+
+                                       var difG = data[offset+1] - blurData[offset+1];
+                                       if (difG > threshold || difG < thresholdNeg) {
+                                               var blurG = blurData[offset+1];
+                                               blurG = amount * difG + blurG;
+                                               data[offset+1] = blurG > 255 ? 255 : (blurG < 0 ? 0 : blurG);
+                                       }
+
+                                       var difB = data[offset+2] - blurData[offset+2];
+                                       if (difB > threshold || difB < thresholdNeg) {
+                                               var blurB = blurData[offset+2];
+                                               blurB = amount * difB + blurB;
+                                               data[offset+2] = blurB > 255 ? 255 : (blurB < 0 ? 0 : blurB);
+                                       }
+
+                               } while (--x);
+                       } while (--y);
+
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}
+
+
+
+
diff --git a/js2/mwEmbed/libClipEdit/pixastic-editor/pixastic.css b/js2/mwEmbed/libClipEdit/pixastic-editor/pixastic.css
new file mode 100644 (file)
index 0000000..bda133c
--- /dev/null
@@ -0,0 +1,423 @@
+/* http://meyerweb.com/eric/thoughts/2007/05/01/reset-reloaded/ */
+
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, font, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td {
+       margin: 0;
+       padding: 0;
+       border: 0;
+       outline: 0;
+       font-weight: inherit;
+       font-style: inherit;
+       font-size: 100%;
+       font-family: inherit;
+       vertical-align: baseline;
+}
+/* remember to define focus styles! */
+:focus {
+       outline: 0;
+}
+body {
+       line-height: 1;
+       color: black;
+       background: white;
+}
+ol, ul {
+       list-style: none;
+}
+/* tables still need 'cellspacing="0"' in the markup */
+table {
+       border-collapse: separate;
+       border-spacing: 0;
+}
+caption, th, td {
+       text-align: left;
+       font-weight: normal;
+}
+blockquote:before, blockquote:after,
+q:before, q:after {
+       content: "";
+}
+blockquote, q {
+       quotes: "" "";
+}
+/* end reset */
+
+/* -----------------------
+ *   Base
+ * -----------------------
+ */
+
+/* main container element for editor app */
+#pixastic-editor {
+       margin : 0;
+       position : absolute;
+       left : 0;
+       top : 0;
+       padding: 0px;
+       width: 100%;
+       height: 100%;
+       font-family : Helvetica,Arial,sans-serif;
+       overflow : hidden;
+       z-index : 10000000;
+} 
+
+
+/* -----------------------
+ *   Loading screen
+ * -----------------------
+ */
+
+/* container for loading screen */
+#loading-screen {
+       margin : 0;
+       position : absolute;
+       left : 0;
+       top : 0;
+       padding: 0px;
+       width: 100%;
+       height: 100%;
+       font-family : Helvetica,Arial,sans-serif;
+       overflow : hidden;
+       z-index : 10000000;
+       background-color : #111;
+       opacity : 0.9;
+       display : table;
+       text-align : center;
+} 
+
+/* container for spinner in loading screen */
+#loading-screen-cell {
+       display : table-cell;
+       vertical-align : middle;
+       text-align : center;
+}
+
+
+/* -----------------------
+ *   Misc
+ * -----------------------
+ */
+
+
+// UI error dialog
+.ui-dialog .error-dialog {
+       background-color : #544;
+}
+
+/* loading spinner */
+.spinner {
+       width : 31px;
+       height : 31px;
+       display : inline-block;
+       background: url(spinner.gif);
+       overflow : hidden;
+}
+
+canvas.display-canvas,
+canvas.undo-canvas {
+       /*
+       background : url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAC1JREFUeNpiPHPmDAM2YGxsjFWciYFEMKqBGMD4//9/rBJnz54dDSX6aQAIMABCtQiAsDRF+wAAAABJRU5ErkJggg==');
+       */
+       background : url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAC5JREFUeNpiPHPmTAMDHmBsbIxPmoGJgUIwasBgMICFUDyfPXt2NBCHvwEAAQYAICIGn294LYEAAAAASUVORK5CYII=');
+
+}
+
+.far-far-away {
+       position : absolute;
+       left : -9999px;
+       top : -9999px;
+}
+
+#powered-by-pixastic {
+       position : absolute;
+       bottom : 0px;
+       margin-bottom : 23px;
+       margin-left : 42px;
+}
+#powered-by-pixastic a {
+       font-size : 12px;
+       font-family : Helvetica,Arial,sans-serif;
+       letter-spacing : 0.1em;
+       color : rgb(100,100,100);
+       color : rgba(255,255,255,0.2);
+       text-decoration : none;
+}
+
+#powered-by-pixastic a:hover {
+       color : rgb(200,200,200);
+       color : rgba(255,255,255,0.7);
+       text-decoration : underline;
+}
+
+
+/* -----------------------
+ *   Skeleton structure
+ * -----------------------
+ */
+
+/* editor background underlay */
+#background {
+       background-color : #111;
+       opacity : 0.9;
+       width : 100%;
+       height : 100%;
+       position : absolute;
+       z-index : -1;
+}
+
+#image-area {
+       position : relative;
+       background-color : #222;
+       border : 1px solid #444;
+       width : 100%;
+       height : 100%;
+       -moz-box-sizing:border-box;
+       overflow : auto;
+       text-align : center;
+}
+
+#image-area-sub {
+}
+
+#image-container {
+}
+
+#image-overlay-container {
+       -moz-box-sizing:border-box;
+       width:100%;
+       height:100%;
+       position:absolute;
+       top:0;
+       left:0;
+}
+
+#image-overlay {
+}
+
+
+/* structure elements */
+#edit-ctr-1 {
+       position : absolute;
+       top : 0;
+       left : 0;
+       width : 100%;
+       height : 100%;
+}
+
+#edit-ctr-2 {
+       -moz-box-sizing : border-box;
+       box-sizing : border-box;
+       padding-left:40px;
+       padding-right:420px;
+       padding-top:70px;
+       padding-bottom : 40px;
+       height : 100%;
+       width : 100%;
+}
+
+
+/* main menu bar */
+#main-bar {
+       position : absolute;
+       width : 100%;
+       text-align : right;
+       margin-top : 20px;
+       margin-right : 30px;
+}
+
+/* area on the right with accordion widgets and undo bar */
+#controls-bar {
+       margin-right : -385px;
+       width : 372px;
+       float : right;
+       height : 100%;
+}
+
+/* accordion area */
+#action-bar {
+       padding : 10px;
+       width : 290px;
+       background-color : #222;
+       border : 1px solid #444;
+       -moz-box-sizing : border-box;
+       box-sizing : border-box;
+       height : 100%;
+       overflow-x : hidden;
+       overflow-y : auto;
+       float: right; 
+       position : relative;
+}
+
+#action-bar-overlay {
+       position : absolute;
+       z-index : 1000000;
+       width : 100%;
+       height : 100%;
+       left : 0;
+       top : 0;
+       background-color : #444;
+       opacity : 0.2;
+       display : none;
+}
+
+
+/* vertical bar with undo image states */
+#undo-bar {
+       -moz-box-sizing : border-box;
+       box-sizing : border-box;
+       background-color : #222;
+       border : 1px solid #444;
+       width: 70px; 
+       height: 100%;
+       overflow: hidden;
+       padding-top : 3px;
+}
+
+
+
+/* -----------------------
+ *   Main menu styles
+ * -----------------------
+ */
+
+.main-tab {
+       color : #999;
+       display : inline-block;
+       width : 150px;
+       text-transform : lowercase;
+       font-size : 22px;
+       cursor : pointer;
+       text-align : center;
+       text-decoration : none;
+       padding-top : 4px;
+       padding-bottom : 5px;
+       outline : 0;
+}
+
+.main-tab.hover {
+       color : white !important;
+}
+
+.main-tab.active {
+       color : white;
+}
+
+
+
+/* -----------------------
+ *   Undo list
+ * -----------------------
+ */
+
+
+.undo-canvas-small {
+       width : 60px;
+       height : 40px;
+       cursor : pointer;
+}
+
+.undo-link {
+       width : 60px;
+       height : 40px;
+       display : block;
+       margin : 4px;
+       cursor : pointer;
+       opacity : 0.8;
+}
+
+.undo-link.hover {
+       opacity : 1;
+}
+
+
+
+/* -----------------------
+ *   Action UI controls
+ * -----------------------
+ */
+
+
+.ui-slider-label, 
+.ui-checkbox-label, 
+.ui-textinput-label, 
+.ui-select-label {
+       width : 70px;
+       text-align : right;
+       margin-right : 5px;
+       display : inline-block;
+}
+
+.ui-textinput-label-right {
+       margin-left : 5px;
+}
+
+.ui-textinput {
+}
+
+.ui-numericinput {
+       width : 35px;
+}
+
+.ui-slider {
+       width : 125px;
+       display : inline-block;
+       margin-left : 3px;
+       background-color : #222;
+}
+
+.ui-slider-value {
+       font-size : 11px;
+       width : 25px;
+       display : inline-block;
+       margin-left : 10px;
+}
+
+.ui-action-output {
+       margin-bottom : 10px;
+}
+
+.ui-accordion .ui-accordion-content-active {
+       font-size : 11px;
+       overflow : hidden;
+}
+
+.ui-slider-horizontal {
+}
+
+.ui-slider-container, 
+.ui-checkbox-container, 
+.ui-textinput-container, 
+.ui-select-container {
+       margin-top : 0px;
+       margin-bottom : 10px;
+       white-space : nowrap;
+}
+
+.ui-preview-checkbox-container {
+       display : inline-block;
+}
+
+.ui-checkbox {
+       margin-bottom:3px;
+       margin-left:5px;
+       margin-right:5px;
+       margin-top:0px;
+       vertical-align:middle;
+}
+
+input::-moz-focus-inner { border: 0; }
+
+.action-output-text {
+       margin-bottom : 5px;
+}
+
+button {
+       margin-right : 5px;
+}
+
diff --git a/js2/mwEmbed/libClipEdit/pixastic-editor/ui.js b/js2/mwEmbed/libClipEdit/pixastic-editor/ui.js
new file mode 100644 (file)
index 0000000..6b267ac
--- /dev/null
@@ -0,0 +1,237 @@
+(function($) {
+
+       var PE = PixasticEditor;
+
+       function makeSlider(label, id, min, max, step, defaultVal, onChange) {
+               var $ctr = $j("<div></div>", PE.getDocument())
+                       .addClass("ui-slider-container");
+
+               var $label = $j("<label></label>", PE.getDocument())
+                       .addClass("ui-slider-label")
+                       .attr("for", "input-slider-" + id)
+                       .html(label + ":")
+                       .appendTo($ctr);
+
+               var $value = $j("<div></div>", PE.getDocument())
+                       .addClass("ui-slider-value")
+                       .html(defaultVal());
+
+               var $valueField = $j("<input type='hidden'>", PE.getDocument())
+                       .attr("id", "input-hidden-" + id)
+                       .val(defaultVal())
+                       .appendTo($ctr);
+
+               var performOnChange = true;
+
+               var $slider = $j("<div class='ui-slider'><div class='ui-slider-handle'></div><div class='ui-slider-range'></div></div>", PE.getDocument())
+                       .appendTo($ctr)
+                       .attr("id", "input-slider-" + id)
+                       .slider({
+                               slide: function() {
+                                       $value.html($j(this).slider("value"));
+                                       $valueField.val($j(this).slider("value"));
+                               },
+                               change : function() {
+                                       $value.html($j(this).slider("value"));
+                                       $valueField.val($j(this).slider("value"));
+                                       if (onChange && performOnChange)
+                                               onChange();
+                               },
+                               min : min,
+                               max : max,
+                               step : step,
+                               value : defaultVal()
+                       });
+
+               $value.appendTo($ctr);
+
+               return {
+                       container : $ctr,
+                       label : $label,
+                       slider : $slider,
+                       valueText : $value,
+                       valueField : $valueField,
+                       reset : function() {
+                               performOnChange = false;
+                               $value.html(defaultVal());
+                               $valueField.val(defaultVal());
+                               $slider.slider("value", defaultVal());
+                               performOnChange = true;
+                       }
+               };
+       }
+
+       function makeCheckbox(label, id, defaultVal, onChange) {
+               var $ctr = $j("<div></div>", PE.getDocument())
+                       .addClass("ui-checkbox-container");
+
+               var $label = $j("<label></label>", PE.getDocument())
+                       .addClass("ui-checkbox-label")
+                       .attr("for", "input-checkbox-" + id)
+                       .html(label + ":")
+                       .appendTo($ctr);
+
+               var $valueField = $j("<input type='hidden'>", PE.getDocument())
+                       .attr("id", "input-hidden-" + id)
+                       .val(defaultVal())
+                       .appendTo($ctr);
+
+               var performOnChange = true;
+
+               var $checkbox = $j("<input type=\"checkbox\"></input>", PE.getDocument())
+                       .addClass("ui-checkbox")
+                       .attr("id", "input-checkbox-" + id)
+                       .attr("checked", defaultVal())
+                       .appendTo($ctr)
+                       .change(function() {
+                               $valueField.val(this.checked);
+                               if (onChange && performOnChange)
+                                       onChange();
+                       });
+
+               return {
+                       container : $ctr,
+                       label : $label,
+                       checkbox : $checkbox,
+                       valueField : $valueField,
+                       reset : function() {
+                               performOnChange = false;
+                               $checkbox.attr("checked", defaultVal());
+                               $valueField.val(defaultVal());
+                               performOnChange = true;
+                       }
+               };
+       }
+
+       function makeSelect(label, id, values, defaultVal, onChange) {
+               var $ctr = $j("<div></div>", PE.getDocument())
+                       .addClass("ui-select-container");
+
+               var $label = $j("<label></label>", PE.getDocument())
+                       .addClass("ui-checkbox-label")
+                       .attr("for", "input-checkbox-" + id)
+                       .html(label + ":")
+                       .appendTo($ctr);
+
+               var $valueField = $j("<input type='hidden'>", PE.getDocument())
+                       .attr("id", "input-hidden-" + id)
+                       .val(defaultVal())
+                       .appendTo($ctr);
+
+               var selectHtml = "<select>";
+               for (var i=0;i<values.length;i++) {
+                       selectHtml += "<option value='" + values[i].value + "' " 
+                               + (defaultVal() == values[i].value ? "selected" : "") 
+                               + ">" + values[i].name + "</option>";
+               }
+               selectHtml += "</select>";
+
+               var $select = $j(selectHtml).appendTo($ctr);
+
+               var performOnChange = true;
+
+               $select.change(
+                       function() {
+                               $valueField.val(this.options[this.selectedIndex].value);
+                               if (onChange && performOnChange)
+                                       onChange();
+                       }
+               );
+
+               return {
+                       container : $ctr,
+                       label : $label,
+                       select : $select,
+                       valueField : $valueField,
+                       reset : function() {
+                               performOnChange = false;
+                               var defVal = defaultVal();
+                               $select.val(defVal);
+                               $valueField.val(defVal);
+                               performOnChange = true;
+                       }
+               };
+       }
+
+       function makeNumericInput(label, labelRight, id, min, max, step, defaultVal, onChange) {
+               var $ctr = $j("<div></div>", PE.getDocument())
+                       .addClass("ui-textinput-container");
+
+               var $label = $j("<label></label>", PE.getDocument())
+                       .addClass("ui-textinput-label")
+                       .attr("for", "input-numeric-" + id)
+                       .html(label + ":")
+                       .appendTo($ctr);
+
+               var $valueField = $j("<input type='hidden'>", PE.getDocument())
+                       .attr("id", "input-hidden-" + id)
+                       .val(defaultVal())
+                       .appendTo($ctr);
+
+               var performOnChange = true;
+
+               function setVal(val) {
+                       val = Math.min(max, val);
+                       val = Math.max(min, val);
+                       $textInput.val(val);
+                       $valueField.val(val);
+               }
+
+               var $textInput = $j("<input type=\"text\"></input>", PE.getDocument())
+                       .addClass("ui-textinput")
+                       .addClass("ui-numericinput")
+                       .appendTo($ctr)
+                       .val(defaultVal())
+                       .attr("id", "input-numeric-" + id)
+                       .change(function() {
+                               var val = parseFloat(this.value);
+                               setVal(val);
+                               if (onChange && performOnChange)
+                                       onChange();
+                       })
+                       .keydown(function(e) {
+                               var val = parseFloat($j(this).val());
+                               if (e.keyCode == 38) { // up
+                                       setVal(val + step);
+                               }
+                               if (e.keyCode == 40) { // down
+                                       setVal(val - step);
+                               }
+                       });
+
+               if (labelRight) {
+                       var $labelRight = $j("<label></label>", PE.getDocument())
+                               .addClass("ui-textinput-label-right")
+                               .html(labelRight)
+                               .appendTo($ctr);
+               }
+
+               return {
+                       container : $ctr,
+                       label : $label,
+                       textinput : $textInput,
+                       valueField : $valueField,
+                       reset : function() {
+                               performOnChange = false;
+                               setVal(defaultVal());
+                               performOnChange = true;
+                       }
+               };
+       }
+
+       function makeButton(text) {
+               var $button = $j("<button></button>", PE.getDocument()).html(text);
+               return $button;
+       }
+
+
+       PE.UI = {
+               makeSlider : makeSlider,
+               makeCheckbox : makeCheckbox,
+               makeNumericInput : makeNumericInput,
+               makeSelect : makeSelect,
+               makeButton : makeButton
+       }
+
+})(PixasticEditor.jQuery);
+
diff --git a/js2/mwEmbed/libClipEdit/pixastic-editor/uidata.js b/js2/mwEmbed/libClipEdit/pixastic-editor/uidata.js
new file mode 100644 (file)
index 0000000..ef648f6
--- /dev/null
@@ -0,0 +1,966 @@
+(function($) {
+
+var PE = PixasticEditor;
+
+PE.UI.data = {
+       tabs : [
+               {
+                       title : "Reshape",
+                       id : "reshape",
+                       actions : [
+                               {
+                                       title : "Resize",
+                                       id : "resize",
+                                       isAction : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Enter new dimensions below."
+                                               },
+                                               {
+                                                       label : "Width",
+                                                       labelRight : "px",
+                                                       option : "width",
+                                                       type : "number", 
+                                                       range : [1,10000], 
+                                                       step : 1,
+                                                       defaultValue : function() { return PE.getImageWidth(); },
+                                                       ui : "text"
+                                               },
+                                               {
+                                                       label : "Height",
+                                                       labelRight : "px",
+                                                       option : "height",
+                                                       type : "number", 
+                                                       range : [1,10000], 
+                                                       step : 1,
+                                                       defaultValue : function() { return PE.getImageHeight(); },
+                                                       ui : "text"
+                                               }
+                                       ]
+                               },
+                               {
+                                       title : "Crop",
+                                       id : "crop",
+                                       isAction : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Enter new crop values below or use mouse to select crop area."
+                                               },
+                                               {
+                                                       label : "X",
+                                                       labelRight : "px",
+                                                       option : "left",
+                                                       type : "number", 
+                                                       range : [0,10000], 
+                                                       step : 1,
+                                                       defaultValue : 0,
+                                                       ui : "text"
+                                               },
+                                               {
+                                                       label : "Y",
+                                                       labelRight : "px",
+                                                       option : "top",
+                                                       type : "number", 
+                                                       range : [0,10000], 
+                                                       step : 1,
+                                                       defaultValue : 0,
+                                                       ui : "text"
+                                               },
+                                               {
+                                                       label : "Width",
+                                                       labelRight : "px",
+                                                       option : "width",
+                                                       type : "number", 
+                                                       range : [1,10000], 
+                                                       step : 1,
+                                                       defaultValue : function() { return PE.getImageWidth(); },
+                                                       ui : "text"
+                                               },
+                                               {
+                                                       label : "Height",
+                                                       labelRight : "px",
+                                                       option : "height",
+                                                       type : "number", 
+                                                       range : [1,10000], 
+                                                       step : 1,
+                                                       defaultValue : function() { return PE.getImageHeight(); },
+                                                       ui : "text"
+                                               }
+                                       ],
+                                       onactivate : function() {
+                                               var $canvas = PE.getDisplayCanvas();
+                                               var onchange = function(c) {
+                                                       var doc = PE.getDocument();
+                                                       $j("#input-numeric-crop-left", doc).val(c.x).change();
+                                                       $j("#input-numeric-crop-top", doc).val(c.y).change();
+                                                       $j("#input-numeric-crop-width", doc).val(c.w).change();
+                                                       $j("#input-numeric-crop-height", doc).val(c.h).change();
+                                                       $j("#input-hidden-crop-left", doc).val(c.x).change();
+                                                       $j("#input-hidden-crop-top", doc).val(c.y).change();
+                                                       $j("#input-hidden-crop-width", doc).val(c.w).change();
+                                                       $j("#input-hidden-crop-height", doc).val(c.h).change();
+                                               }
+                                               $canvas.data("Jcrop-onchange", onchange);
+                                               $canvas.Jcrop({onChange:onchange}, PE.getDocument());
+                                       },
+                                       ondeactivate : function() {
+                                               var $canvas = PE.getDisplayCanvas();
+                                               if ($canvas.data("Jcrop") && $canvas.data("Jcrop").destroy)
+                                                       $canvas.data("Jcrop").destroy();
+                                       },
+                                       onafteraction : function(action, isPreview) {
+                                               action.ondeactivate();
+                                               action.onactivate();
+                                               /*
+                                               var $canvas = PE.getDisplayCanvas();
+                                               if ($canvas.data("Jcrop") && $canvas.data("Jcrop").destroy)
+                                                       $canvas.data("Jcrop").destroy();
+                                               var onchange = $canvas.data("Jcrop-onchange");
+                                               $canvas.Jcrop({onChange:onchange});
+                                               */
+                                       }
+                               },
+                               {
+                                       title : "Rotate",
+                                       id : "rotate",
+                                       isAction : true,
+                                       preview : true,
+                                       forcePreview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Enter the angle (-180&deg; to 180&deg;) you want to rotate the picture. Use negative values for clockwise rotation, positive for counterclockwise."
+                                               },
+                                               {
+                                                       label : "Angle",
+                                                       labelRight : "&deg;",
+                                                       option : "angle",
+                                                       type : "number", 
+                                                       range : [-180,180], 
+                                                       step : 1,
+                                                       defaultValue : 0,
+                                                       ui : "text"
+                                               }
+                                       ],
+                                       onactivate : function() {
+                                               var doc = PE.getDocument();
+                                               var $displayCanvas = PE.getDisplayCanvas();
+                                               var dim = Math.min($displayCanvas.attr("height"), 200);
+                                               var $canvas = $j("<canvas></canvas>", doc);
+                                               PE.getOverlay().append($canvas);
+
+                                               $canvas.attr("width", dim);
+                                               $canvas.attr("height", dim);
+                                               $canvas.width(dim);
+                                               $canvas.height(dim);
+
+                                               $canvas.css("marginTop", (($displayCanvas.attr("height") - dim) * 0.5) + "px");
+
+                                               var lineWidth = 20;
+                                               var radius = dim/2 - lineWidth;
+                                               if (radius < 1) radius = 1;
+
+                                               var ctx = $canvas.get(0).getContext("2d");
+                                               ctx.beginPath()
+                                               ctx.arc(dim/2, dim/2, radius, 0, Math.PI*2, true);
+                                               ctx.closePath();
+                                               ctx.fillStyle = "rgba(200,200,200,0.2)";
+                                               ctx.fill();
+                                               ctx.strokeStyle = "rgba(200,200,200,0.5)";
+                                               ctx.lineWidth = 20;
+                                               ctx.stroke();
+
+                                               $j("#image-area", doc).css("cursor", "move");
+
+                                               $overlay = PE.getOverlay();
+
+                                               $canvas.get(0).ondragstart = function() {return false;}
+                                               $canvas.get(0).onselectstart = function() {return false;}
+
+                                               var mx = 0, my = 0;
+                                               var startMouseAngle = 0;
+                                               var startAngle = 0;
+                                               var deltaAngle = 0;
+                                               var angle = 0;
+
+                                               var mouseIsDown = false;
+                                               var onmousedown = function(e) {
+                                                       mouseIsDown = true;
+                                                       var offset = $displayCanvas.offset();
+                                                       mx = (e.pageX - offset.left) - $displayCanvas.attr("width")*0.5;
+                                                       my = (e.pageY - offset.top) - $displayCanvas.attr("height")*0.5;
+                                                       startMouseAngle = Math.atan2(my, mx);
+                                                       startAngle = parseInt($j("#input-numeric-rotate-angle", doc).val(), 10) * Math.PI / 180;
+                                               }
+                                               var onmousemove = function(e) {
+                                                       if (!mouseIsDown) return;
+
+                                                       var offset = $displayCanvas.offset();
+                                                       mx = (e.pageX - offset.left) - $displayCanvas.attr("width")*0.5;
+                                                       my = (e.pageY - offset.top) - $displayCanvas.attr("height")*0.5;
+                                                       deltaAngle = Math.atan2(my, mx) - startMouseAngle;
+                                                       angle = startAngle - deltaAngle;
+                                                       if (angle < -Math.PI) angle += 2*Math.PI;
+                                                       if (angle > Math.PI) angle -= 2*Math.PI;
+                                                       $j("#input-numeric-rotate-angle", doc).val(Math.round(angle * 180 / Math.PI));
+                                                       $j("#input-numeric-rotate-angle", doc).change();
+                                               }
+                                               var onmouseup = function() {
+                                                       mouseIsDown = false;
+                                               }
+
+                                               $j("#image-area", doc).bind("mousedown", onmousedown);
+                                               $j("#image-area", doc).bind("mousemove", onmousemove);
+                                               $j("#image-area", doc).bind("mouseup", onmouseup);
+                                               $canvas.data("onmousedown", onmousedown);
+                                               $canvas.data("onmousemove", onmousemove);
+                                               $canvas.data("onmouseup", onmouseup);
+                                               $displayCanvas.data("rotateCanvas", $canvas);
+                                       },
+                                       ondeactivate : function() {
+                                               var doc = PE.getDocument();
+                                               var $displayCanvas = PE.getDisplayCanvas();
+                                               $overlay = PE.getOverlay();
+                                               $j("#image-area", doc).css("cursor", "default");
+
+                                               var $canvas = $displayCanvas.data("rotateCanvas");
+
+                                               $j("#image-area", doc).unbind("mousedown", $canvas.data("onmousedown"));
+                                               $j("#image-area", doc).unbind("mousemove", $canvas.data("onmousemove"));
+                                               $j("#image-area", doc).unbind("mouseup", $canvas.data("onmouseup"));
+                                               $displayCanvas.removeData("rotateCanvas");
+                                               $canvas.remove();
+                                       },
+                                       onafteraction : function(action, isPreview) {
+                                               if (!isPreview) { // rebuild the rotate widget
+                                                       action.ondeactivate();
+                                                       action.onactivate();
+                                               }
+                                       },
+                                       onoverlayupdate : function() {
+                                               var $canvas = PE.getDisplayCanvas().data("rotateCanvas");
+                                               if ($canvas) {
+                                                       $canvas.css("marginTop", ((PE.getDisplayCanvas().get(0).height - $canvas.get(0).height) * 0.5) + "px");
+                                               }
+                                       }
+                               },
+                               {
+                                       title : "Flip",
+                                       id : "flip",
+                                       isAction : true,
+                                       controls : [
+                                               {
+                                                       label : "Axis",
+                                                       option : "axis",
+                                                       type : "string", 
+                                                       values : [
+                                                               {name:"Horizontal", value:"horizontal"},
+                                                               {name:"Vertical", value:"vertical"}
+                                                       ],
+                                                       defaultValue : "vertical",
+                                                       ui : "select"
+                                               }
+                                       ]
+                               }
+                       ]
+               },
+               {
+                       title : "Develop",
+                       id : "develop",
+                       actions : [
+                               {
+                                       title : "Brightness & Contrast",
+                                       id : "brightness",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Use the sliders below to adjust the brightness and/or contrast of the image."
+                                               },
+                                               {
+                                                       label : "Brightness",
+                                                       option : "brightness",
+                                                       type : "number", 
+                                                       range : [-100,100], 
+                                                       defaultValue : 0,
+                                                       ui : "slider",
+                                                       step : 1
+                                               },
+                                               {
+                                                       label : "Contrast",
+                                                       option : "contrast",
+                                                       type : "number", 
+                                                       range : [-1,1], 
+                                                       defaultValue : 0,
+                                                       ui : "slider",
+                                                       step : 0.01
+                                               },
+                                               {
+                                                       label : "Legacy mode",
+                                                       option : "legacy",
+                                                       type : "boolean", 
+                                                       defaultValue : false,
+                                                       ui : "checkbox"
+                                               }
+                                       ]
+                               },
+                               {
+                                       title : "Hue/Saturation/Lightness",
+                                       id : "hsl",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Use the sliders below to adjust the hue, saturation and/or lightness of the image."
+                                               },
+                                               {
+                                                       label : "Hue",
+                                                       option : "hue",
+                                                       type : "number", 
+                                                       range : [-180,180], 
+                                                       defaultValue : 0,
+                                                       ui : "slider",
+                                                       step : 1
+                                               },
+                                               {
+                                                       label : "Saturation",
+                                                       option : "saturation",
+                                                       type : "number", 
+                                                       range : [-100,100], 
+                                                       defaultValue : 0,
+                                                       ui : "slider",
+                                                       step : 1
+                                               },
+                                               {
+                                                       label : "Lightness",
+                                                       option : "lightness",
+                                                       type : "number", 
+                                                       range : [-100,100], 
+                                                       defaultValue : 0,
+                                                       ui : "slider",
+                                                       step : 1
+                                               }
+                                       ]
+                               },
+                               {
+                                       title : "Adjust colors",
+                                       id : "coloradjust",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Use the sliders below to shift the R, G and B channels of the image."
+                                               },
+                                               {
+                                                       label : "Red",
+                                                       option : "red",
+                                                       type : "number", 
+                                                       range : [-1,1], 
+                                                       defaultValue : 0,
+                                                       ui : "slider",
+                                                       step : 0.01
+                                               },
+                                               {
+                                                       label : "Green",
+                                                       option : "green",
+                                                       type : "number", 
+                                                       range : [-1,1], 
+                                                       defaultValue : 0,
+                                                       ui : "slider",
+                                                       step : 0.01
+                                               },
+                                               {
+                                                       label : "Blue",
+                                                       option : "blue",
+                                                       type : "number", 
+                                                       range : [-1,1], 
+                                                       defaultValue : 0,
+                                                       ui : "slider",
+                                                       step : 0.01
+                                               }
+                                       ]
+                               },
+                               {
+                                       title : "Desaturate",
+                                       id : "desaturate",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "This will desaturate the image. Select \"Use average\" to use the average value of the R, G and B channels rather than the default mix of 30% red, 59% green and 11% blue."
+                                               },
+                                               {
+                                                       label : "Use average",
+                                                       option : "average",
+                                                       type : "boolean", 
+                                                       defaultValue : false,
+                                                       ui : "checkbox"
+                                               }
+                                       ]
+                               },
+                               {
+                                       title : "Sepia toning",
+                                       id : "sepia",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Applies a sepia toning effect to the image."
+                                               }
+                                       ]
+                               },
+                               {
+                                       title : "Invert",
+                                       id : "invert",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "This will invert the colors of the image."
+                                               }
+                                       ]
+                               },
+                               {
+                                       title : "Lighten",
+                                       id : "lighten",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Use the slider below to lighten or darken the image."
+                                               },
+                                               {
+                                                       label : "Amount",
+                                                       option : "amount",
+                                                       type : "number", 
+                                                       range : [-1,1], 
+                                                       defaultValue : 0,
+                                                       ui : "slider",
+                                                       step : 0.01
+                                               }
+                                       ]
+                               },
+                               {
+                                       title : "Unsharp mask",
+                                       id : "unsharpmask",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Use the sliders below to adjust the unsharp mask parameters."
+                                               },
+                                               {
+                                                       label : "Amount",
+                                                       option : "amount",
+                                                       type : "number", 
+                                                       range : [0,500], 
+                                                       defaultValue : 200,
+                                                       ui : "slider",
+                                                       step : 2
+                                               },
+                                               {
+                                                       label : "Radius",
+                                                       option : "radius",
+                                                       type : "number", 
+                                                       range : [0,5], 
+                                                       defaultValue : 2,
+                                                       ui : "slider",
+                                                       step : 0.1
+                                               },
+                                               {
+                                                       label : "Threshold",
+                                                       option : "amount",
+                                                       type : "number", 
+                                                       range : [0,255], 
+                                                       defaultValue : 25,
+                                                       ui : "slider",
+                                                       step : 1
+                                               }
+                                       ]
+                               }
+
+                       ]
+               },
+               {
+                       title : "Effects",
+                       id : "effects",
+                       actions : [
+                               {
+                                       title : "Blur",
+                                       id : "blurfast",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Use the slider to set the blur amount."
+                                               },
+                                               {
+                                                       label : "Amount",
+                                                       option : "amount",
+                                                       type : "number", 
+                                                       range : [0,1], 
+                                                       defaultValue : 0.5,
+                                                       ui : "slider",
+                                                       step : 0.01
+                                               }
+                                       ]
+
+                               },
+                               {
+                                       title : "Edge detection",
+                                       id : "edges",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Performs edge detection on the image."
+                                               },
+                                               {
+                                                       label : "Greyscale",
+                                                       option : "mono",
+                                                       type : "boolean", 
+                                                       defaultValue : false,
+                                                       ui : "checkbox"
+                                               },
+                                               {
+                                                       label : "Invert",
+                                                       option : "invert",
+                                                       type : "boolean", 
+                                                       defaultValue : false,
+                                                       ui : "checkbox"
+                                               }
+                                       ]
+                               },
+                               {
+                                       title : "Emboss",
+                                       id : "emboss",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Adds an emboss-like effect to the image. Use the controls below to control the appearance of the effect. Choose \"Blend\" to blend the effect with the original image."
+                                               },
+                                               {
+                                                       label : "Strength",
+                                                       option : "strength",
+                                                       type : "number", 
+                                                       range : [0,10], 
+                                                       defaultValue : 1,
+                                                       ui : "slider",
+                                                       step : 0.1
+                                               },
+                                               {
+                                                       label : "Grey level",
+                                                       option : "greyLevel",
+                                                       type : "number", 
+                                                       range : [0,255], 
+                                                       defaultValue : 180,
+                                                       ui : "slider",
+                                                       step : 1
+                                               },
+                                               {
+                                                       label : "Direction",
+                                                       option : "direction",
+                                                       type : "string", 
+                                                       values : [
+                                                               {name:"Top left", value:"topleft"},
+                                                               {name:"Top", value:"top"},
+                                                               {name:"Top right", value:"topright"},
+                                                               {name:"Right", value:"right"},
+                                                               {name:"Bottom right", value:"bottomright"},
+                                                               {name:"Bottom", value:"bottom"},
+                                                               {name:"Bottom left", value:"bottomleft"},
+                                                               {name:"Left", value:"left"}
+                                                       ],
+                                                       defaultValue : "topleft",
+                                                       ui : "select"
+                                               },
+                                               {
+                                                       label : "Blend",
+                                                       option : "blend",
+                                                       type : "boolean", 
+                                                       defaultValue : false,
+                                                       ui : "checkbox"
+                                               }
+                                       ]
+
+                               },
+                               {
+                                       title : "Glow",
+                                       id : "glow",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Creates a glowing effect on the image."
+                                               },
+                                               {
+                                                       label : "Amount",
+                                                       option : "amount",
+                                                       type : "number", 
+                                                       range : [0,1], 
+                                                       defaultValue : 0.5,
+                                                       ui : "slider",
+                                                       step : 0.01
+                                               },
+                                               {
+                                                       label : "Radius",
+                                                       option : "radius",
+                                                       type : "number", 
+                                                       range : [0,1], 
+                                                       defaultValue : 0.5,
+                                                       ui : "slider",
+                                                       step : 0.01
+                                               }
+                                       ]
+                               },
+                               {
+                                       title : "Add noise",
+                                       id : "noise",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Add random noise to the image."
+                                               },
+                                               {
+                                                       label : "Amount",
+                                                       option : "amount",
+                                                       type : "number", 
+                                                       range : [0,1], 
+                                                       defaultValue : 0.5,
+                                                       ui : "slider",
+                                                       step : 0.01
+                                               },
+                                               {
+                                                       label : "Strength",
+                                                       option : "strength",
+                                                       type : "number", 
+                                                       range : [0,1], 
+                                                       defaultValue : 0.5,
+                                                       ui : "slider",
+                                                       step : 0.01
+                                               },
+                                               {
+                                                       label : "Greyscale",
+                                                       option : "mono",
+                                                       type : "boolean", 
+                                                       defaultValue : false,
+                                                       ui : "checkbox"
+                                               }
+                                       ]
+                               },
+                               {
+                                       title : "Remove noise",
+                                       id : "removenoise",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Attempts to remove noise from the image. Works best for getting rid of single pixels that stand out."
+                                               }
+                                       ]
+                               },
+                               {
+                                       title : "Pointillize",
+                                       id : "pointillize",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Paints the picture with circular points."
+                                               },
+                                               {
+                                                       label : "Point radius",
+                                                       option : "radius",
+                                                       type : "number", 
+                                                       range : [1,50], 
+                                                       defaultValue : 5,
+                                                       ui : "slider",
+                                                       step : 1
+                                               },
+                                               {
+                                                       label : "Density",
+                                                       option : "density",
+                                                       type : "number", 
+                                                       range : [0,5], 
+                                                       defaultValue : 1,
+                                                       ui : "slider",
+                                                       step : 0.01
+                                               },
+                                               {
+                                                       label : "Noise",
+                                                       option : "noise",
+                                                       type : "number", 
+                                                       range : [0,2], 
+                                                       defaultValue : 1,
+                                                       ui : "slider",
+                                                       step : 0.01
+                                               },
+                                               {
+                                                       label : "Transparent",
+                                                       option : "transparent",
+                                                       type : "boolean", 
+                                                       defaultValue : false,
+                                                       ui : "checkbox"
+                                               }
+                                       ]
+                               },
+                               {
+                                       title : "Posterize",
+                                       id : "posterize",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Reduces the number of colours to a specified number of levels."
+                                               },
+                                               {
+                                                       label : "Levels",
+                                                       option : "levels",
+                                                       type : "number", 
+                                                       range : [1,32], 
+                                                       defaultValue : 5,
+                                                       ui : "slider",
+                                                       step : 1
+                                               }
+                                       ]
+                               },
+                               {
+                                       title : "Solarize",
+                                       id : "solarize",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Applies a solarize effect to the image."
+                                               }
+                                       ]
+                               },
+                               {
+                                       title : "Mosaic",
+                                       id : "mosaic",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Creates a pixelated look."
+                                               },
+                                               {
+                                                       label : "Block size",
+                                                       option : "blockSize",
+                                                       type : "number", 
+                                                       range : [1,100], 
+                                                       defaultValue : 5,
+                                                       ui : "slider",
+                                                       step : 1
+                                               }
+                                       ]
+                               }
+
+
+                       ]
+               },
+               {
+                       title : "Done",
+                       id : "done",
+                       actions : [
+                               {
+                                       title : "Save to page",
+                                       id : "savepage",
+                                       content : function($ctr) {
+                                               var doc = PE.getDocument();
+                                               $j("<div></div>", doc)
+                                                       .addClass("action-output-text")
+                                                       .html("This will save the image to the page.")
+                                                       .appendTo($ctr);
+
+                                               var $buttonCtr = $j("<div></div>", doc).appendTo($ctr);
+                                               var $saveButton = $j("<button></button>", doc)
+                                                       .html("Save image")
+                                                       .appendTo($buttonCtr)
+                                                       .click(function() {
+                                                               PE.saveToPage();
+                                                       });
+
+                                       }
+                               },
+                               {
+                                       title : "Save to file",
+                                       id : "savefile",
+                                       content : function(ctr) {
+                                               var doc = PE.getDocument();
+                                               $j("<div></div>", doc)
+                                                       .addClass("action-output-text")
+                                                       .html("This will save the image to your local computer.")
+                                                       .appendTo(ctr);
+
+                                               var formats = PE.validSaveFormats();
+
+                                               var selectHtml = "<select>";
+                                               for (var i=0;i<formats.length;i++) {
+                                                       selectHtml += "<option value='" + formats[i].mime + "'>" + formats[i].name + "</option>";
+                                               }
+                                               selectHtml += "</select>";
+
+                                               var selectCtr = $j("<div></div>", doc)
+                                                       .addClass("ui-select-container");
+
+
+                                               var label = $j("<div></div>", doc)
+                                                       .addClass("ui-select-label")
+                                                       .html("Format:")
+                                                       .appendTo(selectCtr);
+
+                                               var formatSelect = $j(selectHtml, doc).appendTo(selectCtr);
+
+
+                                               selectCtr.appendTo(ctr);
+
+                                               var buttonCtr = $j("<div></div>", doc).appendTo(ctr);
+                                               var saveButton = $j("<button></button>", doc)
+                                                       .html("Save file")
+                                                       .appendTo(buttonCtr)
+
+                                               saveButton.click(function() {
+                                                       var selectElement = formatSelect.get(0);
+                                                       var formatMime = selectElement.options[selectElement.selectedIndex].value;
+                                                       var dataString = PE.getDataURI(formatMime);
+
+                                                       var dialog = $j("<div></div>", doc)
+                                                               .attr("id", "save-dialog")
+                                                               .attr("title", "Download file")
+                                                               .html(
+                                                                       "Right click the link below and select \"Save as...\" to save your file.<br/>"
+                                                                       + "<br/>"
+                                                                       + "<a href=\"" + dataString + "\">Image Link</a>"
+                                                               )
+                                                               .dialog();
+
+                                                       // the dialog is added outside the Pixastic container, so get it back in.
+                                                       var dialogParent = $j(dialog.get(0).parentNode);
+                                                       $j("#pixastic-editor", doc).append(dialogParent);
+                                               });
+                                       }
+                               },
+                               /*
+                               {
+                                       title : "Upload to Flickr",
+                                       id : "flickrupload",
+                                       content : function($ctr) {
+                                               var doc = PE.getDocument();
+
+                                               function flickrAuthed() {
+                                                       var $text = $j("<div />", doc)
+                                                               .addClass("action-output-text")
+                                                               .html("Authorized as: " + PE.Flickr.getAuthName());
+
+                                                       var $buttonCtr = $j("<div></div>", doc);
+                                                       var $uploadButton = $j("<button></button>", doc)
+                                                               .html("Upload image")
+                                                               .appendTo($buttonCtr)
+
+                                                       $uploadButton.click(function() {
+                                                               PE.Flickr.uploadImage(PE.getDataURI());
+                                                       });
+
+                                                       $ctr.append($text, $buttonCtr);
+                                               }
+
+                                               var $authCtr = $j("<div />", doc).appendTo($ctr);
+
+                                               $j("<div />", doc)
+                                                       .addClass("action-output-text")
+                                                       .html("If you have a Flickr account you can now upload your image to Flickr. You will need to give access to your account first. Click the button below to open an authorization window.")
+                                                       .appendTo($authCtr);
+
+                                               var $buttonCtr = $j("<div></div>", doc).appendTo($authCtr);
+                                               var $authButton = $j("<button></button>", doc)
+                                                       .html("Authenticate")
+                                                       .appendTo($buttonCtr)
+
+                                               var checkButtonAdded = false;
+                                               $authButton.click(function() {
+                                                       PE.Flickr.auth();
+                                                       if (!checkButtonAdded) {
+                                                               checkButtonAdded = true;
+
+                                                               var $text = $j("<div />", doc)
+                                                                       .addClass("action-output-text")
+                                                                       .html("Now click the button below when you have authorized access to your Flickr account.");
+       
+                                                               var $buttonCtr = $j("<div></div>", doc);
+       
+                                                               $authCtr.append($text, $buttonCtr);
+       
+                                                               var $checkButton = $j("<button></button>", doc)
+                                                                       .html("I have authenticated!")
+                                                                       .appendTo($buttonCtr);
+       
+                                                               $checkButton.click(function() {
+                                                                       PE.Flickr.checkAuth(function(res) {
+                                                                               if (res.stat == "ok") {
+                                                                                       $authCtr.remove();
+                                                                                       flickrAuthed();
+                                                                               }
+                                                                       });
+                                                               });
+                                                       }
+
+                                               });
+                                       }
+                               },
+                               */
+                               {
+                                       title : "Quit",
+                                       id : "quit", 
+                                       content : function(ctr) {
+                                               var doc = PE.getDocument();
+
+                                               $j("<div>Are you sure you want to quit?</div>", doc)
+                                                       .addClass("action-output-text")
+                                                       .appendTo(ctr);
+                                               var $buttonCtr = $j("<div></div>", doc).appendTo(ctr);
+
+                                               var $quitButton = PE.UI.makeButton("Yes, quit now!")
+                                                       .appendTo($buttonCtr)
+
+                                               $quitButton.click(function() {
+                                                       PE.unload();
+                                               });
+
+                                               var $saveButton = PE.UI.makeButton("Save to page and quit")
+                                                       .appendTo($buttonCtr)
+                                                       .click(function() {
+                                                               PE.saveToPage();
+                                                               PE.unload();
+                                                       });
+                                       }
+                               }
+                       ]
+               }
+       ]
+};
+
+
+})(PixasticEditor.jQuery);
\ No newline at end of file
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/actions/blend.js b/js2/mwEmbed/libClipEdit/pixastic-lib/actions/blend.js
new file mode 100644 (file)
index 0000000..db057d1
--- /dev/null
@@ -0,0 +1,462 @@
+/*
+ * Pixastic Lib - Blend - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * MIT License [http://www.opensource.org/licenses/mit-license.php]
+ */
+
+Pixastic.Actions.blend = {
+
+       process : function(params) {
+               var amount = parseFloat(params.options.amount);
+               var mode = (params.options.mode || "normal").toLowerCase();
+               var image = params.options.image;
+
+               amount = Math.max(0,Math.min(1,amount));
+
+               if (!image) return false;
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var rect = params.options.rect;
+                       var data = Pixastic.prepareData(params);
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       params.useData = false;
+
+                       var otherCanvas = document.createElement("canvas");
+                       otherCanvas.width = params.canvas.width;
+                       otherCanvas.height = params.canvas.height;
+                       var otherCtx = otherCanvas.getContext("2d");
+                       otherCtx.drawImage(image,0,0);
+
+                       var params2 = {canvas:otherCanvas,options:params.options};
+                       var data2 = Pixastic.prepareData(params2);
+                       var dataDesc2 = params2.canvasData;
+
+                       var p = w*h;
+                       var pix = p*4;
+                       var pix1, pix2;
+                       var r1, g1, b1;
+                       var r2, g2, b2;
+                       var r3, g3, b3;
+                       var r4, g4, b4;
+
+                       switch (mode) {
+                               case "normal" : 
+                                       //while (p--) {
+                                       //      data2[pix-=4] = data2[pix];
+                                       //      data2[pix1=pix+1] = data2[pix1];
+                                       //      data2[pix2=pix+2] = data2[pix2];
+                                       //}
+                                       break;
+
+                               case "multiply" : 
+                                       while (p--) {
+                                               data2[pix-=4] = data[pix] * data2[pix] / 255;
+                                               data2[pix1=pix+1] = data[pix1] * data2[pix1] / 255;
+                                               data2[pix2=pix+2] = data[pix2] * data2[pix2] / 255;
+                                       }
+                                       break;
+
+                               case "lighten" : 
+                                       while (p--) {
+                                               if ((r1 = data[pix-=4]) > data2[pix])
+                                                       data2[pix] = r1;
+                                               if ((g1 = data[pix1=pix+1]) > data2[pix1])
+                                                       data2[pix1] = g1;
+                                               if ((b1 = data[pix2=pix+2]) > data2[pix2])
+                                                       data2[pix2] = b1;
+                                       }
+                                       break;
+
+                               case "darken" : 
+                                       while (p--) {
+                                               if ((r1 = data[pix-=4]) < data2[pix])
+                                                       data2[pix] = r1;
+                                               if ((g1 = data[pix1=pix+1]) < data2[pix1])
+                                                       data2[pix1] = g1;
+                                               if ((b1 = data[pix2=pix+2]) < data2[pix2])
+                                                       data2[pix2] = b1;
+
+                                       }
+                                       break;
+
+                               case "darkercolor" : 
+                                       while (p--) {
+                                               if (((r1 = data[pix-=4])*0.3+(g1 = data[pix1=pix+1])*0.59+(b1 = data[pix2=pix+2])*0.11) <= (data2[pix]*0.3+data2[pix1]*0.59+data2[pix2]*0.11)) {
+                                                       data2[pix] = r1;
+                                                       data2[pix1] = g1;
+                                                       data2[pix2] = b1;
+                                               }
+                                       }
+                                       break;
+
+                               case "lightercolor" : 
+                                       while (p--) {
+                                               if (((r1 = data[pix-=4])*0.3+(g1 = data[pix1=pix+1])*0.59+(b1 = data[pix2=pix+2])*0.11) > (data2[pix]*0.3+data2[pix1]*0.59+data2[pix2]*0.11)) {
+                                                       data2[pix] = r1;
+                                                       data2[pix1] = g1;
+                                                       data2[pix2] = b1;
+                                               }
+                                       }
+                                       break;
+
+                               case "lineardodge" : 
+                                       while (p--) {
+                                               if ((r3 = data[pix-=4] + data2[pix]) > 255)
+                                                       data2[pix] = 255;
+                                               else
+                                                       data2[pix] = r3;
+                                               if ((g3 = data[pix1=pix+1] + data2[pix1]) > 255)
+                                                       data2[pix1] = 255;
+                                               else
+                                                       data2[pix1] = g3;
+                                               if ((b3 = data[pix2=pix+2] + data2[pix2]) > 255)
+                                                       data2[pix2] = 255;
+                                               else
+                                                       data2[pix2] = b3;
+                                       }
+                                       break;
+
+                               case "linearburn" : 
+                                       while (p--) {
+                                               if ((r3 = data[pix-=4] + data2[pix]) < 255)
+                                                       data2[pix] = 0;
+                                               else
+                                                       data2[pix] = (r3 - 255);
+                                               if ((g3 = data[pix1=pix+1] + data2[pix1]) < 255)
+                                                       data2[pix1] = 0;
+                                               else
+                                                       data2[pix1] = (g3 - 255);
+                                               if ((b3 = data[pix2=pix+2] + data2[pix2]) < 255)
+                                                       data2[pix2] = 0;
+                                               else
+                                                       data2[pix2] = (b3 - 255);
+                                       }
+                                       break;
+
+                               case "difference" : 
+                                       while (p--) {
+                                               if ((r3 = data[pix-=4] - data2[pix]) < 0)
+                                                       data2[pix] = -r3;
+                                               else
+                                                       data2[pix] = r3;
+                                               if ((g3 = data[pix1=pix+1] - data2[pix1]) < 0)
+                                                       data2[pix1] = -g3;
+                                               else
+                                                       data2[pix1] = g3;
+                                               if ((b3 = data[pix2=pix+2] - data2[pix2]) < 0)
+                                                       data2[pix2] = -b3;
+                                               else
+                                                       data2[pix2] = b3;
+                                       }
+                                       break;
+
+                               case "screen" : 
+                                       while (p--) {
+                                               data2[pix-=4] = (255 - ( ((255-data2[pix])*(255-data[pix])) >> 8));
+                                               data2[pix1=pix+1] = (255 - ( ((255-data2[pix1])*(255-data[pix1])) >> 8));
+                                               data2[pix2=pix+2] = (255 - ( ((255-data2[pix2])*(255-data[pix2])) >> 8));
+                                       }
+                                       break;
+
+                               case "exclusion" : 
+                                       var div_2_255 = 2 / 255;
+                                       while (p--) {
+                                               data2[pix-=4] = (r1 = data[pix]) - (r1 * div_2_255 - 1) * data2[pix];
+                                               data2[pix1=pix+1] = (g1 = data[pix1]) - (g1 * div_2_255 - 1) * data2[pix1];
+                                               data2[pix2=pix+2] = (b1 = data[pix2]) - (b1 * div_2_255 - 1) * data2[pix2];
+                                       }
+                                       break;
+
+                               case "overlay" : 
+                                       var div_2_255 = 2 / 255;
+                                       while (p--) {
+                                               if ((r1 = data[pix-=4]) < 128)
+                                                       data2[pix] = data2[pix]*r1*div_2_255;
+                                               else
+                                                       data2[pix] = 255 - (255-data2[pix])*(255-r1)*div_2_255;
+
+                                               if ((g1 = data[pix1=pix+1]) < 128)
+                                                       data2[pix1] = data2[pix1]*g1*div_2_255;
+                                               else
+                                                       data2[pix1] = 255 - (255-data2[pix1])*(255-g1)*div_2_255;
+
+                                               if ((b1 = data[pix2=pix+2]) < 128)
+                                                       data2[pix2] = data2[pix2]*b1*div_2_255;
+                                               else
+                                                       data2[pix2] = 255 - (255-data2[pix2])*(255-b1)*div_2_255;
+
+                                       }
+                                       break;
+
+                               case "softlight" : 
+                                       var div_2_255 = 2 / 255;
+                                       while (p--) {
+                                               if ((r1 = data[pix-=4]) < 128)
+                                                       data2[pix] = ((data2[pix]>>1) + 64) * r1 * div_2_255;
+                                               else
+                                                       data2[pix] = 255 - (191 - (data2[pix]>>1)) * (255-r1) * div_2_255;
+
+                                               if ((g1 = data[pix1=pix+1]) < 128)
+                                                       data2[pix1] = ((data2[pix1]>>1)+64) * g1 * div_2_255;
+                                               else
+                                                       data2[pix1] = 255 - (191 - (data2[pix1]>>1)) * (255-g1) * div_2_255;
+
+                                               if ((b1 = data[pix2=pix+2]) < 128)
+                                                       data2[pix2] = ((data2[pix2]>>1)+64) * b1 * div_2_255;
+                                               else
+                                                       data2[pix2] = 255 - (191 - (data2[pix2]>>1)) * (255-b1) * div_2_255;
+
+                                       }
+                                       break;
+
+
+                               case "hardlight" : 
+                                       var div_2_255 = 2 / 255;
+                                       while (p--) {
+                                               if ((r2 = data2[pix-=4]) < 128)
+                                                       data2[pix] = data[pix] * r2 * div_2_255;
+                                               else
+                                                       data2[pix] = 255 - (255-data[pix]) * (255-r2) * div_2_255;
+
+                                               if ((g2 = data2[pix1=pix+1]) < 128)
+                                                       data2[pix1] = data[pix1] * g2 * div_2_255;
+                                               else
+                                                       data2[pix1] = 255 - (255-data[pix1]) * (255-g2) * div_2_255;
+
+                                               if ((b2 = data2[pix2=pix+2]) < 128)
+                                                       data2[pix2] = data[pix2] * b2 * div_2_255;
+                                               else
+                                                       data2[pix2] = 255 - (255-data[pix2]) * (255-b2) * div_2_255;
+
+                                       }
+                                       break;
+
+                               case "colordodge" : 
+                                       while (p--) {
+                                               if ((r3 = (data[pix-=4]<<8)/(255-(r2 = data2[pix]))) > 255 || r2 == 255)
+                                                       data2[pix] = 255;
+                                               else
+                                                       data2[pix] = r3;
+
+                                               if ((g3 = (data[pix1=pix+1]<<8)/(255-(g2 = data2[pix1]))) > 255 || g2 == 255)
+                                                       data2[pix1] = 255;
+                                               else
+                                                       data2[pix1] = g3;
+
+                                               if ((b3 = (data[pix2=pix+2]<<8)/(255-(b2 = data2[pix2]))) > 255 || b2 == 255)
+                                                       data2[pix2] = 255;
+                                               else
+                                                       data2[pix2] = b3;
+                                       }
+
+                                       break;
+
+                               case "colorburn" : 
+                                       while (p--) {
+                                               if ((r3 = 255-((255-data[pix-=4])<<8)/data2[pix]) < 0 || data2[pix] == 0)
+                                                       data2[pix] = 0;
+                                               else
+                                                       data2[pix] = r3;
+
+                                               if ((g3 = 255-((255-data[pix1=pix+1])<<8)/data2[pix1]) < 0 || data2[pix1] == 0)
+                                                       data2[pix1] = 0;
+                                               else
+                                                       data2[pix1] = g3;
+
+                                               if ((b3 = 255-((255-data[pix2=pix+2])<<8)/data2[pix2]) < 0 || data2[pix2] == 0)
+                                                       data2[pix2] = 0;
+                                               else
+                                                       data2[pix2] = b3;
+                                       }
+                                       break;
+
+                               case "linearlight" : 
+                                       while (p--) {
+                                               if ( ((r3 = 2*(r2=data2[pix-=4])+data[pix]-256) < 0) || (r2 < 128 && r3 < 0)) {
+                                                       data2[pix] = 0
+                                               } else {
+                                                       if (r3 > 255)
+                                                               data2[pix] = 255;
+                                                       else
+                                                               data2[pix] = r3;
+                                               }
+                                               if ( ((g3 = 2*(g2=data2[pix1=pix+1])+data[pix1]-256) < 0) || (g2 < 128 && g3 < 0)) {
+                                                       data2[pix1] = 0
+                                               } else {
+                                                       if (g3 > 255)
+                                                               data2[pix1] = 255;
+                                                       else
+                                                               data2[pix1] = g3;
+                                               }
+                                               if ( ((b3 = 2*(b2=data2[pix2=pix+2])+data[pix2]-256) < 0) || (b2 < 128 && b3 < 0)) {
+                                                       data2[pix2] = 0
+                                               } else {
+                                                       if (b3 > 255)
+                                                               data2[pix2] = 255;
+                                                       else
+                                                               data2[pix2] = b3;
+                                               }
+                                       }
+
+                                       break;
+
+                               case "vividlight" : 
+                                       while (p--) {
+                                               if ((r2=data2[pix-=4]) < 128) {
+                                                       if (r2) {
+                                                               if ((r3 = 255 - ((255-data[pix])<<8) / (2*r2)) < 0) 
+                                                                       data2[pix] = 0;
+                                                               else
+                                                                       data2[pix] = r3
+                                                       } else {
+                                                               data2[pix] = 0;
+                                                       }
+                                               } else if ((r3 = (r4=2*r2-256)) < 255) {
+                                                       if ((r3 = (data[pix]<<8)/(255-r4)) > 255) 
+                                                               data2[pix] = 255;
+                                                       else
+                                                               data2[pix] = r3;
+                                               } else {
+                                                       if (r3 < 0) 
+                                                               data2[pix] = 0;
+                                                       else
+                                                               data2[pix] = r3
+                                               }
+
+                                               if ((g2=data2[pix1=pix+1]) < 128) {
+                                                       if (g2) {
+                                                               if ((g3 = 255 - ((255-data[pix1])<<8) / (2*g2)) < 0) 
+                                                                       data2[pix1] = 0;
+                                                               else
+                                                                       data2[pix1] = g3;
+                                                       } else {
+                                                               data2[pix1] = 0;
+                                                       }
+                                               } else if ((g3 = (g4=2*g2-256)) < 255) {
+                                                       if ((g3 = (data[pix1]<<8)/(255-g4)) > 255)
+                                                               data2[pix1] = 255;
+                                                       else
+                                                               data2[pix1] = g3;
+                                               } else {
+                                                       if (g3 < 0) 
+                                                               data2[pix1] = 0;
+                                                       else
+                                                               data2[pix1] = g3;
+                                               }
+
+                                               if ((b2=data2[pix2=pix+2]) < 128) {
+                                                       if (b2) {
+                                                               if ((b3 = 255 - ((255-data[pix2])<<8) / (2*b2)) < 0) 
+                                                                       data2[pix2] = 0;
+                                                               else
+                                                                       data2[pix2] = b3;
+                                                       } else {
+                                                               data2[pix2] = 0;
+                                                       }
+                                               } else if ((b3 = (b4=2*b2-256)) < 255) {
+                                                       if ((b3 = (data[pix2]<<8)/(255-b4)) > 255) 
+                                                               data2[pix2] = 255;
+                                                       else
+                                                               data2[pix2] = b3;
+                                               } else {
+                                                       if (b3 < 0) 
+                                                               data2[pix2] = 0;
+                                                       else
+                                                               data2[pix2] = b3;
+                                               }
+                                       }
+                                       break;
+
+                               case "pinlight" : 
+                                       while (p--) {
+                                               if ((r2=data2[pix-=4]) < 128)
+                                                       if ((r1=data[pix]) < (r4=2*r2))
+                                                               data2[pix] = r1;
+                                                       else
+                                                               data2[pix] = r4;
+                                               else
+                                                       if ((r1=data[pix]) > (r4=2*r2-256))
+                                                               data2[pix] = r1;
+                                                       else
+                                                               data2[pix] = r4;
+
+                                               if ((g2=data2[pix1=pix+1]) < 128)
+                                                       if ((g1=data[pix1]) < (g4=2*g2))
+                                                               data2[pix1] = g1;
+                                                       else
+                                                               data2[pix1] = g4;
+                                               else
+                                                       if ((g1=data[pix1]) > (g4=2*g2-256))
+                                                               data2[pix1] = g1;
+                                                       else
+                                                               data2[pix1] = g4;
+
+                                               if ((r2=data2[pix2=pix+2]) < 128)
+                                                       if ((r1=data[pix2]) < (r4=2*r2))
+                                                               data2[pix2] = r1;
+                                                       else
+                                                               data2[pix2] = r4;
+                                               else
+                                                       if ((r1=data[pix2]) > (r4=2*r2-256))
+                                                               data2[pix2] = r1;
+                                                       else
+                                                               data2[pix2] = r4;
+                                       }
+                                       break;
+
+                               case "hardmix" : 
+                                       while (p--) {
+                                               if ((r2 = data2[pix-=4]) < 128)
+                                                       if (255 - ((255-data[pix])<<8)/(2*r2) < 128 || r2 == 0)
+                                                               data2[pix] = 0;
+                                                       else
+                                                               data2[pix] = 255;
+                                               else if ((r4=2*r2-256) < 255 && (data[pix]<<8)/(255-r4) < 128)
+                                                       data2[pix] = 0;
+                                               else
+                                                       data2[pix] = 255;
+
+                                               if ((g2 = data2[pix1=pix+1]) < 128)
+                                                       if (255 - ((255-data[pix1])<<8)/(2*g2) < 128 || g2 == 0)
+                                                               data2[pix1] = 0;
+                                                       else
+                                                               data2[pix1] = 255;
+                                               else if ((g4=2*g2-256) < 255 && (data[pix1]<<8)/(255-g4) < 128)
+                                                       data2[pix1] = 0;
+                                               else
+                                                       data2[pix1] = 255;
+
+                                               if ((b2 = data2[pix2=pix+2]) < 128)
+                                                       if (255 - ((255-data[pix2])<<8)/(2*b2) < 128 || b2 == 0)
+                                                               data2[pix2] = 0;
+                                                       else
+                                                               data2[pix2] = 255;
+                                               else if ((b4=2*b2-256) < 255 && (data[pix2]<<8)/(255-b4) < 128)
+                                                       data2[pix2] = 0;
+                                               else
+                                                       data2[pix2] = 255;
+                                       }
+                                       break;
+                       }
+
+                       otherCtx.putImageData(dataDesc2,0,0);
+                       var ctx = params.canvas.getContext("2d");
+                       ctx.save();
+                       ctx.globalAlpha = amount;
+                       ctx.drawImage(
+                               otherCanvas,
+                               0,0,rect.width,rect.height,
+                               rect.left,rect.top,rect.width,rect.height
+                       );
+                       ctx.globalAlpha = 1;
+                       ctx.restore();
+
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/actions/blur.js b/js2/mwEmbed/libClipEdit/pixastic-lib/actions/blur.js
new file mode 100644 (file)
index 0000000..eb70774
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Pixastic Lib - Blur filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * MIT License [http://www.opensource.org/licenses/mit-license.php]
+ */
+
+Pixastic.Actions.blur = {
+       process : function(params) {
+
+               if (typeof params.options.fixMargin == "undefined")
+                       params.options.fixMargin = true;
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var dataCopy = Pixastic.prepareData(params, true)
+
+                       /*
+                       var kernel = [
+                               [0.5,   1,      0.5],
+                               [1,     2,      1],
+                               [0.5,   1,      0.5]
+                       ];
+                       */
+
+                       var kernel = [
+                               [0,     1,      0],
+                               [1,     2,      1],
+                               [0,     1,      0]
+                       ];
+
+                       var weight = 0;
+                       for (var i=0;i<3;i++) {
+                               for (var j=0;j<3;j++) {
+                                       weight += kernel[i][j];
+                               }
+                       }
+
+                       weight = 1 / (weight*2);
+
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+
+                               var prevY = (y == 1) ? 0 : y-2;
+                               var nextY = (y == h) ? y - 1 : y;
+
+                               var offsetYPrev = prevY*w*4;
+                               var offsetYNext = nextY*w*4;
+
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x*4-4);
+
+                                       var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
+                                       var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
+       
+                                       data[offset] = (
+                                               /*
+                                               dataCopy[offsetPrev - 4]
+                                               + dataCopy[offsetPrev+4] 
+                                               + dataCopy[offsetNext - 4]
+                                               + dataCopy[offsetNext+4]
+                                               + 
+                                               */
+                                               (dataCopy[offsetPrev]
+                                               + dataCopy[offset-4]
+                                               + dataCopy[offset+4]
+                                               + dataCopy[offsetNext])         * 2
+                                               + dataCopy[offset]              * 4
+                                               ) * weight;
+
+                                       data[offset+1] = (
+                                               /*
+                                               dataCopy[offsetPrev - 3]
+                                               + dataCopy[offsetPrev+5] 
+                                               + dataCopy[offsetNext - 3] 
+                                               + dataCopy[offsetNext+5]
+                                               + 
+                                               */
+                                               (dataCopy[offsetPrev+1]
+                                               + dataCopy[offset-3]
+                                               + dataCopy[offset+5]
+                                               + dataCopy[offsetNext+1])       * 2
+                                               + dataCopy[offset+1]            * 4
+                                               ) * weight;
+
+                                       data[offset+2] = (
+                                               /*
+                                               dataCopy[offsetPrev - 2] 
+                                               + dataCopy[offsetPrev+6] 
+                                               + dataCopy[offsetNext - 2] 
+                                               + dataCopy[offsetNext+6]
+                                               + 
+                                               */
+                                               (dataCopy[offsetPrev+2]
+                                               + dataCopy[offset-2]
+                                               + dataCopy[offset+6]
+                                               + dataCopy[offsetNext+2])       * 2
+                                               + dataCopy[offset+2]            * 4
+                                               ) * weight;
+
+                               } while (--x);
+                       } while (--y);
+
+                       return true;
+
+               } else if (Pixastic.Client.isIE()) {
+                       params.image.style.filter += " progid:DXImageTransform.Microsoft.Blur(pixelradius=1.5)";
+
+                       if (params.options.fixMargin) {
+                               params.image.style.marginLeft = (parseInt(params.image.style.marginLeft,10)||0) - 2 + "px";
+                               params.image.style.marginTop = (parseInt(params.image.style.marginTop,10)||0) - 2 + "px";
+                       }
+
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
+       }
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/actions/blurfast.js b/js2/mwEmbed/libClipEdit/pixastic-lib/actions/blurfast.js
new file mode 100644 (file)
index 0000000..caf6b75
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Pixastic Lib - Blur Fast - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * MIT License [http://www.opensource.org/licenses/mit-license.php]
+ */
+
+Pixastic.Actions.blurfast = {
+       process : function(params) {
+
+               var amount = parseFloat(params.options.amount)||0;
+
+               amount = Math.max(0,Math.min(5,amount));
+
+               if (Pixastic.Client.hasCanvas()) {
+                       var rect = params.options.rect;
+
+                       var ctx = params.canvas.getContext("2d");
+                       ctx.save();
+                       ctx.beginPath();
+                       ctx.moveTo(rect.left,rect.top);
+                       ctx.lineTo(rect.left+rect.width,rect.top);
+                       ctx.lineTo(rect.left+rect.width,rect.top+rect.height);
+                       ctx.lineTo(rect.left,rect.top+rect.height);
+                       ctx.lineTo(rect.left,rect.top);
+                       ctx.closePath();
+                       ctx.clip();
+
+                       var scale = 2;
+                       var smallWidth = Math.round(params.width / scale);
+                       var smallHeight = Math.round(params.height / scale);
+
+                       var copy = document.createElement("canvas");
+                       copy.width = smallWidth;
+                       copy.height = smallHeight;
+
+                       var clear = true;
+                       var steps = Math.round(amount * 20);
+
+                       var copyCtx = copy.getContext("2d");
+                       for (var i=0;i<steps;i++) {
+                               var scaledWidth = Math.max(1,Math.round(smallWidth - i));
+                               var scaledHeight = Math.max(1,Math.round(smallHeight - i));
+       
+                               copyCtx.clearRect(0,0,smallWidth,smallHeight);
+       
+                               copyCtx.drawImage(
+                                       params.canvas,
+                                       0,0,params.width,params.height,
+                                       0,0,scaledWidth,scaledHeight
+                               );
+       
+                               if (clear)
+                                       ctx.clearRect(rect.left,rect.top,rect.width,rect.height);
+       
+                               ctx.drawImage(
+                                       copy,
+                                       0,0,scaledWidth,scaledHeight,
+                                       0,0,params.width,params.height
+                               );
+                       }
+
+                       ctx.restore();
+
+                       params.useData = false;
+                       return true;
+               } else if (Pixastic.Client.isIE()) {
+                       var radius = 10 * amount;
+                       params.image.style.filter += " progid:DXImageTransform.Microsoft.Blur(pixelradius=" + radius + ")";
+
+                       if (params.options.fixMargin || 1) {
+                               params.image.style.marginLeft = (parseInt(params.image.style.marginLeft,10)||0) - Math.round(radius) + "px";
+                               params.image.style.marginTop = (parseInt(params.image.style.marginTop,10)||0) - Math.round(radius) + "px";
+                       }
+
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvas() || Pixastic.Client.isIE());
+       }
+}
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/actions/brightness.js b/js2/mwEmbed/libClipEdit/pixastic-lib/actions/brightness.js
new file mode 100644 (file)
index 0000000..7efc3b8
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Pixastic Lib - Brightness/Contrast filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * MIT License [http://www.opensource.org/licenses/mit-license.php]
+ */
+
+Pixastic.Actions.brightness = {
+
+       process : function(params) {
+
+               var brightness = parseInt(params.options.brightness,10) || 0;
+               var contrast = parseFloat(params.options.contrast)||0;
+               var legacy = !!(params.options.legacy);
+
+               if (legacy) {
+                       brightness = Math.min(150,Math.max(-150,brightness));
+               } else {
+                       var brightMul = 1 + Math.min(150,Math.max(-150,brightness)) / 150;
+               }
+               contrast = Math.max(0,contrast+1);
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x-1)*4;
+
+                                       if (legacy) {
+                                               var r = data[offset] + brightness;
+                                               var g = data[offset+1] + brightness;
+                                               var b = data[offset+2] + brightness;
+                                       } else {
+                                               var r = data[offset] * brightMul;
+                                               var g = data[offset+1] * brightMul;
+                                               var b = data[offset+2] * brightMul;
+                                       }
+
+                                       if (contrast != 1) {
+                                               r = (r - 128) * contrast + 128;
+                                               g = (g - 128) * contrast + 128;
+                                               b = (b - 128) * contrast + 128;
+                                       }
+
+                                       if (r < 0 ) r = 0;
+                                       if (g < 0 ) g = 0;
+                                       if (b < 0 ) b = 0;
+                                       if (r > 255 ) r = 255;
+                                       if (g > 255 ) g = 255;
+                                       if (b > 255 ) b = 255;
+
+                                       data[offset] = r;
+                                       data[offset+1] = g;
+                                       data[offset+2] = b;
+
+                               } while (--x);
+                       } while (--y);
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}
+
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/actions/coloradjust.js b/js2/mwEmbed/libClipEdit/pixastic-lib/actions/coloradjust.js
new file mode 100644 (file)
index 0000000..dfcb271
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Pixastic Lib - Color adjust filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * MIT License [http://www.opensource.org/licenses/mit-license.php]
+ */
+
+Pixastic.Actions.coloradjust = {
+
+       process : function(params) {
+               var red = parseFloat(params.options.red) || 0;
+               var green = parseFloat(params.options.green) || 0;
+               var blue = parseFloat(params.options.blue) || 0;
+
+               red = Math.round(red*255);
+               green = Math.round(green*255);
+               blue = Math.round(blue*255);
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x-1)*4;
+
+                                       var r = data[offset] + red;
+                                       var g = data[offset+1] + green;
+                                       var b = data[offset+2] + blue;
+
+                                       if (r < 0 ) r = 0;
+                                       if (g < 0 ) g = 0;
+                                       if (b < 0 ) b = 0;
+                                       if (r > 255 ) r = 255;
+                                       if (g > 255 ) g = 255;
+                                       if (b > 255 ) b = 255;
+
+                                       data[offset] = r;
+                                       data[offset+1] = g;
+                                       data[offset+2] = b;
+
+                               } while (--x);
+                       } while (--y);
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvasImageData());
+       }
+}
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/actions/crop.js b/js2/mwEmbed/libClipEdit/pixastic-lib/actions/crop.js
new file mode 100644 (file)
index 0000000..b145be5
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Pixastic Lib - Crop - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * MIT License [http://www.opensource.org/licenses/mit-license.php]
+ */
+
+Pixastic.Actions.crop = {
+       process : function(params) {
+               if (Pixastic.Client.hasCanvas()) {
+                       var rect = params.options.rect;
+
+                       var copy = document.createElement("canvas");
+                       copy.width = params.width;
+                       copy.height = params.height;
+                       copy.getContext("2d").drawImage(params.canvas,0,0);
+
+                       params.canvas.width = rect.width;
+                       params.canvas.height = rect.height;
+                       params.canvas.getContext("2d").clearRect(0,0,rect.width,rect.height);
+
+                       params.canvas.getContext("2d").drawImage(copy,
+                               rect.left,rect.top,rect.width,rect.height,
+                               0,0,rect.width,rect.height
+                       );
+
+                       params.useData = false;
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvas();
+       }
+}
+
+
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/actions/desaturate.js b/js2/mwEmbed/libClipEdit/pixastic-lib/actions/desaturate.js
new file mode 100644 (file)
index 0000000..9466f56
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Pixastic Lib - Desaturation filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * MIT License [http://www.opensource.org/licenses/mit-license.php]
+ */
+
+Pixastic.Actions.desaturate = {
+
+       process : function(params) {
+               var useAverage = !!params.options.average;
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x-1)*4;
+                                       var brightness = useAverage ?
+                                               (data[offset]+data[offset+1]+data[offset+2])/3
+                                               : (data[offset]*0.3 + data[offset+1]*0.59 + data[offset+2]*0.11);
+                                       data[offset] = data[offset+1] = data[offset+2] = brightness;
+                               } while (--x);
+                       } while (--y);
+                       return true;
+               } else if (Pixastic.Client.isIE()) {
+                       params.image.style.filter += " gray";
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
+       }
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/actions/edges.js b/js2/mwEmbed/libClipEdit/pixastic-lib/actions/edges.js
new file mode 100644 (file)
index 0000000..8e0d860
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Pixastic Lib - Edge detection filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * MIT License [http://www.opensource.org/licenses/mit-license.php]
+ */
+
+Pixastic.Actions.edges = {
+       process : function(params) {
+
+               var mono = !!(params.options.mono);
+
+               var strength = 1.0;
+
+               //if (typeof params.options.strength != "undefined")
+               //      strength = parseFloat(params.options.strength)||0;
+
+               var invert = !!(params.options.invert);
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var dataCopy = Pixastic.prepareData(params, true)
+
+                       var c = -strength/8;
+                       var kernel = [
+                               [c,     c,      c],
+                               [c,     1,      c],
+                               [c,     c,      c]
+                       ];
+
+                       weight = 1/c;
+
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+
+                               var nextY = (y == h) ? y - 1 : y;
+                               var prevY = (y == 1) ? 0 : y-2;
+
+                               var offsetYPrev = prevY*w*4;
+                               var offsetYNext = nextY*w*4;
+
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x*4-4);
+
+                                       var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
+                                       var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
+       
+                                       var r = ((dataCopy[offsetPrev-4]
+                                               + dataCopy[offsetPrev]
+                                               + dataCopy[offsetPrev+4]
+                                               + dataCopy[offset-4]
+                                               + dataCopy[offset+4]
+                                               + dataCopy[offsetNext-4]
+                                               + dataCopy[offsetNext]
+                                               + dataCopy[offsetNext+4]) * c
+                                               + dataCopy[offset]
+                                               ) 
+                                               * weight;
+       
+                                       var g = ((dataCopy[offsetPrev-3]
+                                               + dataCopy[offsetPrev+1]
+                                               + dataCopy[offsetPrev+5]
+                                               + dataCopy[offset-3]
+                                               + dataCopy[offset+5]
+                                               + dataCopy[offsetNext-3]
+                                               + dataCopy[offsetNext+1]
+                                               + dataCopy[offsetNext+5]) * c
+                                               + dataCopy[offset+1])
+                                               * weight;
+       
+                                       var b = ((dataCopy[offsetPrev-2]
+                                               + dataCopy[offsetPrev+2]
+                                               + dataCopy[offsetPrev+6]
+                                               + dataCopy[offset-2]
+                                               + dataCopy[offset+6]
+                                               + dataCopy[offsetNext-2]
+                                               + dataCopy[offsetNext+2]
+                                               + dataCopy[offsetNext+6]) * c
+                                               + dataCopy[offset+2])
+                                               * weight;
+
+                                       if (mono) {
+                                               var brightness = (r*0.3 + g*0.59 + b*0.11)||0;
+                                               if (invert) brightness = 255 - brightness;
+                                               if (brightness < 0 ) brightness = 0;
+                                               if (brightness > 255 ) brightness = 255;
+                                               r = g = b = brightness;
+                                       } else {
+                                               if (invert) {
+                                                       r = 255 - r;
+                                                       g = 255 - g;
+                                                       b = 255 - b;
+                                               }
+                                               if (r < 0 ) r = 0;
+                                               if (g < 0 ) g = 0;
+                                               if (b < 0 ) b = 0;
+                                               if (r > 255 ) r = 255;
+                                               if (g > 255 ) g = 255;
+                                               if (b > 255 ) b = 255;
+                                       }
+
+                                       data[offset] = r;
+                                       data[offset+1] = g;
+                                       data[offset+2] = b;
+
+                               } while (--x);
+                       } while (--y);
+
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/actions/edges2.js b/js2/mwEmbed/libClipEdit/pixastic-lib/actions/edges2.js
new file mode 100644 (file)
index 0000000..bf15041
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Pixastic Lib - Edge detection 2 - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * MIT License [http://www.opensource.org/licenses/mit-license.php]
+ * 
+ * Contribution by Oliver Hunt (http://nerget.com/, http://nerget.com/canvas/edgeDetection.js). Thanks Oliver!
+ *
+ */
+
+Pixastic.Actions.edges2 = {
+       process : function(params) {
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var dataCopy = Pixastic.prepareData(params, true)
+
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       var w4 = w * 4;
+                       var pixel = w4 + 4; // Start at (1,1)
+                       var hm1 = h - 1;
+                       var wm1 = w - 1;
+                       for (var y = 1; y < hm1; ++y) {
+                               // Prepare initial cached values for current row
+                               var centerRow = pixel - 4;
+                               var priorRow = centerRow - w4;
+                               var nextRow = centerRow + w4;
+                               
+                               var r1 = - dataCopy[priorRow]   - dataCopy[centerRow]   - dataCopy[nextRow];
+                               var g1 = - dataCopy[++priorRow] - dataCopy[++centerRow] - dataCopy[++nextRow];
+                               var b1 = - dataCopy[++priorRow] - dataCopy[++centerRow] - dataCopy[++nextRow];
+                               
+                               var rp = dataCopy[priorRow += 2];
+                               var gp = dataCopy[++priorRow];
+                               var bp = dataCopy[++priorRow];
+                               
+                               var rc = dataCopy[centerRow += 2];
+                               var gc = dataCopy[++centerRow];
+                               var bc = dataCopy[++centerRow];
+                               
+                               var rn = dataCopy[nextRow += 2];
+                               var gn = dataCopy[++nextRow];
+                               var bn = dataCopy[++nextRow];
+                               
+                               var r2 = - rp - rc - rn;
+                               var g2 = - gp - gc - gn;
+                               var b2 = - bp - bc - bn;
+                               
+                               // Main convolution loop
+                               for (var x = 1; x < wm1; ++x) {
+                                       centerRow = pixel + 4;
+                                       priorRow = centerRow - w4;
+                                       nextRow = centerRow + w4;
+                                       
+                                       var r = 127 + r1 - rp - (rc * -8) - rn;
+                                       var g = 127 + g1 - gp - (gc * -8) - gn;
+                                       var b = 127 + b1 - bp - (bc * -8) - bn;
+                                       
+                                       r1 = r2;
+                                       g1 = g2;
+                                       b1 = b2;
+                                       
+                                       rp = dataCopy[  priorRow];
+                                       gp = dataCopy[++priorRow];
+                                       bp = dataCopy[++priorRow];
+                                       
+                                       rc = dataCopy[  centerRow];
+                                       gc = dataCopy[++centerRow];
+                                       bc = dataCopy[++centerRow];
+                                       
+                                       rn = dataCopy[  nextRow];
+                                       gn = dataCopy[++nextRow];
+                                       bn = dataCopy[++nextRow];
+                                       
+                                       r += (r2 = - rp - rc - rn);
+                                       g += (g2 = - gp - gc - gn);
+                                       b += (b2 = - bp - bc - bn);
+
+                                       if (r > 255) r = 255;
+                                       if (g > 255) g = 255;
+                                       if (b > 255) b = 255;
+                                       if (r < 0) r = 0;
+                                       if (g < 0) g = 0;
+                                       if (b < 0) b = 0;
+
+                                       data[pixel] = r;
+                                       data[++pixel] = g;
+                                       data[++pixel] = b;
+                                       //data[++pixel] = 255; // alpha
+
+                                       pixel+=2;
+                               }
+                               pixel += 8;
+                       }
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/actions/emboss.js b/js2/mwEmbed/libClipEdit/pixastic-lib/actions/emboss.js
new file mode 100644 (file)
index 0000000..51e4252
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Pixastic Lib - Emboss filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * MIT License [http://www.opensource.org/licenses/mit-license.php]
+ */
+
+Pixastic.Actions.emboss = {
+       process : function(params) {
+
+               var strength = parseFloat(params.options.strength)||1;
+               var greyLevel = typeof params.options.greyLevel != "undefined" ? parseInt(params.options.greyLevel) : 180;
+               var direction = params.options.direction||"topleft";
+               var blend = !!params.options.blend;
+
+               var dirY = 0;
+               var dirX = 0;
+
+               switch (direction) {
+                       case "topleft":                 // top left
+                               dirY = -1;
+                               dirX = -1;
+                               break;
+                       case "top":                     // top
+                               dirY = -1;
+                               dirX = 0;
+                               break;
+                       case "topright":                        // top right
+                               dirY = -1;
+                               dirX = 1;
+                               break;
+                       case "right":                   // right
+                               dirY = 0;
+                               dirX = 1;
+                               break;
+                       case "bottomright":                     // bottom right
+                               dirY = 1;
+                               dirX = 1;
+                               break;
+                       case "bottom":                  // bottom
+                               dirY = 1;
+                               dirX = 0;
+                               break;
+                       case "bottomleft":                      // bottom left
+                               dirY = 1;
+                               dirX = -1;
+                               break;
+                       case "left":                    // left
+                               dirY = 0;
+                               dirX = -1;
+                               break;
+               }
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var dataCopy = Pixastic.prepareData(params, true)
+
+                       var invertAlpha = !!params.options.invertAlpha;
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+
+                               var otherY = dirY;
+                               if (y + otherY < 1) otherY = 0;
+                               if (y + otherY > h) otherY = 0;
+
+                               var offsetYOther = (y-1+otherY)*w*4;
+
+                               var x = w;
+                               do {
+                                               var offset = offsetY + (x-1)*4;
+
+                                               var otherX = dirX;
+                                               if (x + otherX < 1) otherX = 0;
+                                               if (x + otherX > w) otherX = 0;
+
+                                               var offsetOther = offsetYOther + (x-1+otherX)*4;
+
+                                               var dR = dataCopy[offset] - dataCopy[offsetOther];
+                                               var dG = dataCopy[offset+1] - dataCopy[offsetOther+1];
+                                               var dB = dataCopy[offset+2] - dataCopy[offsetOther+2];
+
+                                               var dif = dR;
+                                               var absDif = dif > 0 ? dif : -dif;
+
+                                               var absG = dG > 0 ? dG : -dG;
+                                               var absB = dB > 0 ? dB : -dB;
+
+                                               if (absG > absDif) {
+                                                       dif = dG;
+                                               }
+                                               if (absB > absDif) {
+                                                       dif = dB;
+                                               }
+
+                                               dif *= strength;
+
+                                               if (blend) {
+                                                       var r = data[offset] + dif;
+                                                       var g = data[offset+1] + dif;
+                                                       var b = data[offset+2] + dif;
+
+                                                       data[offset] = (r > 255) ? 255 : (r < 0 ? 0 : r);
+                                                       data[offset+1] = (g > 255) ? 255 : (g < 0 ? 0 : g);
+                                                       data[offset+2] = (b > 255) ? 255 : (b < 0 ? 0 : b);
+                                               } else {
+                                                       var grey = greyLevel - dif;
+                                                       if (grey < 0) {
+                                                               grey = 0;
+                                                       } else if (grey > 255) {
+                                                               grey = 255;
+                                                       }
+
+                                                       data[offset] = data[offset+1] = data[offset+2] = grey;
+                                               }
+
+                               } while (--x);
+                       } while (--y);
+                       return true;
+
+               } else if (Pixastic.Client.isIE()) {
+                       params.image.style.filter += " progid:DXImageTransform.Microsoft.emboss()";
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
+       }
+
+}
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/actions/fliph.js b/js2/mwEmbed/libClipEdit/pixastic-lib/actions/fliph.js
new file mode 100644 (file)
index 0000000..5b7b0d2
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Pixastic Lib - Horizontal flip - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * MIT License [http://www.opensource.org/licenses/mit-license.php]
+ */
+
+Pixastic.Actions.fliph = {
+       process : function(params) {
+               if (Pixastic.Client.hasCanvas()) {
+                       var rect = params.options.rect;
+                       var copyCanvas = document.createElement("canvas");
+                       copyCanvas.width = rect.width;
+                       copyCanvas.height = rect.height;
+                       copyCanvas.getContext("2d").drawImage(params.image, rect.left, rect.top, rect.width, rect.height, 0, 0, rect.width, rect.height);
+
+                       var ctx = params.canvas.getContext("2d");
+                       ctx.clearRect(rect.left, rect.top, rect.width, rect.height);
+                       ctx.scale(-1,1);
+                       ctx.drawImage(copyCanvas, -rect.left-rect.width, rect.top, rect.width, rect.height)
+                       params.useData = false;
+
+                       return true;            
+
+               } else if (Pixastic.Client.isIE()) {
+                       params.image.style.filter += " fliph";
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvas() || Pixastic.Client.isIE());
+       }
+}
+
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/actions/flipv.js b/js2/mwEmbed/libClipEdit/pixastic-lib/actions/flipv.js
new file mode 100644 (file)
index 0000000..cfc60d3
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Pixastic Lib - Vertical flip - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * MIT License [http://www.opensource.org/licenses/mit-license.php]
+ */
+
+Pixastic.Actions.flipv = {
+       process : function(params) {
+               if (Pixastic.Client.hasCanvas()) {
+                       var rect = params.options.rect;
+                       var copyCanvas = document.createElement("canvas");
+                       copyCanvas.width = rect.width;
+                       copyCanvas.height = rect.height;
+                       copyCanvas.getContext("2d").drawImage(params.image, rect.left, rect.top, rect.width, rect.height, 0, 0, rect.width, rect.height);
+
+                       var ctx = params.canvas.getContext("2d");
+                       ctx.clearRect(rect.left, rect.top, rect.width, rect.height);
+                       ctx.scale(1,-1);
+                       ctx.drawImage(copyCanvas, rect.left, -rect.top-rect.height, rect.width, rect.height)
+                       params.useData = false;
+
+                       return true;            
+
+               } else if (Pixastic.Client.isIE()) {
+                       params.image.style.filter += " flipv";
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvas() || Pixastic.Client.isIE());
+       }
+}
+
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/actions/glow.js b/js2/mwEmbed/libClipEdit/pixastic-lib/actions/glow.js
new file mode 100644 (file)
index 0000000..bd93c81
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Pixastic Lib - Glow - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * MIT License [http://www.opensource.org/licenses/mit-license.php]
+ */
+
+
+Pixastic.Actions.glow = {
+       process : function(params) {
+
+               var amount = (parseFloat(params.options.amount)||0);
+               var blurAmount = parseFloat(params.options.radius)||0;
+
+               amount = Math.min(1,Math.max(0,amount));
+               blurAmount = Math.min(5,Math.max(0,blurAmount));
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var rect = params.options.rect;
+
+                       var blurCanvas = document.createElement("canvas");
+                       blurCanvas.width = params.width;
+                       blurCanvas.height = params.height;
+                       var blurCtx = blurCanvas.getContext("2d");
+                       blurCtx.drawImage(params.canvas,0,0);
+
+                       var scale = 2;
+                       var smallWidth = Math.round(params.width / scale);
+                       var smallHeight = Math.round(params.height / scale);
+
+                       var copy = document.createElement("canvas");
+                       copy.width = smallWidth;
+                       copy.height = smallHeight;
+
+                       var clear = true;
+                       var steps = Math.round(blurAmount * 20);
+
+                       var copyCtx = copy.getContext("2d");
+                       for (var i=0;i<steps;i++) {
+                               var scaledWidth = Math.max(1,Math.round(smallWidth - i));
+                               var scaledHeight = Math.max(1,Math.round(smallHeight - i));
+       
+                               copyCtx.clearRect(0,0,smallWidth,smallHeight);
+       
+                               copyCtx.drawImage(
+                                       blurCanvas,
+                                       0,0,params.width,params.height,
+                                       0,0,scaledWidth,scaledHeight
+                               );
+       
+                               blurCtx.clearRect(0,0,params.width,params.height);
+       
+                               blurCtx.drawImage(
+                                       copy,
+                                       0,0,scaledWidth,scaledHeight,
+                                       0,0,params.width,params.height
+                               );
+                       }
+
+                       var data = Pixastic.prepareData(params);
+                       var blurData = Pixastic.prepareData({canvas:blurCanvas,options:params.options});
+                       var w = rect.width;
+                       var h = rect.height;
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x*4-4);
+
+                                       var r = data[offset] + amount * blurData[offset];
+                                       var g = data[offset+1] + amount * blurData[offset+1];
+                                       var b = data[offset+2] + amount * blurData[offset+2];
+       
+                                       if (r > 255) r = 255;
+                                       if (g > 255) g = 255;
+                                       if (b > 255) b = 255;
+                                       if (r < 0) r = 0;
+                                       if (g < 0) g = 0;
+                                       if (b < 0) b = 0;
+
+                                       data[offset] = r;
+                                       data[offset+1] = g;
+                                       data[offset+2] = b;
+
+                               } while (--x);
+                       } while (--y);
+
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}
+
+
+
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/actions/histogram.js b/js2/mwEmbed/libClipEdit/pixastic-lib/actions/histogram.js
new file mode 100644 (file)
index 0000000..4b88404
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Pixastic Lib - Histogram - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * MIT License [http://www.opensource.org/licenses/mit-license.php]
+ */
+
+Pixastic.Actions.histogram = {
+       process : function(params) {
+
+               var average = !!(params.options.average);
+               var paint = !!(params.options.paint);
+               var color = params.options.color || "rgba(255,255,255,0.5)";
+               var values = [];
+               if (typeof params.options.returnValue != "object") {
+                       params.options.returnValue = {values:[]};
+               }
+               var returnValue = params.options.returnValue;
+               if (typeof returnValue.values != "array") {
+                       returnValue.values = [];
+               }
+               values = returnValue.values;
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       params.useData = false;
+
+                       for (var i=0;i<256;i++) {
+                               values[i] = 0;
+                       }
+
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x*4-4);
+                                       var brightness = average ? 
+                                               Math.round((data[offset]+data[offset+1]+data[offset+2])/3)
+                                               : Math.round(data[offset]*0.3 + data[offset+1]*0.59 + data[offset+2]*0.11);
+                                       values[brightness]++;
+
+                               } while (--x);
+                       } while (--y);
+
+                       if (paint) {
+                               var maxValue = 0;
+                               for (var i=0;i<256;i++) {
+                                       if (values[i] > maxValue) {
+                                               maxValue = values[i];
+                                       }
+                               }
+                               var heightScale = params.height / maxValue;
+                               var widthScale = params.width / 256;
+                               var ctx = params.canvas.getContext("2d");
+                               ctx.fillStyle = color;
+                               for (var i=0;i<256;i++) {
+                                       ctx.fillRect(
+                                               i * widthScale, params.height - heightScale * values[i],
+                                               widthScale, values[i] * heightScale
+                                       );
+                               }
+                       }
+
+                       returnValue.values = values;
+
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/actions/hsl.js b/js2/mwEmbed/libClipEdit/pixastic-lib/actions/hsl.js
new file mode 100644 (file)
index 0000000..510f71b
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * Pixastic Lib - HSL Adjust  - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * MIT License [http://www.opensource.org/licenses/mit-license.php]
+ */
+
+Pixastic.Actions.hsl = {
+       process : function(params) {
+
+               var hue = parseInt(params.options.hue,10)||0;
+               var saturation = (parseInt(params.options.saturation,10)||0) / 100;
+               var lightness = (parseInt(params.options.lightness,10)||0) / 100;
+
+
+               // this seems to give the same result as Photoshop
+               if (saturation < 0) {
+                       var satMul = 1+saturation;
+               } else {
+                       var satMul = 1+saturation*2;
+               }
+
+               hue = (hue%360) / 360;
+               var hue6 = hue * 6;
+
+               var rgbDiv = 1 / 255;
+
+               var light255 = lightness * 255;
+               var lightp1 = 1 + lightness;
+               var lightm1 = 1 - lightness;
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       var w4 = w*4;
+                       var y = h;
+
+                       do {
+                               var offsetY = (y-1)*w4;
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x*4-4);
+
+                                       var r = data[offset];
+                                       var g = data[offset+1];
+                                       var b = data[offset+2];
+
+                                       if (hue != 0 || saturation != 0) {
+                                               // ok, here comes rgb to hsl + adjust + hsl to rgb, all in one jumbled mess. 
+                                               // It's not so pretty, but it's been optimized to get somewhat decent performance.
+                                               // The transforms were originally adapted from the ones found in Graphics Gems, but have been heavily modified.
+                                               var vs = r;
+                                               if (g > vs) vs = g;
+                                               if (b > vs) vs = b;
+                                               var ms = r;
+                                               if (g < ms) ms = g;
+                                               if (b < ms) ms = b;
+                                               var vm = (vs-ms);
+                                               var l = (ms+vs)/255 * 0.5;
+                                               if (l > 0) {
+                                                       if (vm > 0) {
+                                                               if (l <= 0.5) {
+                                                                       var s = vm / (vs+ms) * satMul;
+                                                                       if (s > 1) s = 1;
+                                                                       var v = (l * (1+s));
+                                                               } else {
+                                                                       var s = vm / (510-vs-ms) * satMul;
+                                                                       if (s > 1) s = 1;
+                                                                       var v = (l+s - l*s);
+                                                               }
+                                                               if (r == vs) {
+                                                                       if (g == ms)
+                                                                               var h = 5 + ((vs-b)/vm) + hue6;
+                                                                       else
+                                                                               var h = 1 - ((vs-g)/vm) + hue6;
+                                                               } else if (g == vs) {
+                                                                       if (b == ms)
+                                                                               var h = 1 + ((vs-r)/vm) + hue6;
+                                                                       else
+                                                                               var h = 3 - ((vs-b)/vm) + hue6;
+                                                               } else {
+                                                                       if (r == ms)
+                                                                               var h = 3 + ((vs-g)/vm) + hue6;
+                                                                       else
+                                                                               var h = 5 - ((vs-r)/vm) + hue6;
+                                                               }
+                                                               if (h < 0) h+=6;
+                                                               if (h >= 6) h-=6;
+                                                               var m = (l+l-v);
+                                                               var sextant = h>>0;
+                                                               switch (sextant) {
+                                                                       case 0: r = v*255; g = (m+((v-m)*(h-sextant)))*255; b = m*255; break;
+                                                                       case 1: r = (v-((v-m)*(h-sextant)))*255; g = v*255; b = m*255; break;
+                                                                       case 2: r = m*255; g = v*255; b = (m+((v-m)*(h-sextant)))*255; break;
+                                                                       case 3: r = m*255; g = (v-((v-m)*(h-sextant)))*255; b = v*255; break;
+                                                                       case 4: r = (m+((v-m)*(h-sextant)))*255; g = m*255; b = v*255; break;
+                                                                       case 5: r = v*255; g = m*255; b = (v-((v-m)*(h-sextant)))*255; break;
+                                                               }
+                                                       }
+                                               }
+                                       }
+
+                                       if (lightness < 0) {
+                                               r *= lightp1;
+                                               g *= lightp1;
+                                               b *= lightp1;
+                                       } else if (lightness > 0) {
+                                               r = r * lightm1 + light255;
+                                               g = g * lightm1 + light255;
+                                               b = b * lightm1 + light255;
+                                       }
+
+                                       if (r < 0) r = 0;
+                                       if (g < 0) g = 0;
+                                       if (b < 0) b = 0;
+                                       if (r > 255) r = 255;
+                                       if (g > 255) g = 255;
+                                       if (b > 255) b = 255;
+
+                                       data[offset] = r;
+                                       data[offset+1] = g;
+                                       data[offset+2] = b;
+
+                               } while (--x);
+                       } while (--y);
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+
+}
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/actions/invert.js b/js2/mwEmbed/libClipEdit/pixastic-lib/actions/invert.js
new file mode 100644 (file)
index 0000000..0b5102b
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Pixastic Lib - Invert filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * MIT License [http://www.opensource.org/licenses/mit-license.php]
+ */
+
+Pixastic.Actions.invert = {
+       process : function(params) {
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+
+                       var invertAlpha = !!params.options.invertAlpha;
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x-1)*4;
+                                       data[offset] = 255 - data[offset];
+                                       data[offset+1] = 255 - data[offset+1];
+                                       data[offset+2] = 255 - data[offset+2];
+                                       if (invertAlpha) data[offset+3] = 255 - data[offset+3];
+                               } while (--x);
+                       } while (--y);
+                       return true;
+               } else if (Pixastic.Client.isIE()) {
+                       params.image.style.filter += " invert";
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
+       }
+}
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/actions/laplace.js b/js2/mwEmbed/libClipEdit/pixastic-lib/actions/laplace.js
new file mode 100644 (file)
index 0000000..6a6e146
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Pixastic Lib - Laplace filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * MIT License [http://www.opensource.org/licenses/mit-license.php]
+ */
+
+Pixastic.Actions.laplace = {
+       process : function(params) {
+
+               var strength = 1.0;
+               var invert = !!(params.options.invert);
+               var contrast = parseFloat(params.options.edgeStrength)||0;
+
+               var greyLevel = parseInt(params.options.greyLevel)||0;
+
+               contrast = -contrast;
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var dataCopy = Pixastic.prepareData(params, true)
+
+                       var kernel = [
+                               [-1,    -1,     -1],
+                               [-1,    8,      -1],
+                               [-1,    -1,     -1]
+                       ];
+
+                       var weight = 1/8;
+
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+
+                               var nextY = (y == h) ? y - 1 : y;
+                               var prevY = (y == 1) ? 0 : y-2;
+
+                               var offsetYPrev = prevY*w*4;
+                               var offsetYNext = nextY*w*4;
+
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x*4-4);
+
+                                       var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
+                                       var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
+       
+                                       var r = ((-dataCopy[offsetPrev-4]
+                                               - dataCopy[offsetPrev]
+                                               - dataCopy[offsetPrev+4]
+                                               - dataCopy[offset-4]
+                                               - dataCopy[offset+4]
+                                               - dataCopy[offsetNext-4]
+                                               - dataCopy[offsetNext]
+                                               - dataCopy[offsetNext+4])
+                                               + dataCopy[offset] * 8) 
+                                               * weight;
+       
+                                       var g = ((-dataCopy[offsetPrev-3]
+                                               - dataCopy[offsetPrev+1]
+                                               - dataCopy[offsetPrev+5]
+                                               - dataCopy[offset-3]
+                                               - dataCopy[offset+5]
+                                               - dataCopy[offsetNext-3]
+                                               - dataCopy[offsetNext+1]
+                                               - dataCopy[offsetNext+5])
+                                               + dataCopy[offset+1] * 8)
+                                               * weight;
+       
+                                       var b = ((-dataCopy[offsetPrev-2]
+                                               - dataCopy[offsetPrev+2]
+                                               - dataCopy[offsetPrev+6]
+                                               - dataCopy[offset-2]
+                                               - dataCopy[offset+6]
+                                               - dataCopy[offsetNext-2]
+                                               - dataCopy[offsetNext+2]
+                                               - dataCopy[offsetNext+6])
+                                               + dataCopy[offset+2] * 8)
+                                               * weight;
+
+                                       var brightness = ((r + g + b)/3) + greyLevel;
+
+                                       if (contrast != 0) {
+                                               if (brightness > 127) {
+                                                       brightness += ((brightness + 1) - 128) * contrast;
+                                               } else if (brightness < 127) {
+                                                       brightness -= (brightness + 1) * contrast;
+                                               }
+                                       }
+                                       if (invert) {
+                                               brightness = 255 - brightness;
+                                       }
+                                       if (brightness < 0 ) brightness = 0;
+                                       if (brightness > 255 ) brightness = 255;
+
+                                       data[offset] = data[offset+1] = data[offset+2] = brightness;
+
+                               } while (--x);
+                       } while (--y);
+
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}
+
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/actions/lighten.js b/js2/mwEmbed/libClipEdit/pixastic-lib/actions/lighten.js
new file mode 100644 (file)
index 0000000..90381aa
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Pixastic Lib - Lighten filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * MIT License [http://www.opensource.org/licenses/mit-license.php]
+ */
+
+Pixastic.Actions.lighten = {
+
+       process : function(params) {
+               var amount = parseFloat(params.options.amount) || 0;
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x-1)*4;
+
+                                       var r = data[offset];
+                                       var g = data[offset+1];
+                                       var b = data[offset+2];
+
+                                       r += r*amount;
+                                       g += g*amount;
+                                       b += b*amount;
+
+                                       if (r < 0 ) r = 0;
+                                       if (g < 0 ) g = 0;
+                                       if (b < 0 ) b = 0;
+                                       if (r > 255 ) r = 255;
+                                       if (g > 255 ) g = 255;
+                                       if (b > 255 ) b = 255;
+
+                                       data[offset] = r;
+                                       data[offset+1] = g;
+                                       data[offset+2] = b;
+
+                               } while (--x);
+                       } while (--y);
+                       return true;
+
+               } else if (Pixastic.Client.isIE()) {
+                       var img = params.image;
+                       if (amount < 0) {
+                               img.style.filter += " light()";
+                               img.filters[img.filters.length-1].addAmbient(
+                                       255,255,255,
+                                       100 * -amount
+                               );
+                       } else if (amount > 0) {
+                               img.style.filter += " light()";
+                               img.filters[img.filters.length-1].addAmbient(
+                                       255,255,255,
+                                       100
+                               );
+                               img.filters[img.filters.length-1].addAmbient(
+                                       255,255,255,
+                                       100 * amount
+                               );
+                       }
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
+       }
+}
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/actions/mosaic.js b/js2/mwEmbed/libClipEdit/pixastic-lib/actions/mosaic.js
new file mode 100644 (file)
index 0000000..ee462af
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Pixastic Lib - Mosaic filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * MIT License [http://www.opensource.org/licenses/mit-license.php]
+ */
+
+Pixastic.Actions.mosaic = {
+
+       process : function(params) {
+               var blockSize = Math.max(1,parseInt(params.options.blockSize,10));
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+                       var w4 = w*4;
+                       var y = h;
+
+                       var ctx = params.canvas.getContext("2d");
+
+                       var pixel = document.createElement("canvas");
+                       pixel.width = pixel.height = 1;
+                       var pixelCtx = pixel.getContext("2d");
+
+                       var copy = document.createElement("canvas");
+                       copy.width = w;
+                       copy.height = h;
+                       var copyCtx = copy.getContext("2d");
+                       copyCtx.drawImage(params.canvas,rect.left,rect.top,w,h, 0,0,w,h);
+
+                       for (var y=0;y<h;y+=blockSize) {
+                               for (var x=0;x<w;x+=blockSize) {
+                                       pixelCtx.drawImage(copy, x, y, blockSize, blockSize, 0, 0, 1, 1);
+                                       var data = pixelCtx.getImageData(0,0,1,1).data;
+                                       ctx.fillStyle = "rgb(" + data[0] + "," + data[1] + "," + data[2] + ")";
+                                       ctx.fillRect(rect.left + x, rect.top + y, blockSize, blockSize);
+                               }
+                       }
+
+                       params.useData = false;
+
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvasImageData());
+       }
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/actions/noise.js b/js2/mwEmbed/libClipEdit/pixastic-lib/actions/noise.js
new file mode 100644 (file)
index 0000000..97ba825
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Pixastic Lib - Noise filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * MIT License [http://www.opensource.org/licenses/mit-license.php]
+ */
+
+Pixastic.Actions.noise = {
+
+       process : function(params) {
+               var amount = 0;
+               var strength = 0;
+               var mono = false;
+
+               if (typeof params.options.amount != "undefined")
+                       amount = parseFloat(params.options.amount)||0;
+               if (typeof params.options.strength != "undefined")
+                       strength = parseFloat(params.options.strength)||0;
+               if (typeof params.options.mono != "undefined")
+                       mono = !!(params.options.mono);
+
+               amount = Math.max(0,Math.min(1,amount));
+               strength = Math.max(0,Math.min(1,strength));
+
+               var noise = 128 * strength;
+               var noise2 = noise / 2;
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+                       var w4 = w*4;
+                       var y = h;
+                       var random = Math.random;
+
+                       do {
+                               var offsetY = (y-1)*w4;
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x-1)*4;
+                                       if (random() < amount) {
+                                               if (mono) {
+                                                       var pixelNoise = - noise2 + random() * noise;
+                                                       var r = data[offset] + pixelNoise;
+                                                       var g = data[offset+1] + pixelNoise;
+                                                       var b = data[offset+2] + pixelNoise;
+                                               } else {
+                                                       var r = data[offset] - noise2 + (random() * noise);
+                                                       var g = data[offset+1] - noise2 + (random() * noise);
+                                                       var b = data[offset+2] - noise2 + (random() * noise);
+                                               }
+
+                                               if (r < 0 ) r = 0;
+                                               if (g < 0 ) g = 0;
+                                               if (b < 0 ) b = 0;
+                                               if (r > 255 ) r = 255;
+                                               if (g > 255 ) g = 255;
+                                               if (b > 255 ) b = 255;
+
+                                               data[offset] = r;
+                                               data[offset+1] = g;
+                                               data[offset+2] = b;
+                                       }
+                               } while (--x);
+                       } while (--y);
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}
+
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/actions/pointillize.js b/js2/mwEmbed/libClipEdit/pixastic-lib/actions/pointillize.js
new file mode 100644 (file)
index 0000000..59329c8
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Pixastic Lib - Pointillize filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * MIT License [http://www.opensource.org/licenses/mit-license.php]
+ */
+
+Pixastic.Actions.pointillize = {
+
+       process : function(params) {
+               var radius = Math.max(1,parseInt(params.options.radius,10));
+               var density = Math.min(5,Math.max(0,parseFloat(params.options.density)||0));
+               var noise = Math.max(0,parseFloat(params.options.noise)||0);
+               var transparent = !!params.options.transparent;
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+                       var w4 = w*4;
+                       var y = h;
+
+                       var ctx = params.canvas.getContext("2d");
+
+                       var pixel = document.createElement("canvas");
+                       pixel.width = pixel.height = 1;
+                       var pixelCtx = pixel.getContext("2d");
+
+                       var copy = document.createElement("canvas");
+                       copy.width = w;
+                       copy.height = h;
+                       var copyCtx = copy.getContext("2d");
+                       copyCtx.drawImage(params.canvas,rect.left,rect.top,w,h, 0,0,w,h);
+
+                       var diameter = radius * 2;
+
+                       if (transparent)
+                               ctx.clearRect(rect.left, rect.top, rect.width, rect.height);
+
+                       var noiseRadius = radius * noise;
+
+                       var dist = 1 / density;
+
+                       for (var y=0;y<h+radius;y+=diameter*dist) {
+                               for (var x=0;x<w+radius;x+=diameter*dist) {
+                                       rndX = noise ? (x+((Math.random()*2-1) * noiseRadius))>>0 : x;
+                                       rndY = noise ? (y+((Math.random()*2-1) * noiseRadius))>>0 : y;
+
+                                       var pixX = rndX - radius;
+                                       var pixY = rndY - radius;
+                                       if (pixX < 0) pixX = 0;
+                                       if (pixY < 0) pixY = 0;
+
+                                       pixelCtx.drawImage(copy, pixX, pixY, diameter, diameter, 0, 0, 1, 1);
+                                       var data = pixelCtx.getImageData(0,0,1,1).data;
+                                       ctx.fillStyle = "rgb(" + data[0] + "," + data[1] + "," + data[2] + ")";
+                                       ctx.beginPath();
+                                       ctx.arc(rect.left + rndX,rect.top + rndY, radius, 0, Math.PI*2, true);
+                                       ctx.closePath();
+                                       ctx.fill();
+                               }
+                       }
+
+                       params.useData = false;
+
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvasImageData());
+       }
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/actions/posterize.js b/js2/mwEmbed/libClipEdit/pixastic-lib/actions/posterize.js
new file mode 100644 (file)
index 0000000..1bc629a
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Pixastic Lib - Posterize effect - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * MIT License [http://www.opensource.org/licenses/mit-license.php]
+ */
+
+Pixastic.Actions.posterize = {
+
+       process : function(params) {
+
+               
+               var numLevels = 256;
+               if (typeof params.options.levels != "undefined")
+                       numLevels = parseInt(params.options.levels,10)||1;
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+
+                       numLevels = Math.max(2,Math.min(256,numLevels));
+       
+                       var numAreas = 256 / numLevels;
+                       var numValues = 256 / (numLevels-1);
+
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x-1)*4;
+
+                                       var r = numValues * ((data[offset] / numAreas)>>0);
+                                       var g = numValues * ((data[offset+1] / numAreas)>>0);
+                                       var b = numValues * ((data[offset+2] / numAreas)>>0);
+
+                                       if (r > 255) r = 255;
+                                       if (g > 255) g = 255;
+                                       if (b > 255) b = 255;
+
+                                       data[offset] = r;
+                                       data[offset+1] = g;
+                                       data[offset+2] = b;
+
+                               } while (--x);
+                       } while (--y);
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}
+
+
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/actions/removenoise.js b/js2/mwEmbed/libClipEdit/pixastic-lib/actions/removenoise.js
new file mode 100644 (file)
index 0000000..042033a
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Pixastic Lib - Remove noise - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * MIT License [http://www.opensource.org/licenses/mit-license.php]
+ */
+
+Pixastic.Actions.removenoise = {
+       process : function(params) {
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+
+                               var nextY = (y == h) ? y - 1 : y;
+                               var prevY = (y == 1) ? 0 : y-2;
+
+                               var offsetYPrev = prevY*w*4;
+                               var offsetYNext = nextY*w*4;
+
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x*4-4);
+
+                                       var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
+                                       var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
+
+                                       var minR, maxR, minG, maxG, minB, maxB;
+
+                                       minR = maxR = data[offsetPrev];
+                                       var r1 = data[offset-4], r2 = data[offset+4], r3 = data[offsetNext];
+                                       if (r1 < minR) minR = r1;
+                                       if (r2 < minR) minR = r2;
+                                       if (r3 < minR) minR = r3;
+                                       if (r1 > maxR) maxR = r1;
+                                       if (r2 > maxR) maxR = r2;
+                                       if (r3 > maxR) maxR = r3;
+
+                                       minG = maxG = data[offsetPrev+1];
+                                       var g1 = data[offset-3], g2 = data[offset+5], g3 = data[offsetNext+1];
+                                       if (g1 < minG) minG = g1;
+                                       if (g2 < minG) minG = g2;
+                                       if (g3 < minG) minG = g3;
+                                       if (g1 > maxG) maxG = g1;
+                                       if (g2 > maxG) maxG = g2;
+                                       if (g3 > maxG) maxG = g3;
+
+                                       minB = maxB = data[offsetPrev+2];
+                                       var b1 = data[offset-2], b2 = data[offset+6], b3 = data[offsetNext+2];
+                                       if (b1 < minB) minB = b1;
+                                       if (b2 < minB) minB = b2;
+                                       if (b3 < minB) minB = b3;
+                                       if (b1 > maxB) maxB = b1;
+                                       if (b2 > maxB) maxB = b2;
+                                       if (b3 > maxB) maxB = b3;
+
+                                       if (data[offset] > maxR) {
+                                               data[offset] = maxR;
+                                       } else if (data[offset] < minR) {
+                                               data[offset] = minR;
+                                       }
+                                       if (data[offset+1] > maxG) {
+                                               data[offset+1] = maxG;
+                                       } else if (data[offset+1] < minG) {
+                                               data[offset+1] = minG;
+                                       }
+                                       if (data[offset+2] > maxB) {
+                                               data[offset+2] = maxB;
+                                       } else if (data[offset+2] < minB) {
+                                               data[offset+2] = minB;
+                                       }
+
+                               } while (--x);
+                       } while (--y);
+
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/actions/sepia.js b/js2/mwEmbed/libClipEdit/pixastic-lib/actions/sepia.js
new file mode 100644 (file)
index 0000000..016bf20
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Pixastic Lib - Sepia filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * MIT License [http://www.opensource.org/licenses/mit-license.php]
+ */
+
+Pixastic.Actions.sepia = {
+
+       process : function(params) {
+               var mode = (parseInt(params.options.mode,10)||0);
+               if (mode < 0) mode = 0;
+               if (mode > 1) mode = 1;
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x-1)*4;
+
+                                       if (mode) {
+                                               // a bit faster, but not as good
+                                               var d = data[offset] * 0.299 + data[offset+1] * 0.587 + data[offset+2] * 0.114;
+                                               var r = (d + 39);
+                                               var g = (d + 14);
+                                               var b = (d - 36);
+                                       } else {
+                                               // Microsoft
+                                               var or = data[offset];
+                                               var og = data[offset+1];
+                                               var ob = data[offset+2];
+       
+                                               var r = (or * 0.393 + og * 0.769 + ob * 0.189);
+                                               var g = (or * 0.349 + og * 0.686 + ob * 0.168);
+                                               var b = (or * 0.272 + og * 0.534 + ob * 0.131);
+                                       }
+
+                                       if (r < 0) r = 0; if (r > 255) r = 255;
+                                       if (g < 0) g = 0; if (g > 255) g = 255;
+                                       if (b < 0) b = 0; if (b > 255) b = 255;
+
+                                       data[offset] = r;
+                                       data[offset+1] = g;
+                                       data[offset+2] = b;
+
+                               } while (--x);
+                       } while (--y);
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/actions/sharpen.js b/js2/mwEmbed/libClipEdit/pixastic-lib/actions/sharpen.js
new file mode 100644 (file)
index 0000000..d013832
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Pixastic Lib - Sharpen filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * MIT License [http://www.opensource.org/licenses/mit-license.php]
+ */
+
+Pixastic.Actions.sharpen = {
+       process : function(params) {
+
+               var strength = 0;
+               if (typeof params.options.amount != "undefined")
+                       strength = parseFloat(params.options.amount)||0;
+
+               if (strength < 0) strength = 0;
+               if (strength > 1) strength = 1;
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var dataCopy = Pixastic.prepareData(params, true)
+
+                       var mul = 15;
+                       var mulOther = 1 + 3*strength;
+
+                       var kernel = [
+                               [0,     -mulOther,      0],
+                               [-mulOther,     mul,    -mulOther],
+                               [0,     -mulOther,      0]
+                       ];
+
+                       var weight = 0;
+                       for (var i=0;i<3;i++) {
+                               for (var j=0;j<3;j++) {
+                                       weight += kernel[i][j];
+                               }
+                       }
+
+                       weight = 1 / weight;
+
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       mul *= weight;
+                       mulOther *= weight;
+
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+
+                               var nextY = (y == h) ? y - 1 : y;
+                               var prevY = (y == 1) ? 0 : y-2;
+
+                               var offsetYPrev = prevY*w4;
+                               var offsetYNext = nextY*w4;
+
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x*4-4);
+
+                                       var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
+                                       var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
+
+                                       var r = ((
+                                               - dataCopy[offsetPrev]
+                                               - dataCopy[offset-4]
+                                               - dataCopy[offset+4]
+                                               - dataCopy[offsetNext])         * mulOther
+                                               + dataCopy[offset]      * mul
+                                               );
+
+                                       var g = ((
+                                               - dataCopy[offsetPrev+1]
+                                               - dataCopy[offset-3]
+                                               - dataCopy[offset+5]
+                                               - dataCopy[offsetNext+1])       * mulOther
+                                               + dataCopy[offset+1]    * mul
+                                               );
+
+                                       var b = ((
+                                               - dataCopy[offsetPrev+2]
+                                               - dataCopy[offset-2]
+                                               - dataCopy[offset+6]
+                                               - dataCopy[offsetNext+2])       * mulOther
+                                               + dataCopy[offset+2]    * mul
+                                               );
+
+
+                                       if (r < 0 ) r = 0;
+                                       if (g < 0 ) g = 0;
+                                       if (b < 0 ) b = 0;
+                                       if (r > 255 ) r = 255;
+                                       if (g > 255 ) g = 255;
+                                       if (b > 255 ) b = 255;
+
+                                       data[offset] = r;
+                                       data[offset+1] = g;
+                                       data[offset+2] = b;
+
+                               } while (--x);
+                       } while (--y);
+
+                       return true;
+
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/actions/solarize.js b/js2/mwEmbed/libClipEdit/pixastic-lib/actions/solarize.js
new file mode 100644 (file)
index 0000000..33205ad
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Pixastic Lib - Solarize filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * MIT License [http://www.opensource.org/licenses/mit-license.php]
+ */
+
+Pixastic.Actions.solarize = {
+
+       process : function(params) {
+               var useAverage = !!params.options.average;
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x-1)*4;
+
+                                       var r = data[offset];
+                                       var g = data[offset+1];
+                                       var b = data[offset+2];
+
+                                       if (r > 127) r = 255 - r;
+                                       if (g > 127) g = 255 - g;
+                                       if (b > 127) b = 255 - b;
+
+                                       data[offset] = r;
+                                       data[offset+1] = g;
+                                       data[offset+2] = b;
+
+                               } while (--x);
+                       } while (--y);
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvasImageData());
+       }
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/actions/unsharpmask.js b/js2/mwEmbed/libClipEdit/pixastic-lib/actions/unsharpmask.js
new file mode 100644 (file)
index 0000000..6c562e2
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Pixastic Lib - USM - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * MIT License [http://www.opensource.org/licenses/mit-license.php]
+ */
+
+
+Pixastic.Actions.unsharpmask = {
+       process : function(params) {
+
+               var amount = (parseFloat(params.options.amount)||0);
+               var blurAmount = parseFloat(params.options.radius)||0;
+               var threshold = parseFloat(params.options.threshold)||0;
+
+               amount = Math.min(500,Math.max(0,amount)) / 2;
+               blurAmount = Math.min(5,Math.max(0,blurAmount)) / 10;
+               threshold = Math.min(255,Math.max(0,threshold));
+
+               threshold--;
+               var thresholdNeg = -threshold;
+
+               amount *= 0.016;
+               amount++;
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var rect = params.options.rect;
+
+                       var blurCanvas = document.createElement("canvas");
+                       blurCanvas.width = params.width;
+                       blurCanvas.height = params.height;
+                       var blurCtx = blurCanvas.getContext("2d");
+                       blurCtx.drawImage(params.canvas,0,0);
+
+                       var scale = 2;
+                       var smallWidth = Math.round(params.width / scale);
+                       var smallHeight = Math.round(params.height / scale);
+
+                       var copy = document.createElement("canvas");
+                       copy.width = smallWidth;
+                       copy.height = smallHeight;
+
+                       var steps = Math.round(blurAmount * 20);
+
+                       var copyCtx = copy.getContext("2d");
+                       for (var i=0;i<steps;i++) {
+                               var scaledWidth = Math.max(1,Math.round(smallWidth - i));
+                               var scaledHeight = Math.max(1,Math.round(smallHeight - i));
+
+                               copyCtx.clearRect(0,0,smallWidth,smallHeight);
+
+                               copyCtx.drawImage(
+                                       blurCanvas,
+                                       0,0,params.width,params.height,
+                                       0,0,scaledWidth,scaledHeight
+                               );
+       
+                               blurCtx.clearRect(0,0,params.width,params.height);
+       
+                               blurCtx.drawImage(
+                                       copy,
+                                       0,0,scaledWidth,scaledHeight,
+                                       0,0,params.width,params.height
+                               );
+                       }
+
+                       var data = Pixastic.prepareData(params);
+                       var blurData = Pixastic.prepareData({canvas:blurCanvas,options:params.options});
+                       var w = rect.width;
+                       var h = rect.height;
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x*4-4);
+
+                                       var difR = data[offset] - blurData[offset];
+                                       if (difR > threshold || difR < thresholdNeg) {
+                                               var blurR = blurData[offset];
+                                               blurR = amount * difR + blurR;
+                                               data[offset] = blurR > 255 ? 255 : (blurR < 0 ? 0 : blurR);
+                                       }
+
+                                       var difG = data[offset+1] - blurData[offset+1];
+                                       if (difG > threshold || difG < thresholdNeg) {
+                                               var blurG = blurData[offset+1];
+                                               blurG = amount * difG + blurG;
+                                               data[offset+1] = blurG > 255 ? 255 : (blurG < 0 ? 0 : blurG);
+                                       }
+
+                                       var difB = data[offset+2] - blurData[offset+2];
+                                       if (difB > threshold || difB < thresholdNeg) {
+                                               var blurB = blurData[offset+2];
+                                               blurB = amount * difB + blurB;
+                                               data[offset+2] = blurB > 255 ? 255 : (blurB < 0 ? 0 : blurB);
+                                       }
+
+                               } while (--x);
+                       } while (--y);
+
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}
+
+
+
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/pixastic-editor/editor.js b/js2/mwEmbed/libClipEdit/pixastic-lib/pixastic-editor/editor.js
new file mode 100644 (file)
index 0000000..6789531
--- /dev/null
@@ -0,0 +1,968 @@
+
+var PixasticEditor = (function () {
+
+       var $frame;     // iframe container element
+       var $editor;    // editor container element
+
+       // various UI structures
+       var accordionElements = {};
+       var tabElements = {};
+       var activeTabId;
+       var $activeTabContent;
+
+       var isRunning = false;
+
+       var $loadingScreen;
+
+       var $imageCanvas;       // the canvas holding the current state of the image
+       var $displayCanvas;     // the canvas element displayed on the screen, also the working canvas (where preview operations are performed)
+       var imageCtx;
+
+       var imageWidth = 0;     // dimensions of the current image state
+       var imageHeight = 0;
+
+       var undoImages = [];    // canvas elements holding previous image states
+       var undoLevels = 10;
+
+       var doc;
+
+       var $;
+
+       // test for valid file formats for toDataURL()
+       // we do that by calling it with each of the mime types in testFormats
+       // and then doing string checking on the resulting data: URI to see if it succeeded
+       var saveFormats = [];
+       var testFormats = [["image/jpeg", "JPEG"], ["image/png", "PNG"]];
+       var testCanvas = document.createElement("canvas");
+       if (testCanvas.toDataURL) {
+               testCanvas.width = testCanvas.height = 1;
+               for (var i=0;i<testFormats.length;i++) {
+                       var data = testCanvas.toDataURL(testFormats[i][0]);
+                       if (data.substr(0, 5 + testFormats[i][0].length) == "data:" + testFormats[i][0])
+                               saveFormats.push({mime:testFormats[i][0], name:testFormats[i][1]});
+               }
+       }
+
+
+       // pops up an error dialog with the specified text (errTxt),
+       // if no context is provided, the name of the calling function is used.
+       // The final message is returned for easy throwing of actual errors
+       function errorDialog(errTxt, context) {
+               if (!($editor && $editor.get && $editor.get(0)))
+                       throw new Error("errorDialog(): $editor doesn't exist");
+
+               var caller = errorDialog.caller.toString().split(" ")[1];
+               caller = caller.substring(0, caller.indexOf("("));
+               context = context || caller;
+               errTxt = context + "(): " + errTxt;
+               var dialog = $j("<div></div>", doc)
+                       .addClass("error-dialog")
+                       .attr("title", "Oops!")
+                       .html(errTxt)
+                       .dialog();
+               // the dialog is added outside the Pixastic container, so get it back in.
+               var dialogParent = $j(dialog.get(0).parentNode);
+               dialogParent.appendTo($editor);
+
+               return errTxt;
+       }
+       
+       function enableTab(id, refresh) {
+               if (id == activeTabId && !refresh)
+                       return;
+
+               activeTabId = id;
+
+               var activeIndex = 0;
+
+               if ($activeTabContent) {
+                       if ($activeTabContent.get(0)) {
+                               var $parent = $j($activeTabContent.get(0).parentNode);
+                               activeIndex = $parent.data("accordionindex");
+                               if ($parent.data("ondeactivate")) {
+                                       $parent.data("ondeactivate")();
+                               }
+                               if ($parent.data("previewCheckbox"))
+                                       $parent.data("previewCheckbox").attr("checked", false);
+                               $parent.data("uidesc").previewEnabled = false;
+                               if ($parent.data("uidesc").forcePreview)
+                                       $parent.data("uidesc").previewEnabled = true;
+                       }
+               }
+
+
+               for (var a in accordionElements) {
+                       if (accordionElements.hasOwnProperty(a)) {
+                               accordionElements[a].accordion("option", "animated", false);
+                               accordionElements[a].accordion("activate", -1);
+                               accordionElements[a].hide();
+                               tabElements[a].removeClass("active");
+
+                       }
+               }
+
+               accordionElements[id].accordion("option", "animated", false);
+               accordionElements[id].accordion("activate", refresh ? activeIndex : 0);
+               tabElements[id].addClass("active");
+               accordionElements[id].show();
+               accordionElements[id].accordion("option", "animated", "slide");
+               resetDisplayCanvas();
+       }
+
+       // revert to a previous image state
+       function undo(idx) {
+               var undoImage = undoImages[idx];
+
+               if (!undoImage) 
+                       throw new Error(errorDialog("Invalid undo state"));
+               if (!($imageCanvas && $imageCanvas.get && $imageCanvas.get(0)))
+                       throw new Error(errorDialog("$imageCanvas doesn't exist"));
+
+               var canvas = $imageCanvas.get(0);
+               addUndo(canvas);
+               canvas.width = imageWidth = undoImage.width;
+               canvas.height = imageHeight = undoImage.height;
+               canvas.getContext("2d").drawImage(undoImage,0,0);
+
+               enableTab(activeTabId, true);
+               resetDisplayCanvas();
+       }
+
+       function addUndo(canvasElement) {
+               if (!canvasElement)
+                       throw new Error(errorDialog("No undo image state provided"));
+
+               if (undoImages.length == undoLevels) {
+                       undoImages.shift();
+               }
+               var undoCanvas = document.createElement("canvas");
+               undoCanvas.width = canvasElement.width;
+               undoCanvas.height = canvasElement.height;
+               undoCanvas.getContext("2d").drawImage(canvasElement,0,0);
+               $j(undoCanvas).addClass("undo-canvas");
+               undoImages.push(undoCanvas);
+               updateUndoList();
+       }
+
+       function updateUndoList() {
+               var $listCtr = $j("#undo-bar", doc)
+                       .html("");
+
+               var ctrHeight = $listCtr.height();
+
+               var $testCanvas = $j("<canvas></canvas>", doc)
+                       .addClass("undo-canvas-small")
+                       .addClass("far-far-away")
+                       .appendTo("body");
+
+               var canvasHeight = $testCanvas.height();
+               var canvasWidth = $testCanvas.width();
+               var canvasCSSHeight = canvasHeight + parseInt($testCanvas.css("margin-top"),10) + parseInt($testCanvas.css("margin-bottom"),10);
+
+               $testCanvas.remove();
+
+               var undoRatio = canvasWidth / canvasHeight;
+
+               for (var i=undoImages.length-1;i>=0;i--) {
+                       (function(){
+                               var canvas = document.createElement("canvas");
+                               $j(canvas)
+                                       .addClass("undo-canvas-small")
+                                       .attr("width", canvasWidth)
+                                       .attr("height", canvasHeight);
+
+                               var image = undoImages[i];
+                               $j(image).show();
+                               
+                               var undoWidth, undoHeight;
+                               var imageRatio = image.width / image.height;
+
+                               if (imageRatio > undoRatio) {   // image too wide
+                                       undoWidth = canvasWidth;
+                                       undoHeight = canvasWidth / imageRatio;
+                               } else {
+                                       undoWidth = canvasHeight * imageRatio;
+                                       undoHeight = canvasHeight;
+                               }
+
+                               var restWidth = canvasWidth - undoWidth;
+                               var restHeight = canvasHeight - undoHeight;
+
+                               canvas.getContext("2d").drawImage(
+                                       image,
+                                       0,0,image.width,image.height,
+                                       restWidth*0.5, restHeight*0.5,
+                                       undoWidth, undoHeight
+                               );
+
+
+                               $link = $j("<a href='#'></a>", doc)
+                                       .addClass("undo-link")
+                                       .appendTo($listCtr)
+                                       .mouseover(function(){ $j(this).addClass("hover") })
+                                       .mouseout(function(){ $j(this).removeClass("hover") });
+                               $j(canvas).appendTo($link);
+
+                               var displayShowing;
+                               var undoIndex = i;
+                               $link.click(function() {
+                                       $j(image).hide();
+                                       $j(image).remove();
+                                       undo(undoIndex);
+                                       if (displayShowing)
+                                               $displayCanvas.show();
+                                       $j(".jcrop-holder", doc).show();
+                               });
+
+                               $link.mouseover(function() {
+                                       displayShowing = $displayCanvas.css("display") != "none";
+                                       var $imagectr = $j("#image-container", doc);
+
+                                       $j(".jcrop-holder", doc).hide();
+                                       $displayCanvas.hide();
+                                       $j(image).appendTo($imagectr);
+
+                                       var h1 = $j("#image-area", doc).height();
+                                       var h2 = image.height;
+                                       var m = Math.max(0, (h1 - h2) / 2);
+                                       $imagectr.css("marginTop", m);
+                       
+                                       $imagectr.height(image.height);
+                               });
+
+                               $link.mouseout(function() {
+                                       $j(image).remove();
+                                       if (displayShowing)
+                                               $displayCanvas.show();
+                                       $j(".jcrop-holder", doc).show();
+                                       updateDisplayCanvas();
+                               });
+
+
+                               $j(canvas).attr("title", "Click to revert to this previous image");
+
+                       })();
+               }
+       }
+
+
+       function applyAction(id, options, afteraction) {
+               if (!Pixastic.Actions[id])
+                       throw new Error("applyAction(): unknown action [" + id + "]");
+
+               $j("#action-bar-overlay", doc).show();
+
+               setTimeout(function() {
+                       options.leaveDOM = true;
+                       var canvasElement = $imageCanvas.get(0);
+                       addUndo(canvasElement)
+       
+                       var res = Pixastic.process(
+                               canvasElement, id, options,
+                               function(resCanvas) {
+                                       canvasElement.width = imageWidth = resCanvas.width;
+                                       canvasElement.height = imageHeight = resCanvas.height;
+       
+                                       var ctx = canvasElement.getContext("2d");
+                                       ctx.clearRect(0,0,imageWidth,imageHeight);
+                                       ctx.drawImage(resCanvas,0,0);
+                                       $imageCanvas = $j(canvasElement);
+                                       resetDisplayCanvas();
+       
+                                       $j("#action-bar-overlay", doc).hide();
+
+                                       if (afteraction)
+                                               afteraction();
+                               }
+                       );
+                       if (!res)
+                               throw new Error("applyAction(): Pixastic.process() failed for action [" + id + "]");
+               },1);
+       }
+
+
+       function previewAction(id, options, afteraction) {
+               if (!Pixastic.Actions[id])
+                       throw new Error("applyAction(): unknown action [" + id + "]");
+
+               $j("#action-bar-overlay", doc).show();
+
+               resetDisplayCanvas();
+
+               options.leaveDOM = true;
+               var canvasElement = $displayCanvas.get(0);
+
+               var res = Pixastic.process(
+                       canvasElement, id, options,
+                       function(resCanvas) {
+
+                               canvasElement.width = resCanvas.width;
+                               canvasElement.height = resCanvas.height;
+
+                               var ctx = canvasElement.getContext("2d");
+                               ctx.clearRect(0,0,canvasElement.width,canvasElement.height);
+                               ctx.drawImage(resCanvas,0,0);
+                               updateDisplayCanvas();
+                               updateOverlay();
+
+                               $j("#action-bar-overlay", doc).hide();
+
+                               if (afteraction)
+                                       afteraction();
+                       }
+               );
+       }
+
+       var onwindowresize = function() {
+               updateDisplayCanvas();
+               updateOverlay();
+       }
+
+       var baseUrl = ""
+
+       function buildEditor() {
+               var styles = [
+                       "jquery-ui-1.7.1.custom.css",
+                       "jquery.Jcrop.css",
+                       "pixastic.css"
+               ];
+
+               for (var i=0;i<styles.length;i++) {
+                       var s = doc.createElement("link");
+                       s.href = baseUrl + styles[i];
+                       s.type = "text/css";
+                       s.rel = "stylesheet";
+                       doc.getElementsByTagName("head")[0].appendChild( s );
+               }
+
+               undoImages = [];
+               accordionElements = {};
+               tabElements = {};
+               activeTabId = -1;
+               $activeTabContent = null;
+
+               // setup DOM UI skeleton
+               $editor = $j("<div />", doc)
+                       .attr("id", "pixastic-editor")
+                       .appendTo($j(doc.body));
+
+               $editor.append(
+                       $j("<div id='background' />", doc),
+                       $j("<div id='edit-ctr-1' />", doc).append(
+                               $j("<div id='edit-ctr-2' />", doc).append(
+                                       $j("<div id='controls-bar' />", doc).append(
+                                               $j("<div id='action-bar' />", doc).append(
+                                                       $j("<div id='action-bar-overlay' />", doc)
+                                               ),
+                                               $j("<div id='undo-bar' />", doc)
+                                       ),
+                                       $j("<div id='image-area' />", doc).append(
+                                               $j("<div id='image-area-sub' />", doc).append(
+                                                       $j("<div id='image-container' />", doc),
+                                                       $j("<div id='image-overlay-container' />", doc).append(
+                                                               $j("<div id='image-overlay' />", doc)
+                                                       )
+                                               )
+                                       )
+                               )
+                       ),
+                       $j("<div id='main-bar' />", doc),
+                       $j("<div id='powered-by-pixastic'><a href=\"http://www.pixastic.com/\" target=\"_blank\">Powered by Pixastic</a></div>", doc)
+               );
+
+               $j("#image-container", doc).append(
+                       $displayCanvas = $j("<canvas />", doc)
+                               .addClass("display-canvas")
+               );
+
+               // loop through all  defined UI action controls
+               var tabs = PixasticEditor.UI.data.tabs;
+
+               for (var i=0;i<tabs.length;i++) {
+                       (function() {
+       
+                       var tab = tabs[i];
+
+                       var $tabElement = $j("<a href=\"#\">" + tab.title + "</a>", doc)
+                               .attr("id", "main-tab-button-" + tab.id)
+                               .addClass("main-tab")
+                               .click(function() {
+                                       enableTab(tab.id);
+                               })
+                               .mouseover(function(){ $j(this).addClass("hover") })
+                               .mouseout(function(){ $j(this).removeClass("hover") });
+       
+                       $j("#main-bar", doc).append($tabElement);
+
+                       tabElements[tab.id] = $tabElement;
+
+                       var $menu = $j("<div/>", doc);
+                       accordionElements[tab.id] = $menu;
+
+                       for (var j=0;j<tab.actions.length;j++) {
+                               (function() {
+
+                               var action = tab.actions[j];
+
+                               var $actionElement = $j("<div><h3><a href=\"#\">" + action.title + "</a></h3></div>", doc)
+
+                               $menu.append($actionElement);
+
+                               var $content = $j("<div></div>", doc)
+                                       .attr("id", "pixastic-action-tab-content-" + action.id)
+                                       .appendTo($actionElement);
+
+                               var controlOptions = [];
+
+                               action.previewEnabled = false;
+                               if (action.forcePreview)
+                                       action.previewEnabled = true;
+
+                               function togglePreview(enable, doAction) {
+                                       if (enable && !action.previewEnabled && doAction)
+                                               doAction(true);
+                                       if (!enable && action.previewEnabled)
+                                               resetDisplayCanvas();
+                       
+                                       action.previewEnabled = enable;
+                               }
+
+                               var reset = function() {
+                                       for (var i in controlOptions) {
+                                               if (controlOptions.hasOwnProperty(i)) {
+                                                       controlOptions[i].reset();
+                                               }
+                                       }
+                                       if (action.previewEnabled)
+                                               doAction(true);
+                               }
+                               var doAction = function(isPreview) {
+                                       var options = {};
+                                       for (var i in controlOptions) {
+                                               if (controlOptions.hasOwnProperty(i)) {
+                                                       options[i] = controlOptions[i].valueField.val();
+                                               }
+                                       }
+
+                                       var afteraction = function() {
+                                               if (action.onafteraction)
+                                                       action.onafteraction(action, isPreview);
+                                               if (!isPreview)
+                                                       resetDisplayCanvas();
+       
+                                               if (!isPreview && !action.forcePreview) {
+                                                       $j("#pixastic-input-preview-" + action.id, doc).attr("checked", false);
+                                                       togglePreview(false);
+                                                       reset();
+                                               }
+                                       }
+
+                                       if (isPreview) {
+                                               previewAction(action.id, options, afteraction);
+                                       } else {
+                                               applyAction(action.id, options, afteraction);
+                                       }
+
+                               }
+
+                               var hadInputs = false;
+
+                               if (action.controls) {
+                                       var onChange = function() {};
+                                       if (action.isAction && action.preview) {
+                                               onChange = function() {
+                                                       if (action.previewEnabled)
+                                                               doAction(true)
+                                               };
+                                       }
+
+                                       for (var k=0;k<action.controls.length;k++) {
+                                               var control = action.controls[k];
+                                               if (typeof control.defaultValue != "function") {
+                                                       (function(){
+                                                       var defVal = control.defaultValue;
+                                                       control.defaultValue = function() {
+                                                               return defVal;
+                                                       }
+                                                       })();
+                                               }
+                                               var controlId = action.id + "-" + control.option;
+
+                                               if (control.type != "output")
+                                                       hadInputs = true;
+
+                                               switch (control.type) {
+                                                       case "number" :
+                                                               switch (control.ui) {
+                                                                       case "slider" : 
+                                                                               var slider = PixasticEditor.UI.makeSlider(
+                                                                                       control.label, controlId, 
+                                                                                       control.range[0], control.range[1], control.step, control.defaultValue, onChange
+                                                                               );
+               
+                                                                               slider.container.appendTo($content);
+                                                                               controlOptions[control.option] = slider;
+                                                                               break;
+                                                                       case "text" : 
+                                                                               var text = PixasticEditor.UI.makeNumericInput(
+                                                                                       control.label, control.labelRight, controlId, 
+                                                                                       control.range[0], control.range[1], control.step, control.defaultValue, onChange
+                                                                               );
+                                                                               text.container.appendTo($content);
+                                                                               controlOptions[control.option] = text;
+                                                                               break;
+                                                               }
+                                                               break;
+                                                       case "boolean" :
+                                                               switch (control.ui) {
+                                                                       case "checkbox" : 
+                                                                               var checkbox = PixasticEditor.UI.makeCheckbox(
+                                                                                       control.label, controlId, control.defaultValue, onChange
+                                                                               );
+               
+                                                                               checkbox.container.appendTo($content);
+                                                                               controlOptions[control.option] = checkbox;
+                                                                               break;
+                                                               }
+                                                       case "string" :
+                                                               switch (control.ui) {
+                                                                       case "select" : 
+                                                                               var select = PixasticEditor.UI.makeSelect(
+                                                                                       control.label, controlId, control.values, control.defaultValue, onChange
+                                                                               );
+               
+                                                                               select.container.appendTo($content);
+                                                                               controlOptions[control.option] = select;
+                                                                               break;
+                                                               }
+                                                               break;
+                                                       case "output" :
+                                                               var outputText = $j("<div></div>", doc)
+                                                                       .addClass("ui-action-output")
+                                                                       .html(control.content)
+                                                                       .appendTo($content);
+                                                               break;
+                                               }
+                                       }
+                               }
+
+                               if (action.isAction) {
+
+                                       var $applyButton = PixasticEditor.UI.makeButton("Apply")
+                                               .addClass("pixastic-option-button-apply")
+                                               .click(function() {doAction();});
+
+                                       $content.append($applyButton);
+
+                                       if (hadInputs) {
+                                               var $resetButton = PixasticEditor.UI.makeButton("Reset")
+                                                       .addClass("pixastic-option-button-reset")
+                                                       .click(reset);
+       
+                                               $content.append($resetButton)
+                                       }
+
+                                       if (action.preview && !action.forcePreview) {
+                                               var $checkctr = $j("<div></div>", doc)
+                                                       .addClass("ui-checkbox-container")
+                                                       .addClass("ui-preview-checkbox-container");
+
+                                               var $label = $j("<label></label>", doc)
+                                                       .addClass("ui-checkbox-label")
+                                                       .attr("for", "pixastic-input-preview-" + action.id)
+                                                       .html("Preview:")
+                                                       .appendTo($checkctr);
+
+                                               var $checkbox = $j("<input type=\"checkbox\"></input>", doc)
+                                                       .addClass("ui-checkbox")
+                                                       .attr("id", "pixastic-input-preview-" + action.id)
+                                                       .appendTo($checkctr)
+                                                       .change(function() {
+                                                               togglePreview(this.checked, doAction)
+                                                       });
+
+                                               $content.append($checkctr);
+
+                                               $content.data("previewCheckbox", $checkbox);
+                                       }
+
+                               }
+
+
+                               if (typeof action.content == "function") {
+                                       action.content($content);
+                               }
+
+                               // stupid hack to make it possible to get $content in change event (below)
+                               $j("<span></span>", doc).appendTo($content);
+
+                               $content.data("controlOptions", controlOptions);
+                               $content.data("onactivate", action.onactivate);
+                               $content.data("ondeactivate", action.ondeactivate);
+                               $content.data("onoverlayupdate", action.onoverlayupdate);
+                               $content.data("accordionindex", j);
+                               $content.data("uidesc", action);
+
+                               })();
+                       }
+       
+                       $j("#action-bar", doc).append($menu);
+
+                       $menu.hide().accordion({
+                               header: "h3",
+                               autoHeight : false,
+                               collapsible : true,
+                               active: -1
+                       })
+                       .bind("accordionchange", 
+                               function(event, ui) {
+                                       resetDisplayCanvas();
+
+                                       // oldContent / newContent are arrays of whatever elements are present in the content area
+                                       // We need the parent element (the one holding the content) but if there is no content, how do we get it?
+                                       // fixed above by always appending a <span> but that's ugly and needs to be done in some other way
+                                       if (ui.oldContent.get(0)) {
+                                               var $parent = $j(ui.oldContent.get(0).parentNode);
+                                               if ($parent.data("ondeactivate")) {
+                                                       $parent.data("ondeactivate")();
+                                               }
+                                       }
+                                       $activeTabContent = ui.newContent;
+
+                                       if (ui.newContent.get(0)) {
+                                               var $parent = $j(ui.newContent.get(0).parentNode);
+                                               if ($parent.data("previewCheckbox"))
+                                                       $parent.data("previewCheckbox").attr("checked", false);
+                                               $parent.data("uidesc").previewEnabled = false;
+                                               if ($parent.data("uidesc").forcePreview)
+                                                       $parent.data("uidesc").previewEnabled = true;
+
+                                               var controlOptions = $parent.data("controlOptions");
+                                               for (var i in controlOptions) {
+                                                       if (controlOptions.hasOwnProperty(i)) {
+                                                               controlOptions[i].reset();
+                                                       }
+                                               }
+                                               if ($parent.data("onactivate")) {
+                                                       $parent.data("onactivate")();
+                                               }
+                                       }
+                                       updateDisplayCanvas();
+
+                               }
+                       );
+
+       
+                       })();
+               }
+
+               $j(window).bind("resize", onwindowresize);
+       }
+
+       function showLoadingScreen() {
+               if ($loadingScreen) {
+                       $loadingScreen.show();
+                       return;
+               }
+               $loadingScreen = $j("<div id=\"loading-screen\" />")
+               var $ctr = $j("<div id=\"loading-screen-cell\" />");
+               $j("<div />")
+                       .addClass("spinner")
+                       .appendTo($ctr);
+               $loadingScreen.append($ctr);
+               $loadingScreen.appendTo("body");
+       }
+
+       function hideLoadingScreen() {
+               setTimeout(function() {
+                       $loadingScreen.hide();
+               }, 1);
+       }
+
+       var oldScrollLeft;
+       var oldScrollTop;
+       var oldOverflow;
+
+       // fire it up
+       function init(callback) {
+               isRunning = true;
+
+               showLoadingScreen();
+
+               oldScrollLeft = document.body.scrollLeft;
+               oldScrollTop = document.body.scrollTop;
+               oldOverflow = document.body.style.overflow;
+
+               document.body.scrollLeft = 0;
+               document.body.scrollTop = 0;
+               document.body.style.overflow = "hidden";
+
+               $frame = $j("<iframe />");
+               $frame.hide();
+               $frame.css({
+                       position : "absolute",
+                       left : document.body.scrollLeft + "px",
+                       top : document.body.scrollTop + "px",
+                       width : "100%",
+                       height : "100%",
+                       zIndex : "11"
+               });
+               $frame.load(function(){
+                       doc = $frame.get(0).contentDocument;
+
+                       buildEditor();
+                       callback();
+                       $frame.show();
+                       hideLoadingScreen();
+                       setTimeout(function(){
+                               updateDisplayCanvas();
+                       },10);
+               });
+               $frame.appendTo("body");
+       }
+
+       // unload the editor, remove all elements added to the page and restore whatever properties we messed with
+       function unload() {
+               $j(window).unbind("resize", onwindowresize);
+               $frame.hide();
+               $editor.hide();
+               $editor.remove();
+               $frame.remove();
+
+               document.body.scrollLeft = oldScrollLeft;
+               document.body.scrollTop = oldScrollTop;
+               document.body.style.overflow = oldOverflow;
+
+               isRunning = false;
+       }
+
+
+       // resets the display canvas (clears the canvas and repaints the current state)
+       // then updates display and overlay
+       function resetDisplayCanvas() {
+               if (!($displayCanvas && $displayCanvas.get))    throw new Error(errorDialog("$displayCanvas doesn't exist"));
+               if (!($imageCanvas && $imageCanvas.get))        throw new Error(errorDialog("$imageCanvas doesn't exist"));
+
+               var display = $displayCanvas.get(0);
+               var image = $imageCanvas.get(0);
+
+               if (!display)   throw new Error(errorDialog("resetDisplayCanvas(): No elements in $displayCanvas"));
+               if (!image)     throw new Error(errorDialog("resetDisplayCanvas(): No elements in $imageCanvas"));
+
+               display.width = imageWidth;
+               display.height = imageHeight;
+               display.getContext("2d").drawImage( image, 0, 0 );
+
+               updateDisplayCanvas();
+               updateOverlay();
+       }
+
+       // updates the display by resetting the height and margin of the image container
+       // this is mainly to keep vertical centering
+       function updateDisplayCanvas() {
+               var $imageCtr = $j("#image-container", doc);
+               var $editArea = $j("#image-area", doc);
+
+               if (!$imageCtr.get(0))          throw new Error(errorDialog("updateDisplayCanvas(): $imageCtr doesn't exist"));
+               if (!$displayCanvas.get(0))     throw new Error(errorDialog("updateDisplayCanvas(): $displayCanvas doesn't exist"));
+               if (!$editArea.get(0))          throw new Error(errorDialog("updateDisplayCanvas(): $editArea doesn't exist"));
+
+               var h2 = $displayCanvas.get(0).height;
+               var h1 = $j("#image-area", doc).height();
+               var m = Math.max(0, (h1 - h2) / 2);
+               $imageCtr.height(h2);
+               $imageCtr.css("marginTop", m);
+       }
+
+       // basically the same as updateDisplayCanvas but for the image overlay
+       function updateOverlay() {
+               var $overlay = $j("#image-overlay-container", doc);
+               var $imagectr = $j("#image-container", doc);
+               $overlay.height($imagectr.height());
+               $overlay.css("marginTop", $imagectr.css("marginTop"));
+
+               if ($activeTabContent && $activeTabContent.get(0)) {
+                       var $tabContent = $j($activeTabContent.get(0).parentNode);
+                       if (typeof $tabContent.data("onoverlayupdate") == "function")
+                               $tabContent.data("onoverlayupdate")();
+               }
+       }
+
+       var imageIsLoading = false;
+       var originalImageElement;
+       var $tmpImg;
+
+       function loadImage(imgEl) {
+               if (imageIsLoading) 
+                       return;
+
+               imageIsLoading = true;
+
+               originalImageElement = imgEl;
+
+               $imageCanvas = $j("<canvas />", doc);
+               imageCtx = $imageCanvas.get(0).getContext("2d");
+
+               imageWidth = 0;
+               imageHeight = 0;
+               $imageCanvas.attr("width", 0);
+               $imageCanvas.attr("height", 0);
+
+               if (imgEl.tagName.toLowerCase() == "img" && !imgEl._pixasticCanvas) {
+                       var onload = function(el) {
+                               imageWidth = el.offsetWidth;
+                               imageHeight = el.offsetHeight;
+                               $imageCanvas.attr("width", imageWidth);
+                               $imageCanvas.attr("height", imageHeight);
+                               imageCtx.drawImage(el,0,0);
+                               $tmpImg.remove();
+                               imageIsLoading = false;
+                               enableTab("reshape");
+                               setTimeout(function() {
+                                       resetDisplayCanvas();
+                               }, 10);
+                       }
+                       $tmpImg = $j("<img />", doc)
+                               .css("position", "absolute")
+                               .css("left", "-9999px")
+                               .css("top", "-9999px")
+                               .appendTo("body")
+                               .load(function(){onload(this);})
+                               .error(function(){
+                                       throw new Error("Could not load temporary copy image. Is provided image valid?");
+                                       unload();
+                               })
+                               .attr("src", imgEl.src);
+                               if ($tmpImg.attr("complete")) {
+                                       onload($tmpImg.get(0));
+                               }
+               } else {
+                       var $canvas = imgEl._pixasticCanvas || imgEl;
+                       imageWidth = $canvas.attr("width");
+                       imageHeight = $canvas.attr("height");
+                       $imageCanvas.attr("width", imageWidth);
+                       $imageCanvas.attr("height", imageHeight);
+                       imageCtx.drawImage($canvas.get(0), 0, 0);
+                       imageIsLoading = false;
+                       enableTab("reshape");
+                       resetDisplayCanvas();
+               }
+       }
+
+       // return public interface
+       return {
+               /*
+               // don't call. For now we must load the image immediately via load()
+               loadImage : function(imgEl) {
+                       if (!isRunning) return false;
+                       loadImage(imgEl);
+               },
+               */
+               saveToPage : function() {
+                       if (!isRunning) throw new Error("PixasticEditor::saveToPage(): Editor is not running");
+
+                       var $canvas = PixasticEditor.getImageCanvas();
+                       var img = PixasticEditor.getOriginalImage();
+                       if (img.tagName.toLowerCase() == "canvas") {
+                               img.width = $canvas.attr("width");
+                               img.height = $canvas.attr("height");
+                               img.getContext("2d").drawImage($canvas.get(0), 0, 0);
+                       } else {
+                               img.src = PixasticEditor.getDataURI();
+                       }
+                       img._pixasticCanvas = PixasticEditor.getImageCanvas();
+               },
+               load : function(img, customBaseUrl) {
+                       if (isRunning) return false;
+
+                       if (!img)
+                               throw new Error("Must be called with an image or canvas as its first argument", "PixasticEditor::load")
+
+                       $ = PixasticEditor.jQuery;
+
+                       baseUrl = customBaseUrl || "http://www.pixastic.com/editor-test/";
+
+                       init(function() {
+                               if (img && img.tagName.toLowerCase() == "img" || img.tagName.toLowerCase() == "canvas") {
+                                       loadImage(img);
+                               }
+                       });
+               },
+
+               unload : function() {
+                       if (!isRunning) throw new Error("PixasticEditor::unload(): Editor is not running");
+                       unload();
+               },
+
+               getDocument : function() {
+                       if (!isRunning) throw new Error("PixasticEditor::getDocument(): Editor is not running");
+
+                       return doc;
+               },
+
+               validSaveFormats : function() {
+                       return saveFormats;
+               },
+
+               getOriginalImage : function() {
+                       if (!isRunning) throw new Error("PixasticEditor::getOriginalImage(): Editor is not running");
+                       return originalImageElement;
+               },
+
+               getDataURI : function(mime) {
+                       if (!isRunning) throw new Error("PixasticEditor::getDataURI(): Editor is not running");
+
+                       if (!($imageCanvas && $imageCanvas.get && $imageCanvas.get(0)))
+                               throw new Error(errorDialog("$imageCanvas doesn't exist", "getImageCanvas"));
+
+                       return $imageCanvas.get(0).toDataURL(mime||"image/png");
+               },
+
+               getImageCanvas : function() {
+                       if (!isRunning) throw new Error("PixasticEditor::getImageCanvas(): Editor is not running");
+
+                       if (!($imageCanvas && $imageCanvas.get && $imageCanvas.get(0)))
+                               throw new Error(errorDialog("$imageCanvas doesn't exist", "getImageCanvas"));
+
+                       return $imageCanvas;
+               },
+               getOverlay : function() {
+                       if (!isRunning) throw new Error("PixasticEditor::getOverlay(): Editor is not running");
+
+                       return $j("#image-overlay", doc);
+               },
+               getDisplayCanvas : function() {
+                       if (!isRunning) throw new Error("PixasticEditor::getDisplayCanvas(): Editor is not running");
+
+                       if (!($displayCanvas && $displayCanvas.get && $displayCanvas.get(0)))
+                               throw new Error(errorDialog("$displayCanvas doesn't exist", "getDisplayCanvas"));
+                       return $displayCanvas;
+               },
+               getDisplayWidth : function() {
+                       if (!isRunning) throw new Error("PixasticEditor::getDisplayWidth(): Editor is not running");
+
+                       return displayWidth;
+               },
+               getDisplayHeight : function() {
+                       if (!isRunning) throw new Error("PixasticEditor::getDisplayHeight(): Editor is not running");
+
+                       return displayHeight;
+               },
+               getImageWidth : function() {
+                       if (!isRunning) throw new Error("PixasticEditor::getImageWidth(): Editor is not running");
+
+                       return imageWidth;
+               },
+               getImageHeight : function() {
+                       if (!isRunning) throw new Error("PixasticEditor::getImageHeight(): Editor is not running");
+
+                       return imageHeight;
+               },
+               errorDialog : function() {
+                       if (!isRunning) throw new Error("PixasticEditor::errorDialog(): Editor is not running");
+
+                       return errorDialog.apply(null, arguments);
+               }
+       }
+
+})();
\ No newline at end of file
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/pixastic-editor/pixastic.all.js b/js2/mwEmbed/libClipEdit/pixastic-lib/pixastic-editor/pixastic.all.js
new file mode 100644 (file)
index 0000000..bee153a
--- /dev/null
@@ -0,0 +1,3169 @@
+/*
+ * Pixastic Lib - Core Functions - v0.1.3
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+var Pixastic = (function() {
+
+
+       function addEvent(el, event, handler) {
+               if (el.addEventListener)
+                       el.addEventListener(event, handler, false); 
+               else if (el.attachEvent)
+                       el.attachEvent("on" + event, handler); 
+       }
+
+       function onready(handler) {
+               var handlerDone = false;
+               var execHandler = function() {
+                       if (!handlerDone) {
+                               handlerDone = true;
+                               handler();
+                       }
+               }
+               document.write("<"+"script defer src=\"//:\" id=\"__onload_ie_sumbox__\"></"+"script>");
+               var script = document.getElementById("__onload_ie_sumbox__");
+               script.onreadystatechange = function() {
+                       if (script.readyState == "complete") {
+                               script.parentNode.removeChild(script);
+                               execHandler();
+                       }
+               }
+               if (document.addEventListener)
+                       document.addEventListener("DOMContentLoaded", execHandler, false); 
+               addEvent(window, "load", execHandler);
+       }
+
+       function init() {
+               if (!Pixastic.parseOnLoad) return;
+               var imgEls = getElementsByClass("pixastic", null, "img");
+               var canvasEls = getElementsByClass("pixastic", null, "canvas");
+               var elements = imgEls.concat(canvasEls);
+               for (var i=0;i<elements.length;i++) {
+                       (function() {
+
+                       var el = elements[i];
+                       var actions = [];
+                       var classes = el.className.split(" ");
+                       for (var c=0;c<classes.length;c++) {
+                               var cls = classes[c];
+                               if (cls.substring(0,9) == "pixastic-") {
+                                       var actionName = cls.substring(9);
+                                       if (actionName != "")
+                                               actions.push(actionName);
+                               }
+                       }
+                       if (actions.length) {
+                               if (el.tagName.toLowerCase() == "img") {
+                                       var dataImg = new Image();
+                                       dataImg.src = el.src;
+                                       if (dataImg.complete) {
+                                               for (var a=0;a<actions.length;a++) {
+                                                       var res = Pixastic.applyAction(el, el, actions[a], null);
+                                                       if (res) 
+                                                               el = res;
+                                               }
+                                       } else {
+                                               dataImg.onload = function() {
+                                                       for (var a=0;a<actions.length;a++) {
+                                                               var res = Pixastic.applyAction(el, el, actions[a], null)
+                                                               if (res) 
+                                                                       el = res;
+                                                       }
+                                               }
+                                       }
+                               } else {
+                                       setTimeout(function() {
+                                               for (var a=0;a<actions.length;a++) {
+                                                       var res = Pixastic.applyAction(
+                                                               el, el, actions[a], null
+                                                       );
+                                                       if (res) 
+                                                               el = res;
+                                               }
+                                       },1);
+                               }
+                       }
+
+                       })();
+               }
+       }
+
+//     if (typeof pixastic_no_onready == "undefined") // yuck.
+//             onready(init);
+
+       // getElementsByClass by Dustin Diaz, http://www.dustindiaz.com/getelementsbyclass/
+       function getElementsByClass(searchClass,node,tag) {
+               var classElements = new Array();
+               if ( node == null )
+                       node = document;
+               if ( tag == null )
+                       tag = '*';
+
+               var els = node.getElementsByTagName(tag);
+               var elsLen = els.length;
+               var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
+               for (i = 0, j = 0; i < elsLen; i++) {
+                       if ( pattern.test(els[i].className) ) {
+                               classElements[j] = els[i];
+                               j++;
+                       }
+               }
+               return classElements;
+       }
+
+       var debugElement;
+
+       function writeDebug(text, level) {
+               if (!Pixastic.debug) return;
+               try {
+                       switch (level) {
+                               case "warn" : 
+                                       console.warn("Pixastic:", text);
+                                       break;
+                               case "error" :
+                                       console.error("Pixastic:", text);
+                                       break;
+                               default:
+                                       console.log("Pixastic:", text);
+                       }
+               } catch(e) {
+               }
+               if (!debugElement) {
+                       
+               }
+       }
+
+
+       return {
+
+               parseOnLoad : false,
+
+               debug : false,
+               
+               applyAction : function(img, dataImg, actionName, options) {
+
+                       options = options || {};
+
+                       var imageIsCanvas = (img.tagName.toLowerCase() == "canvas");
+                       if (imageIsCanvas && Pixastic.Client.isIE()) {
+                               if (Pixastic.debug) writeDebug("Tried to process a canvas element but browser is IE.");
+                               return false;
+                       }
+
+                       var canvas, ctx;
+                       if (Pixastic.Client.hasCanvas()) {
+                               canvas = document.createElement("canvas");
+                               ctx = canvas.getContext("2d");
+                       }
+
+                       var w = parseInt(img.offsetWidth);
+                       var h = parseInt(img.offsetHeight);
+
+                       if (imageIsCanvas) {
+                               w = img.width;
+                               h = img.height;
+                       }
+
+                       if (actionName.indexOf("(") > -1) {
+                               var tmp = actionName;
+                               actionName = tmp.substr(0, tmp.indexOf("("));
+                               var arg = tmp.match(/\((.*?)\)/);
+                               if (arg[1]) {
+                                       arg = arg[1].split(";");
+                                       for (var a=0;a<arg.length;a++) {
+                                               thisArg = arg[a].split("=");
+                                               if (thisArg.length == 2) {
+                                                       if (thisArg[0] == "rect") {
+                                                               var rectVal = thisArg[1].split(",");
+                                                               options[thisArg[0]] = {
+                                                                       left : parseInt(rectVal[0],10)||0,
+                                                                       top : parseInt(rectVal[1],10)||0,
+                                                                       width : parseInt(rectVal[2],10)||0,
+                                                                       height : parseInt(rectVal[3],10)||0
+                                                               }
+                                                       } else {
+                                                               options[thisArg[0]] = thisArg[1];
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+
+                       if (!options.rect) {
+                               options.rect = {
+                                       left : 0, top : 0, width : w, height : h
+                               };
+                       }
+                       var validAction = false;
+                       if (Pixastic.Actions[actionName] && typeof Pixastic.Actions[actionName].process == "function") {
+                               validAction = true;
+                       }
+                       if (!validAction) {
+                               if (Pixastic.debug) writeDebug("Invalid action \"" + actionName + "\". Maybe file not included?");
+                               return false;
+                       }
+                       if (!Pixastic.Actions[actionName].checkSupport()) {
+                               if (Pixastic.debug) writeDebug("Action \"" + actionName + "\" not supported by this browser.");
+                               return false;
+                       }
+
+                       if (Pixastic.Client.hasCanvas()) {
+                               canvas.width = w;
+                               canvas.height = h;
+                               canvas.style.width = w+"px";
+                               canvas.style.height = h+"px";
+                               ctx.drawImage(dataImg,0,0,w,h);
+
+                               if (!img.__pixastic_org_image) {
+                                       canvas.__pixastic_org_image = img;
+                                       canvas.__pixastic_org_width = w;
+                                       canvas.__pixastic_org_height = h;
+                               } else {
+                                       canvas.__pixastic_org_image = img.__pixastic_org_image;
+                                       canvas.__pixastic_org_width = img.__pixastic_org_width;
+                                       canvas.__pixastic_org_height = img.__pixastic_org_height;
+                               }
+
+                       } else if (Pixastic.Client.isIE() && typeof img.__pixastic_org_style == "undefined") {
+                               img.__pixastic_org_style = img.style.cssText;
+                       }
+
+                       var params = {
+                               image : img,
+                               canvas : canvas,
+                               width : w,
+                               height : h,
+                               useData : true,
+                               options : options
+                       }
+
+                       // Ok, let's do it!
+
+                       var res = Pixastic.Actions[actionName].process(params);
+
+                       if (!res) {
+                               return false;
+                       }
+
+                       if (Pixastic.Client.hasCanvas()) {
+                               if (params.useData) {
+                                       if (Pixastic.Client.hasCanvasImageData()) {
+                                               canvas.getContext("2d").putImageData(params.canvasData, options.rect.left, options.rect.top);
+
+                                               // Opera doesn't seem to update the canvas until we draw something on it, lets draw a 0x0 rectangle.
+                                               canvas.getContext("2d").fillRect(0,0,0,0);
+                                       }
+                               }
+
+                               if (!options.leaveDOM) {
+                                       // copy properties and stuff from the source image
+                                       canvas.title = img.title;
+                                       canvas.imgsrc = img.imgsrc;
+                                       if (!imageIsCanvas) canvas.alt  = img.alt;
+                                       if (!imageIsCanvas) canvas.imgsrc = img.src;
+                                       canvas.className = img.className;
+                                       canvas.style.cssText = img.style.cssText;
+                                       canvas.name = img.name;
+                                       canvas.tabIndex = img.tabIndex;
+                                       canvas.id = img.id;
+                                       if (img.parentNode && img.parentNode.replaceChild) {
+                                               img.parentNode.replaceChild(canvas, img);
+                                       }
+                               }
+
+                               options.resultCanvas = canvas;
+
+                               return canvas;
+                       }
+
+                       return img;
+               },
+
+               prepareData : function(params, getCopy) {
+                       var ctx = params.canvas.getContext("2d");
+                       var rect = params.options.rect;
+                       var dataDesc = ctx.getImageData(rect.left, rect.top, rect.width, rect.height);
+                       var data = dataDesc.data;
+                       if (!getCopy) params.canvasData = dataDesc;
+                       return data;
+               },
+
+               // load the image file
+               process : function(img, actionName, options, callback)
+               {
+                       if (img.tagName.toLowerCase() == "img") {
+                               var dataImg = new Image();
+                               dataImg.src = img.src;
+                               if (dataImg.complete) {
+                                       var res = Pixastic.applyAction(img, dataImg, actionName, options);
+                                       if (callback) callback(res);
+                                       return res;
+                               } else {
+                                       dataImg.onload = function() {
+                                               var res = Pixastic.applyAction(img, dataImg, actionName, options)
+                                               if (callback) callback(res);
+                                       }
+                               }
+                       }
+                       if (img.tagName.toLowerCase() == "canvas") {
+                               var res = Pixastic.applyAction(img, img, actionName, options);
+                               if (callback) callback(res);
+                               return res;
+                       }
+               },
+
+               revert : function(img) {
+                       if (Pixastic.Client.hasCanvas()) {
+                               if (img.tagName.toLowerCase() == "canvas" && img.__pixastic_org_image) {
+                                       img.width = img.__pixastic_org_width;
+                                       img.height = img.__pixastic_org_height;
+                                       img.getContext("2d").drawImage(img.__pixastic_org_image, 0, 0);
+
+                                       if (img.parentNode && img.parentNode.replaceChild) {
+                                               img.parentNode.replaceChild(img.__pixastic_org_image, img);
+                                       }
+
+                                       return img;
+                               }
+                       } else if (Pixastic.Client.isIE() && typeof img.__pixastic_org_style != "undefined") {
+                               img.style.cssText = img.__pixastic_org_style;
+                       }
+               },
+
+               Client : {
+                       hasCanvas : (function() {
+                               var c = document.createElement("canvas");
+                               var val = false;
+                               try {
+                                       val = !!((typeof c.getContext == "function") && c.getContext("2d"));
+                               } catch(e) {}
+                               return function() {
+                                       return val;
+                               }
+                       })(),
+
+                       hasCanvasImageData : (function() {
+                               var c = document.createElement("canvas");
+                               var val = false;
+                               var ctx;
+                               try {
+                                       if (typeof c.getContext == "function" && (ctx = c.getContext("2d"))) {
+                                               val = (typeof ctx.getImageData == "function");
+                                       }
+                               } catch(e) {}
+                               return function() {
+                                       return val;
+                               }
+                       })(),
+
+                       isIE : function() {
+                               return !!document.all && !!window.attachEvent && !window.opera;
+                       }
+               },
+
+               Actions : {}
+       }
+
+
+})();
+/*
+ * Pixastic Lib - jQuery plugin
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+if (typeof jQuery != "undefined" && jQuery && jQuery.fn) {
+       jQuery.fn.pixastic = function(action, options) {
+               var newElements = [];
+               this.each(
+                       function () {
+                               if (this.tagName.toLowerCase() == "img" && !this.complete) {
+                                       return;
+                               }
+                               var res = Pixastic.process(this, action, options);
+                               if (res) {
+                                       newElements.push(res);
+                               }
+                       }
+               );
+               if (newElements.length > 0)
+                       return jQuery(newElements);
+               else
+                       return this;
+       };
+
+};
+/*
+ * Pixastic Lib - Blend - v0.1.1
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.blend = {
+
+       process : function(params) {
+               var amount = parseFloat(params.options.amount);
+               var mode = (params.options.mode || "normal").toLowerCase();
+               var image = params.options.image;
+
+               amount = Math.max(0,Math.min(1,amount));
+
+               if (!image) return false;
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var rect = params.options.rect;
+                       var data = Pixastic.prepareData(params);
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       params.useData = false;
+
+                       var otherCanvas = document.createElement("canvas");
+                       otherCanvas.width = params.canvas.width;
+                       otherCanvas.height = params.canvas.height;
+                       var otherCtx = otherCanvas.getContext("2d");
+                       otherCtx.drawImage(image,0,0);
+
+                       var params2 = {canvas:otherCanvas,options:params.options};
+                       var data2 = Pixastic.prepareData(params2);
+                       var dataDesc2 = params2.canvasData;
+
+                       var p = w*h;
+                       var pix = p*4;
+                       var pix1, pix2;
+                       var r1, g1, b1;
+                       var r2, g2, b2;
+                       var r3, g3, b3;
+                       var r4, g4, b4;
+
+                       var dataChanged = false;
+
+                       switch (mode) {
+                               case "normal" : 
+                                       //while (p--) {
+                                       //      data2[pix-=4] = data2[pix];
+                                       //      data2[pix1=pix+1] = data2[pix1];
+                                       //      data2[pix2=pix+2] = data2[pix2];
+                                       //}
+                                       break;
+
+                               case "multiply" : 
+                                       while (p--) {
+                                               data2[pix-=4] = data[pix] * data2[pix] / 255;
+                                               data2[pix1=pix+1] = data[pix1] * data2[pix1] / 255;
+                                               data2[pix2=pix+2] = data[pix2] * data2[pix2] / 255;
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "lighten" : 
+                                       while (p--) {
+                                               if ((r1 = data[pix-=4]) > data2[pix])
+                                                       data2[pix] = r1;
+                                               if ((g1 = data[pix1=pix+1]) > data2[pix1])
+                                                       data2[pix1] = g1;
+                                               if ((b1 = data[pix2=pix+2]) > data2[pix2])
+                                                       data2[pix2] = b1;
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "darken" : 
+                                       while (p--) {
+                                               if ((r1 = data[pix-=4]) < data2[pix])
+                                                       data2[pix] = r1;
+                                               if ((g1 = data[pix1=pix+1]) < data2[pix1])
+                                                       data2[pix1] = g1;
+                                               if ((b1 = data[pix2=pix+2]) < data2[pix2])
+                                                       data2[pix2] = b1;
+
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "darkercolor" : 
+                                       while (p--) {
+                                               if (((r1 = data[pix-=4])*0.3+(g1 = data[pix1=pix+1])*0.59+(b1 = data[pix2=pix+2])*0.11) <= (data2[pix]*0.3+data2[pix1]*0.59+data2[pix2]*0.11)) {
+                                                       data2[pix] = r1;
+                                                       data2[pix1] = g1;
+                                                       data2[pix2] = b1;
+                                               }
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "lightercolor" : 
+                                       while (p--) {
+                                               if (((r1 = data[pix-=4])*0.3+(g1 = data[pix1=pix+1])*0.59+(b1 = data[pix2=pix+2])*0.11) > (data2[pix]*0.3+data2[pix1]*0.59+data2[pix2]*0.11)) {
+                                                       data2[pix] = r1;
+                                                       data2[pix1] = g1;
+                                                       data2[pix2] = b1;
+                                               }
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "lineardodge" : 
+                                       otherCtx.globalCompositeOperation = "source-over";
+                                       otherCtx.drawImage(params.canvas, 0, 0);
+                                       otherCtx.globalCompositeOperation = "lighter";
+                                       otherCtx.drawImage(image, 0, 0);
+
+                                       /*
+                                       while (p--) {
+                                               if ((r3 = data[pix-=4] + data2[pix]) > 255)
+                                                       data2[pix] = 255;
+                                               else
+                                                       data2[pix] = r3;
+                                               if ((g3 = data[pix1=pix+1] + data2[pix1]) > 255)
+                                                       data2[pix1] = 255;
+                                               else
+                                                       data2[pix1] = g3;
+                                               if ((b3 = data[pix2=pix+2] + data2[pix2]) > 255)
+                                                       data2[pix2] = 255;
+                                               else
+                                                       data2[pix2] = b3;
+                                       }
+                                       dataChanged = true;
+                                       */
+
+                                       break;
+
+                               case "linearburn" : 
+                                       while (p--) {
+                                               if ((r3 = data[pix-=4] + data2[pix]) < 255)
+                                                       data2[pix] = 0;
+                                               else
+                                                       data2[pix] = (r3 - 255);
+                                               if ((g3 = data[pix1=pix+1] + data2[pix1]) < 255)
+                                                       data2[pix1] = 0;
+                                               else
+                                                       data2[pix1] = (g3 - 255);
+                                               if ((b3 = data[pix2=pix+2] + data2[pix2]) < 255)
+                                                       data2[pix2] = 0;
+                                               else
+                                                       data2[pix2] = (b3 - 255);
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "difference" : 
+                                       while (p--) {
+                                               if ((r3 = data[pix-=4] - data2[pix]) < 0)
+                                                       data2[pix] = -r3;
+                                               else
+                                                       data2[pix] = r3;
+                                               if ((g3 = data[pix1=pix+1] - data2[pix1]) < 0)
+                                                       data2[pix1] = -g3;
+                                               else
+                                                       data2[pix1] = g3;
+                                               if ((b3 = data[pix2=pix+2] - data2[pix2]) < 0)
+                                                       data2[pix2] = -b3;
+                                               else
+                                                       data2[pix2] = b3;
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "screen" : 
+                                       while (p--) {
+                                               data2[pix-=4] = (255 - ( ((255-data2[pix])*(255-data[pix])) >> 8));
+                                               data2[pix1=pix+1] = (255 - ( ((255-data2[pix1])*(255-data[pix1])) >> 8));
+                                               data2[pix2=pix+2] = (255 - ( ((255-data2[pix2])*(255-data[pix2])) >> 8));
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "exclusion" : 
+                                       var div_2_255 = 2 / 255;
+                                       while (p--) {
+                                               data2[pix-=4] = (r1 = data[pix]) - (r1 * div_2_255 - 1) * data2[pix];
+                                               data2[pix1=pix+1] = (g1 = data[pix1]) - (g1 * div_2_255 - 1) * data2[pix1];
+                                               data2[pix2=pix+2] = (b1 = data[pix2]) - (b1 * div_2_255 - 1) * data2[pix2];
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "overlay" : 
+                                       var div_2_255 = 2 / 255;
+                                       while (p--) {
+                                               if ((r1 = data[pix-=4]) < 128)
+                                                       data2[pix] = data2[pix]*r1*div_2_255;
+                                               else
+                                                       data2[pix] = 255 - (255-data2[pix])*(255-r1)*div_2_255;
+
+                                               if ((g1 = data[pix1=pix+1]) < 128)
+                                                       data2[pix1] = data2[pix1]*g1*div_2_255;
+                                               else
+                                                       data2[pix1] = 255 - (255-data2[pix1])*(255-g1)*div_2_255;
+
+                                               if ((b1 = data[pix2=pix+2]) < 128)
+                                                       data2[pix2] = data2[pix2]*b1*div_2_255;
+                                               else
+                                                       data2[pix2] = 255 - (255-data2[pix2])*(255-b1)*div_2_255;
+
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "softlight" : 
+                                       var div_2_255 = 2 / 255;
+                                       while (p--) {
+                                               if ((r1 = data[pix-=4]) < 128)
+                                                       data2[pix] = ((data2[pix]>>1) + 64) * r1 * div_2_255;
+                                               else
+                                                       data2[pix] = 255 - (191 - (data2[pix]>>1)) * (255-r1) * div_2_255;
+
+                                               if ((g1 = data[pix1=pix+1]) < 128)
+                                                       data2[pix1] = ((data2[pix1]>>1)+64) * g1 * div_2_255;
+                                               else
+                                                       data2[pix1] = 255 - (191 - (data2[pix1]>>1)) * (255-g1) * div_2_255;
+
+                                               if ((b1 = data[pix2=pix+2]) < 128)
+                                                       data2[pix2] = ((data2[pix2]>>1)+64) * b1 * div_2_255;
+                                               else
+                                                       data2[pix2] = 255 - (191 - (data2[pix2]>>1)) * (255-b1) * div_2_255;
+
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "hardlight" : 
+                                       var div_2_255 = 2 / 255;
+                                       while (p--) {
+                                               if ((r2 = data2[pix-=4]) < 128)
+                                                       data2[pix] = data[pix] * r2 * div_2_255;
+                                               else
+                                                       data2[pix] = 255 - (255-data[pix]) * (255-r2) * div_2_255;
+
+                                               if ((g2 = data2[pix1=pix+1]) < 128)
+                                                       data2[pix1] = data[pix1] * g2 * div_2_255;
+                                               else
+                                                       data2[pix1] = 255 - (255-data[pix1]) * (255-g2) * div_2_255;
+
+                                               if ((b2 = data2[pix2=pix+2]) < 128)
+                                                       data2[pix2] = data[pix2] * b2 * div_2_255;
+                                               else
+                                                       data2[pix2] = 255 - (255-data[pix2]) * (255-b2) * div_2_255;
+
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "colordodge" : 
+                                       while (p--) {
+                                               if ((r3 = (data[pix-=4]<<8)/(255-(r2 = data2[pix]))) > 255 || r2 == 255)
+                                                       data2[pix] = 255;
+                                               else
+                                                       data2[pix] = r3;
+
+                                               if ((g3 = (data[pix1=pix+1]<<8)/(255-(g2 = data2[pix1]))) > 255 || g2 == 255)
+                                                       data2[pix1] = 255;
+                                               else
+                                                       data2[pix1] = g3;
+
+                                               if ((b3 = (data[pix2=pix+2]<<8)/(255-(b2 = data2[pix2]))) > 255 || b2 == 255)
+                                                       data2[pix2] = 255;
+                                               else
+                                                       data2[pix2] = b3;
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "colorburn" : 
+                                       while (p--) {
+                                               if ((r3 = 255-((255-data[pix-=4])<<8)/data2[pix]) < 0 || data2[pix] == 0)
+                                                       data2[pix] = 0;
+                                               else
+                                                       data2[pix] = r3;
+
+                                               if ((g3 = 255-((255-data[pix1=pix+1])<<8)/data2[pix1]) < 0 || data2[pix1] == 0)
+                                                       data2[pix1] = 0;
+                                               else
+                                                       data2[pix1] = g3;
+
+                                               if ((b3 = 255-((255-data[pix2=pix+2])<<8)/data2[pix2]) < 0 || data2[pix2] == 0)
+                                                       data2[pix2] = 0;
+                                               else
+                                                       data2[pix2] = b3;
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "linearlight" : 
+                                       while (p--) {
+                                               if ( ((r3 = 2*(r2=data2[pix-=4])+data[pix]-256) < 0) || (r2 < 128 && r3 < 0)) {
+                                                       data2[pix] = 0
+                                               } else {
+                                                       if (r3 > 255)
+                                                               data2[pix] = 255;
+                                                       else
+                                                               data2[pix] = r3;
+                                               }
+                                               if ( ((g3 = 2*(g2=data2[pix1=pix+1])+data[pix1]-256) < 0) || (g2 < 128 && g3 < 0)) {
+                                                       data2[pix1] = 0
+                                               } else {
+                                                       if (g3 > 255)
+                                                               data2[pix1] = 255;
+                                                       else
+                                                               data2[pix1] = g3;
+                                               }
+                                               if ( ((b3 = 2*(b2=data2[pix2=pix+2])+data[pix2]-256) < 0) || (b2 < 128 && b3 < 0)) {
+                                                       data2[pix2] = 0
+                                               } else {
+                                                       if (b3 > 255)
+                                                               data2[pix2] = 255;
+                                                       else
+                                                               data2[pix2] = b3;
+                                               }
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "vividlight" : 
+                                       while (p--) {
+                                               if ((r2=data2[pix-=4]) < 128) {
+                                                       if (r2) {
+                                                               if ((r3 = 255 - ((255-data[pix])<<8) / (2*r2)) < 0) 
+                                                                       data2[pix] = 0;
+                                                               else
+                                                                       data2[pix] = r3
+                                                       } else {
+                                                               data2[pix] = 0;
+                                                       }
+                                               } else if ((r3 = (r4=2*r2-256)) < 255) {
+                                                       if ((r3 = (data[pix]<<8)/(255-r4)) > 255) 
+                                                               data2[pix] = 255;
+                                                       else
+                                                               data2[pix] = r3;
+                                               } else {
+                                                       if (r3 < 0) 
+                                                               data2[pix] = 0;
+                                                       else
+                                                               data2[pix] = r3
+                                               }
+
+                                               if ((g2=data2[pix1=pix+1]) < 128) {
+                                                       if (g2) {
+                                                               if ((g3 = 255 - ((255-data[pix1])<<8) / (2*g2)) < 0) 
+                                                                       data2[pix1] = 0;
+                                                               else
+                                                                       data2[pix1] = g3;
+                                                       } else {
+                                                               data2[pix1] = 0;
+                                                       }
+                                               } else if ((g3 = (g4=2*g2-256)) < 255) {
+                                                       if ((g3 = (data[pix1]<<8)/(255-g4)) > 255)
+                                                               data2[pix1] = 255;
+                                                       else
+                                                               data2[pix1] = g3;
+                                               } else {
+                                                       if (g3 < 0) 
+                                                               data2[pix1] = 0;
+                                                       else
+                                                               data2[pix1] = g3;
+                                               }
+
+                                               if ((b2=data2[pix2=pix+2]) < 128) {
+                                                       if (b2) {
+                                                               if ((b3 = 255 - ((255-data[pix2])<<8) / (2*b2)) < 0) 
+                                                                       data2[pix2] = 0;
+                                                               else
+                                                                       data2[pix2] = b3;
+                                                       } else {
+                                                               data2[pix2] = 0;
+                                                       }
+                                               } else if ((b3 = (b4=2*b2-256)) < 255) {
+                                                       if ((b3 = (data[pix2]<<8)/(255-b4)) > 255) 
+                                                               data2[pix2] = 255;
+                                                       else
+                                                               data2[pix2] = b3;
+                                               } else {
+                                                       if (b3 < 0) 
+                                                               data2[pix2] = 0;
+                                                       else
+                                                               data2[pix2] = b3;
+                                               }
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "pinlight" : 
+                                       while (p--) {
+                                               if ((r2=data2[pix-=4]) < 128)
+                                                       if ((r1=data[pix]) < (r4=2*r2))
+                                                               data2[pix] = r1;
+                                                       else
+                                                               data2[pix] = r4;
+                                               else
+                                                       if ((r1=data[pix]) > (r4=2*r2-256))
+                                                               data2[pix] = r1;
+                                                       else
+                                                               data2[pix] = r4;
+
+                                               if ((g2=data2[pix1=pix+1]) < 128)
+                                                       if ((g1=data[pix1]) < (g4=2*g2))
+                                                               data2[pix1] = g1;
+                                                       else
+                                                               data2[pix1] = g4;
+                                               else
+                                                       if ((g1=data[pix1]) > (g4=2*g2-256))
+                                                               data2[pix1] = g1;
+                                                       else
+                                                               data2[pix1] = g4;
+
+                                               if ((r2=data2[pix2=pix+2]) < 128)
+                                                       if ((r1=data[pix2]) < (r4=2*r2))
+                                                               data2[pix2] = r1;
+                                                       else
+                                                               data2[pix2] = r4;
+                                               else
+                                                       if ((r1=data[pix2]) > (r4=2*r2-256))
+                                                               data2[pix2] = r1;
+                                                       else
+                                                               data2[pix2] = r4;
+                                       }
+                                       dataChanged = true;
+                                       break;
+
+                               case "hardmix" : 
+                                       while (p--) {
+                                               if ((r2 = data2[pix-=4]) < 128)
+                                                       if (255 - ((255-data[pix])<<8)/(2*r2) < 128 || r2 == 0)
+                                                               data2[pix] = 0;
+                                                       else
+                                                               data2[pix] = 255;
+                                               else if ((r4=2*r2-256) < 255 && (data[pix]<<8)/(255-r4) < 128)
+                                                       data2[pix] = 0;
+                                               else
+                                                       data2[pix] = 255;
+
+                                               if ((g2 = data2[pix1=pix+1]) < 128)
+                                                       if (255 - ((255-data[pix1])<<8)/(2*g2) < 128 || g2 == 0)
+                                                               data2[pix1] = 0;
+                                                       else
+                                                               data2[pix1] = 255;
+                                               else if ((g4=2*g2-256) < 255 && (data[pix1]<<8)/(255-g4) < 128)
+                                                       data2[pix1] = 0;
+                                               else
+                                                       data2[pix1] = 255;
+
+                                               if ((b2 = data2[pix2=pix+2]) < 128)
+                                                       if (255 - ((255-data[pix2])<<8)/(2*b2) < 128 || b2 == 0)
+                                                               data2[pix2] = 0;
+                                                       else
+                                                               data2[pix2] = 255;
+                                               else if ((b4=2*b2-256) < 255 && (data[pix2]<<8)/(255-b4) < 128)
+                                                       data2[pix2] = 0;
+                                               else
+                                                       data2[pix2] = 255;
+                                       }
+                                       dataChanged = true;
+                                       break;
+                       }
+
+                       if (dataChanged) 
+                               otherCtx.putImageData(dataDesc2,0,0);
+
+                       var ctx = params.canvas.getContext("2d");
+                       ctx.save();
+                       ctx.globalAlpha = amount;
+                       ctx.drawImage(
+                               otherCanvas,
+                               0,0,rect.width,rect.height,
+                               rect.left,rect.top,rect.width,rect.height
+                       );
+                       ctx.globalAlpha = 1;
+                       ctx.restore();
+
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}/*
+ * Pixastic Lib - Blur filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.blur = {
+       process : function(params) {
+
+               if (typeof params.options.fixMargin == "undefined")
+                       params.options.fixMargin = true;
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var dataCopy = Pixastic.prepareData(params, true)
+
+                       /*
+                       var kernel = [
+                               [0.5,   1,      0.5],
+                               [1,     2,      1],
+                               [0.5,   1,      0.5]
+                       ];
+                       */
+
+                       var kernel = [
+                               [0,     1,      0],
+                               [1,     2,      1],
+                               [0,     1,      0]
+                       ];
+
+                       var weight = 0;
+                       for (var i=0;i<3;i++) {
+                               for (var j=0;j<3;j++) {
+                                       weight += kernel[i][j];
+                               }
+                       }
+
+                       weight = 1 / (weight*2);
+
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+
+                               var prevY = (y == 1) ? 0 : y-2;
+                               var nextY = (y == h) ? y - 1 : y;
+
+                               var offsetYPrev = prevY*w*4;
+                               var offsetYNext = nextY*w*4;
+
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x*4-4);
+
+                                       var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
+                                       var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
+       
+                                       data[offset] = (
+                                               /*
+                                               dataCopy[offsetPrev - 4]
+                                               + dataCopy[offsetPrev+4] 
+                                               + dataCopy[offsetNext - 4]
+                                               + dataCopy[offsetNext+4]
+                                               + 
+                                               */
+                                               (dataCopy[offsetPrev]
+                                               + dataCopy[offset-4]
+                                               + dataCopy[offset+4]
+                                               + dataCopy[offsetNext])         * 2
+                                               + dataCopy[offset]              * 4
+                                               ) * weight;
+
+                                       data[offset+1] = (
+                                               /*
+                                               dataCopy[offsetPrev - 3]
+                                               + dataCopy[offsetPrev+5] 
+                                               + dataCopy[offsetNext - 3] 
+                                               + dataCopy[offsetNext+5]
+                                               + 
+                                               */
+                                               (dataCopy[offsetPrev+1]
+                                               + dataCopy[offset-3]
+                                               + dataCopy[offset+5]
+                                               + dataCopy[offsetNext+1])       * 2
+                                               + dataCopy[offset+1]            * 4
+                                               ) * weight;
+
+                                       data[offset+2] = (
+                                               /*
+                                               dataCopy[offsetPrev - 2] 
+                                               + dataCopy[offsetPrev+6] 
+                                               + dataCopy[offsetNext - 2] 
+                                               + dataCopy[offsetNext+6]
+                                               + 
+                                               */
+                                               (dataCopy[offsetPrev+2]
+                                               + dataCopy[offset-2]
+                                               + dataCopy[offset+6]
+                                               + dataCopy[offsetNext+2])       * 2
+                                               + dataCopy[offset+2]            * 4
+                                               ) * weight;
+
+                               } while (--x);
+                       } while (--y);
+
+                       return true;
+
+               } else if (Pixastic.Client.isIE()) {
+                       params.image.style.filter += " progid:DXImageTransform.Microsoft.Blur(pixelradius=1.5)";
+
+                       if (params.options.fixMargin) {
+                               params.image.style.marginLeft = (parseInt(params.image.style.marginLeft,10)||0) - 2 + "px";
+                               params.image.style.marginTop = (parseInt(params.image.style.marginTop,10)||0) - 2 + "px";
+                       }
+
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
+       }
+}/*
+ * Pixastic Lib - Blur Fast - v0.1.1
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.blurfast = {
+       process : function(params) {
+
+               var amount = parseFloat(params.options.amount)||0;
+               var clear = !!(params.options.clear && params.options.clear != "false");
+
+               amount = Math.max(0,Math.min(5,amount));
+
+               if (Pixastic.Client.hasCanvas()) {
+                       var rect = params.options.rect;
+
+                       var ctx = params.canvas.getContext("2d");
+                       ctx.save();
+                       ctx.beginPath();
+                       ctx.rect(rect.left, rect.top, rect.width, rect.height);
+                       ctx.clip();
+
+                       var scale = 2;
+                       var smallWidth = Math.round(params.width / scale);
+                       var smallHeight = Math.round(params.height / scale);
+
+                       var copy = document.createElement("canvas");
+                       copy.width = smallWidth;
+                       copy.height = smallHeight;
+
+                       var clear = false;
+                       var steps = Math.round(amount * 20);
+
+                       var copyCtx = copy.getContext("2d");
+                       for (var i=0;i<steps;i++) {
+                               var scaledWidth = Math.max(1,Math.round(smallWidth - i));
+                               var scaledHeight = Math.max(1,Math.round(smallHeight - i));
+       
+                               copyCtx.clearRect(0,0,smallWidth,smallHeight);
+       
+                               copyCtx.drawImage(
+                                       params.canvas,
+                                       0,0,params.width,params.height,
+                                       0,0,scaledWidth,scaledHeight
+                               );
+       
+                               if (clear)
+                                       ctx.clearRect(rect.left,rect.top,rect.width,rect.height);
+       
+                               ctx.drawImage(
+                                       copy,
+                                       0,0,scaledWidth,scaledHeight,
+                                       0,0,params.width,params.height
+                               );
+                       }
+
+                       ctx.restore();
+
+                       params.useData = false;
+                       return true;
+               } else if (Pixastic.Client.isIE()) {
+                       var radius = 10 * amount;
+                       params.image.style.filter += " progid:DXImageTransform.Microsoft.Blur(pixelradius=" + radius + ")";
+
+                       if (params.options.fixMargin || 1) {
+                               params.image.style.marginLeft = (parseInt(params.image.style.marginLeft,10)||0) - Math.round(radius) + "px";
+                               params.image.style.marginTop = (parseInt(params.image.style.marginTop,10)||0) - Math.round(radius) + "px";
+                       }
+
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvas() || Pixastic.Client.isIE());
+       }
+}
+/*
+ * Pixastic Lib - Brightness/Contrast filter - v0.1.1
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.brightness = {
+
+       process : function(params) {
+
+               var brightness = parseInt(params.options.brightness,10) || 0;
+               var contrast = parseFloat(params.options.contrast)||0;
+               var legacy = !!(params.options.legacy && params.options.legacy != "false");
+
+               if (legacy) {
+                       brightness = Math.min(150,Math.max(-150,brightness));
+               } else {
+                       var brightMul = 1 + Math.min(150,Math.max(-150,brightness)) / 150;
+               }
+               contrast = Math.max(0,contrast+1);
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       var p = w*h;
+                       var pix = p*4, pix1, pix2;
+
+                       var mul, add;
+                       if (contrast != 1) {
+                               if (legacy) {
+                                       mul = contrast;
+                                       add = (brightness - 128) * contrast + 128;
+                               } else {
+                                       mul = brightMul * contrast;
+                                       add = - contrast * 128 + 128;
+                               }
+                       } else {  // this if-then is not necessary anymore, is it?
+                               if (legacy) {
+                                       mul = 1;
+                                       add = brightness;
+                               } else {
+                                       mul = brightMul;
+                                       add = 0;
+                               }
+                       }
+                       var r, g, b;
+                       while (p--) {
+                               if ((r = data[pix-=4] * mul + add) > 255 )
+                                       data[pix] = 255;
+                               else if (r < 0)
+                                       data[pix] = 0;
+                               else
+                                       data[pix] = r;
+
+                               if ((g = data[pix1=pix+1] * mul + add) > 255 ) 
+                                       data[pix1] = 255;
+                               else if (g < 0)
+                                       data[pix1] = 0;
+                               else
+                                       data[pix1] = g;
+
+                               if ((b = data[pix2=pix+2] * mul + add) > 255 ) 
+                                       data[pix2] = 255;
+                               else if (b < 0)
+                                       data[pix2] = 0;
+                               else
+                                       data[pix2] = b;
+                       }
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}
+
+/*
+ * Pixastic Lib - Color adjust filter - v0.1.1
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.coloradjust = {
+
+       process : function(params) {
+               var red = parseFloat(params.options.red) || 0;
+               var green = parseFloat(params.options.green) || 0;
+               var blue = parseFloat(params.options.blue) || 0;
+
+               red = Math.round(red*255);
+               green = Math.round(green*255);
+               blue = Math.round(blue*255);
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var rect = params.options.rect;
+
+                       var p = rect.width*rect.height;
+                       var pix = p*4, pix1, pix2;
+
+                       var r, g, b;
+                       while (p--) {
+                               pix -= 4;
+
+                               if (red) {
+                                       if ((r = data[pix] + red) < 0 ) 
+                                               data[pix] = 0;
+                                       else if (r > 255 ) 
+                                               data[pix] = 255;
+                                       else
+                                               data[pix] = r;
+                               }
+
+                               if (green) {
+                                       if ((g = data[pix1=pix+1] + green) < 0 ) 
+                                               data[pix1] = 0;
+                                       else if (g > 255 ) 
+                                               data[pix1] = 255;
+                                       else
+                                               data[pix1] = g;
+                               }
+
+                               if (blue) {
+                                       if ((b = data[pix2=pix+2] + blue) < 0 ) 
+                                               data[pix2] = 0;
+                                       else if (b > 255 ) 
+                                               data[pix2] = 255;
+                                       else
+                                               data[pix2] = b;
+                               }
+                       }
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvasImageData());
+       }
+}
+/*
+ * Pixastic Lib - Histogram - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+
+Pixastic.Actions.colorhistogram = {
+
+       array256 : function(default_value) {
+               arr = [];
+               for (var i=0; i<256; i++) { arr[i] = default_value; }
+               return arr
+       },
+       process : function(params) {
+               var values = [];
+               if (typeof params.options.returnValue != "object") {
+                       params.options.returnValue = {rvals:[], gvals:[], bvals:[]};
+               }
+               var paint = !!(params.options.paint);
+
+               var returnValue = params.options.returnValue;
+               if (typeof returnValue.values != "array") {
+                       returnValue.rvals = [];
+                       returnValue.gvals = [];
+                       returnValue.bvals = [];
+               }
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       params.useData = false;
+                       var rvals = this.array256(0);
+                       var gvals = this.array256(0);
+                       var bvals = this.array256(0);
+                       var rect = params.options.rect;
+
+                       var p = rect.width*rect.height;
+                       var pix = p*4;
+                       while (p--) {
+                               rvals[data[pix-=4]]++;
+                               gvals[data[pix+1]]++;
+                               bvals[data[pix+2]]++;
+                       }
+                       returnValue.rvals = rvals;
+                       returnValue.gvals = gvals;
+                       returnValue.bvals = bvals;
+
+                       if (paint) {
+                               var ctx = params.canvas.getContext("2d");
+                               var vals = [rvals, gvals, bvals];
+                               for (var v=0;v<3;v++) {
+                                       var yoff = (v+1) * params.height / 3;
+                                       var maxValue = 0;
+                                       for (var i=0;i<256;i++) {
+                                               if (vals[v][i] > maxValue)
+                                                       maxValue = vals[v][i];
+                                       }
+                                       var heightScale = params.height / 3 / maxValue;
+                                       var widthScale = params.width / 256;
+                                       if (v==0) ctx.fillStyle = "rgba(255,0,0,0.5)";
+                                       else if (v==1) ctx.fillStyle = "rgba(0,255,0,0.5)";
+                                       else if (v==2) ctx.fillStyle = "rgba(0,0,255,0.5)";
+                                       for (var i=0;i<256;i++) {
+                                               ctx.fillRect(
+                                                       i * widthScale, params.height - heightScale * vals[v][i] - params.height + yoff,
+                                                       widthScale, vals[v][i] * heightScale
+                                               );
+                                       }
+                               }
+                       }
+                       return true;
+               }
+       },
+
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}/*
+ * Pixastic Lib - Crop - v0.1.1
+ * Copyright (c) 2008-2009 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.crop = {
+       process : function(params) {
+               if (Pixastic.Client.hasCanvas()) {
+                       var rect = params.options.rect;
+
+                       var width = rect.width;
+                       var height = rect.height;
+                       var top = rect.top;
+                       var left = rect.left;
+
+                       if (typeof params.options.left != "undefined")
+                               left = parseInt(params.options.left,10);
+                       if (typeof params.options.top != "undefined")
+                               top = parseInt(params.options.top,10);
+                       if (typeof params.options.height != "undefined")
+                               width = parseInt(params.options.width,10);
+                       if (typeof params.options.height != "undefined")
+                               height = parseInt(params.options.height,10);
+
+                       if (left < 0) left = 0;
+                       if (left > params.width-1) left = params.width-1;
+
+                       if (top < 0) top = 0;
+                       if (top > params.height-1) top = params.height-1;
+
+                       if (width < 1) width = 1;
+                       if (left + width > params.width)
+                               width = params.width - left;
+
+                       if (height < 1) height = 1;
+                       if (top + height > params.height)
+                               height = params.height - top;
+
+                       var copy = document.createElement("canvas");
+                       copy.width = params.width;
+                       copy.height = params.height;
+                       copy.getContext("2d").drawImage(params.canvas,0,0);
+
+                       params.canvas.width = width;
+                       params.canvas.height = height;
+                       params.canvas.getContext("2d").clearRect(0,0,width,height);
+
+                       params.canvas.getContext("2d").drawImage(copy,
+                               left,top,width,height,
+                               0,0,width,height
+                       );
+
+                       params.useData = false;
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvas();
+       }
+}
+
+
+/*
+ * Pixastic Lib - Desaturation filter - v0.1.1
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.desaturate = {
+
+       process : function(params) {
+               var useAverage = !!(params.options.average && params.options.average != "false");
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       var p = w*h;
+                       var pix = p*4, pix1, pix2;
+
+                       if (useAverage) {
+                               while (p--) 
+                                       data[pix-=4] = data[pix1=pix+1] = data[pix2=pix+2] = (data[pix]+data[pix1]+data[pix2])/3
+                       } else {
+                               while (p--)
+                                       data[pix-=4] = data[pix1=pix+1] = data[pix2=pix+2] = (data[pix]*0.3 + data[pix1]*0.59 + data[pix2]*0.11);
+                       }
+                       return true;
+               } else if (Pixastic.Client.isIE()) {
+                       params.image.style.filter += " gray";
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
+       }
+}/*
+ * Pixastic Lib - Edge detection filter - v0.1.1
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.edges = {
+       process : function(params) {
+
+               var mono = !!(params.options.mono && params.options.mono != "false");
+               var invert = !!(params.options.invert && params.options.invert != "false");
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var dataCopy = Pixastic.prepareData(params, true)
+
+                       var c = -1/8;
+                       var kernel = [
+                               [c,     c,      c],
+                               [c,     1,      c],
+                               [c,     c,      c]
+                       ];
+
+                       weight = 1/c;
+
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+
+                               var nextY = (y == h) ? y - 1 : y;
+                               var prevY = (y == 1) ? 0 : y-2;
+
+                               var offsetYPrev = prevY*w*4;
+                               var offsetYNext = nextY*w*4;
+
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x*4-4);
+
+                                       var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
+                                       var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
+       
+                                       var r = ((dataCopy[offsetPrev-4]
+                                               + dataCopy[offsetPrev]
+                                               + dataCopy[offsetPrev+4]
+                                               + dataCopy[offset-4]
+                                               + dataCopy[offset+4]
+                                               + dataCopy[offsetNext-4]
+                                               + dataCopy[offsetNext]
+                                               + dataCopy[offsetNext+4]) * c
+                                               + dataCopy[offset]
+                                               ) 
+                                               * weight;
+       
+                                       var g = ((dataCopy[offsetPrev-3]
+                                               + dataCopy[offsetPrev+1]
+                                               + dataCopy[offsetPrev+5]
+                                               + dataCopy[offset-3]
+                                               + dataCopy[offset+5]
+                                               + dataCopy[offsetNext-3]
+                                               + dataCopy[offsetNext+1]
+                                               + dataCopy[offsetNext+5]) * c
+                                               + dataCopy[offset+1])
+                                               * weight;
+       
+                                       var b = ((dataCopy[offsetPrev-2]
+                                               + dataCopy[offsetPrev+2]
+                                               + dataCopy[offsetPrev+6]
+                                               + dataCopy[offset-2]
+                                               + dataCopy[offset+6]
+                                               + dataCopy[offsetNext-2]
+                                               + dataCopy[offsetNext+2]
+                                               + dataCopy[offsetNext+6]) * c
+                                               + dataCopy[offset+2])
+                                               * weight;
+
+                                       if (mono) {
+                                               var brightness = (r*0.3 + g*0.59 + b*0.11)||0;
+                                               if (invert) brightness = 255 - brightness;
+                                               if (brightness < 0 ) brightness = 0;
+                                               if (brightness > 255 ) brightness = 255;
+                                               r = g = b = brightness;
+                                       } else {
+                                               if (invert) {
+                                                       r = 255 - r;
+                                                       g = 255 - g;
+                                                       b = 255 - b;
+                                               }
+                                               if (r < 0 ) r = 0;
+                                               if (g < 0 ) g = 0;
+                                               if (b < 0 ) b = 0;
+                                               if (r > 255 ) r = 255;
+                                               if (g > 255 ) g = 255;
+                                               if (b > 255 ) b = 255;
+                                       }
+
+                                       data[offset] = r;
+                                       data[offset+1] = g;
+                                       data[offset+2] = b;
+
+                               } while (--x);
+                       } while (--y);
+
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}/*
+ * Pixastic Lib - Edge detection 2 - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ * 
+ * Contribution by Oliver Hunt (http://nerget.com/, http://nerget.com/canvas/edgeDetection.js). Thanks Oliver!
+ *
+ */
+
+Pixastic.Actions.edges2 = {
+       process : function(params) {
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var dataCopy = Pixastic.prepareData(params, true)
+
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       var w4 = w * 4;
+                       var pixel = w4 + 4; // Start at (1,1)
+                       var hm1 = h - 1;
+                       var wm1 = w - 1;
+                       for (var y = 1; y < hm1; ++y) {
+                               // Prepare initial cached values for current row
+                               var centerRow = pixel - 4;
+                               var priorRow = centerRow - w4;
+                               var nextRow = centerRow + w4;
+                               
+                               var r1 = - dataCopy[priorRow]   - dataCopy[centerRow]   - dataCopy[nextRow];
+                               var g1 = - dataCopy[++priorRow] - dataCopy[++centerRow] - dataCopy[++nextRow];
+                               var b1 = - dataCopy[++priorRow] - dataCopy[++centerRow] - dataCopy[++nextRow];
+                               
+                               var rp = dataCopy[priorRow += 2];
+                               var gp = dataCopy[++priorRow];
+                               var bp = dataCopy[++priorRow];
+                               
+                               var rc = dataCopy[centerRow += 2];
+                               var gc = dataCopy[++centerRow];
+                               var bc = dataCopy[++centerRow];
+                               
+                               var rn = dataCopy[nextRow += 2];
+                               var gn = dataCopy[++nextRow];
+                               var bn = dataCopy[++nextRow];
+                               
+                               var r2 = - rp - rc - rn;
+                               var g2 = - gp - gc - gn;
+                               var b2 = - bp - bc - bn;
+                               
+                               // Main convolution loop
+                               for (var x = 1; x < wm1; ++x) {
+                                       centerRow = pixel + 4;
+                                       priorRow = centerRow - w4;
+                                       nextRow = centerRow + w4;
+                                       
+                                       var r = 127 + r1 - rp - (rc * -8) - rn;
+                                       var g = 127 + g1 - gp - (gc * -8) - gn;
+                                       var b = 127 + b1 - bp - (bc * -8) - bn;
+                                       
+                                       r1 = r2;
+                                       g1 = g2;
+                                       b1 = b2;
+                                       
+                                       rp = dataCopy[  priorRow];
+                                       gp = dataCopy[++priorRow];
+                                       bp = dataCopy[++priorRow];
+                                       
+                                       rc = dataCopy[  centerRow];
+                                       gc = dataCopy[++centerRow];
+                                       bc = dataCopy[++centerRow];
+                                       
+                                       rn = dataCopy[  nextRow];
+                                       gn = dataCopy[++nextRow];
+                                       bn = dataCopy[++nextRow];
+                                       
+                                       r += (r2 = - rp - rc - rn);
+                                       g += (g2 = - gp - gc - gn);
+                                       b += (b2 = - bp - bc - bn);
+
+                                       if (r > 255) r = 255;
+                                       if (g > 255) g = 255;
+                                       if (b > 255) b = 255;
+                                       if (r < 0) r = 0;
+                                       if (g < 0) g = 0;
+                                       if (b < 0) b = 0;
+
+                                       data[pixel] = r;
+                                       data[++pixel] = g;
+                                       data[++pixel] = b;
+                                       //data[++pixel] = 255; // alpha
+
+                                       pixel+=2;
+                               }
+                               pixel += 8;
+                       }
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}/*
+ * Pixastic Lib - Emboss filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.emboss = {
+       process : function(params) {
+
+               var strength = parseFloat(params.options.strength)||1;
+               var greyLevel = typeof params.options.greyLevel != "undefined" ? parseInt(params.options.greyLevel) : 180;
+               var direction = params.options.direction||"topleft";
+               var blend = !!(params.options.blend && params.options.blend != "false");
+
+               var dirY = 0;
+               var dirX = 0;
+
+               switch (direction) {
+                       case "topleft":                 // top left
+                               dirY = -1;
+                               dirX = -1;
+                               break;
+                       case "top":                     // top
+                               dirY = -1;
+                               dirX = 0;
+                               break;
+                       case "topright":                        // top right
+                               dirY = -1;
+                               dirX = 1;
+                               break;
+                       case "right":                   // right
+                               dirY = 0;
+                               dirX = 1;
+                               break;
+                       case "bottomright":                     // bottom right
+                               dirY = 1;
+                               dirX = 1;
+                               break;
+                       case "bottom":                  // bottom
+                               dirY = 1;
+                               dirX = 0;
+                               break;
+                       case "bottomleft":                      // bottom left
+                               dirY = 1;
+                               dirX = -1;
+                               break;
+                       case "left":                    // left
+                               dirY = 0;
+                               dirX = -1;
+                               break;
+               }
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var dataCopy = Pixastic.prepareData(params, true)
+
+                       var invertAlpha = !!params.options.invertAlpha;
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+
+                               var otherY = dirY;
+                               if (y + otherY < 1) otherY = 0;
+                               if (y + otherY > h) otherY = 0;
+
+                               var offsetYOther = (y-1+otherY)*w*4;
+
+                               var x = w;
+                               do {
+                                               var offset = offsetY + (x-1)*4;
+
+                                               var otherX = dirX;
+                                               if (x + otherX < 1) otherX = 0;
+                                               if (x + otherX > w) otherX = 0;
+
+                                               var offsetOther = offsetYOther + (x-1+otherX)*4;
+
+                                               var dR = dataCopy[offset] - dataCopy[offsetOther];
+                                               var dG = dataCopy[offset+1] - dataCopy[offsetOther+1];
+                                               var dB = dataCopy[offset+2] - dataCopy[offsetOther+2];
+
+                                               var dif = dR;
+                                               var absDif = dif > 0 ? dif : -dif;
+
+                                               var absG = dG > 0 ? dG : -dG;
+                                               var absB = dB > 0 ? dB : -dB;
+
+                                               if (absG > absDif) {
+                                                       dif = dG;
+                                               }
+                                               if (absB > absDif) {
+                                                       dif = dB;
+                                               }
+
+                                               dif *= strength;
+
+                                               if (blend) {
+                                                       var r = data[offset] + dif;
+                                                       var g = data[offset+1] + dif;
+                                                       var b = data[offset+2] + dif;
+
+                                                       data[offset] = (r > 255) ? 255 : (r < 0 ? 0 : r);
+                                                       data[offset+1] = (g > 255) ? 255 : (g < 0 ? 0 : g);
+                                                       data[offset+2] = (b > 255) ? 255 : (b < 0 ? 0 : b);
+                                               } else {
+                                                       var grey = greyLevel - dif;
+                                                       if (grey < 0) {
+                                                               grey = 0;
+                                                       } else if (grey > 255) {
+                                                               grey = 255;
+                                                       }
+
+                                                       data[offset] = data[offset+1] = data[offset+2] = grey;
+                                               }
+
+                               } while (--x);
+                       } while (--y);
+                       return true;
+
+               } else if (Pixastic.Client.isIE()) {
+                       params.image.style.filter += " progid:DXImageTransform.Microsoft.emboss()";
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
+       }
+
+}
+/*
+ * Pixastic Lib - Flip - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.flip = {
+       process : function(params) {
+               var rect = params.options.rect;
+               var copyCanvas = document.createElement("canvas");
+               copyCanvas.width = rect.width;
+               copyCanvas.height = rect.height;
+               copyCanvas.getContext("2d").drawImage(params.image, rect.left, rect.top, rect.width, rect.height, 0, 0, rect.width, rect.height);
+
+               var ctx = params.canvas.getContext("2d");
+               ctx.clearRect(rect.left, rect.top, rect.width, rect.height);
+
+               if (params.options.axis == "horizontal") {
+                       ctx.scale(-1,1);
+                       ctx.drawImage(copyCanvas, -rect.left-rect.width, rect.top, rect.width, rect.height)
+               } else {
+                       ctx.scale(1,-1);
+                       ctx.drawImage(copyCanvas, rect.left, -rect.top-rect.height, rect.width, rect.height)
+               }
+
+               params.useData = false;
+
+               return true;            
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvas();
+       }
+}
+
+/*
+ * Pixastic Lib - Horizontal flip - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.fliph = {
+       process : function(params) {
+               if (Pixastic.Client.hasCanvas()) {
+                       var rect = params.options.rect;
+                       var copyCanvas = document.createElement("canvas");
+                       copyCanvas.width = rect.width;
+                       copyCanvas.height = rect.height;
+                       copyCanvas.getContext("2d").drawImage(params.image, rect.left, rect.top, rect.width, rect.height, 0, 0, rect.width, rect.height);
+
+                       var ctx = params.canvas.getContext("2d");
+                       ctx.clearRect(rect.left, rect.top, rect.width, rect.height);
+                       ctx.scale(-1,1);
+                       ctx.drawImage(copyCanvas, -rect.left-rect.width, rect.top, rect.width, rect.height)
+                       params.useData = false;
+
+                       return true;            
+
+               } else if (Pixastic.Client.isIE()) {
+                       params.image.style.filter += " fliph";
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvas() || Pixastic.Client.isIE());
+       }
+}
+
+/*
+ * Pixastic Lib - Vertical flip - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.flipv = {
+       process : function(params) {
+               if (Pixastic.Client.hasCanvas()) {
+                       var rect = params.options.rect;
+                       var copyCanvas = document.createElement("canvas");
+                       copyCanvas.width = rect.width;
+                       copyCanvas.height = rect.height;
+                       copyCanvas.getContext("2d").drawImage(params.image, rect.left, rect.top, rect.width, rect.height, 0, 0, rect.width, rect.height);
+
+                       var ctx = params.canvas.getContext("2d");
+                       ctx.clearRect(rect.left, rect.top, rect.width, rect.height);
+                       ctx.scale(1,-1);
+                       ctx.drawImage(copyCanvas, rect.left, -rect.top-rect.height, rect.width, rect.height)
+                       params.useData = false;
+
+                       return true;            
+
+               } else if (Pixastic.Client.isIE()) {
+                       params.image.style.filter += " flipv";
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvas() || Pixastic.Client.isIE());
+       }
+}
+
+/*
+ * Pixastic Lib - Glow - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+
+Pixastic.Actions.glow = {
+       process : function(params) {
+
+               var amount = (parseFloat(params.options.amount)||0);
+               var blurAmount = parseFloat(params.options.radius)||0;
+
+               amount = Math.min(1,Math.max(0,amount));
+               blurAmount = Math.min(5,Math.max(0,blurAmount));
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var rect = params.options.rect;
+
+                       var blurCanvas = document.createElement("canvas");
+                       blurCanvas.width = params.width;
+                       blurCanvas.height = params.height;
+                       var blurCtx = blurCanvas.getContext("2d");
+                       blurCtx.drawImage(params.canvas,0,0);
+
+                       var scale = 2;
+                       var smallWidth = Math.round(params.width / scale);
+                       var smallHeight = Math.round(params.height / scale);
+
+                       var copy = document.createElement("canvas");
+                       copy.width = smallWidth;
+                       copy.height = smallHeight;
+
+                       var clear = true;
+                       var steps = Math.round(blurAmount * 20);
+
+                       var copyCtx = copy.getContext("2d");
+                       for (var i=0;i<steps;i++) {
+                               var scaledWidth = Math.max(1,Math.round(smallWidth - i));
+                               var scaledHeight = Math.max(1,Math.round(smallHeight - i));
+       
+                               copyCtx.clearRect(0,0,smallWidth,smallHeight);
+       
+                               copyCtx.drawImage(
+                                       blurCanvas,
+                                       0,0,params.width,params.height,
+                                       0,0,scaledWidth,scaledHeight
+                               );
+       
+                               blurCtx.clearRect(0,0,params.width,params.height);
+       
+                               blurCtx.drawImage(
+                                       copy,
+                                       0,0,scaledWidth,scaledHeight,
+                                       0,0,params.width,params.height
+                               );
+                       }
+
+                       var data = Pixastic.prepareData(params);
+                       var blurData = Pixastic.prepareData({canvas:blurCanvas,options:params.options});
+                       var w = rect.width;
+                       var h = rect.height;
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x*4-4);
+
+                                       var r = data[offset] + amount * blurData[offset];
+                                       var g = data[offset+1] + amount * blurData[offset+1];
+                                       var b = data[offset+2] + amount * blurData[offset+2];
+       
+                                       if (r > 255) r = 255;
+                                       if (g > 255) g = 255;
+                                       if (b > 255) b = 255;
+                                       if (r < 0) r = 0;
+                                       if (g < 0) g = 0;
+                                       if (b < 0) b = 0;
+
+                                       data[offset] = r;
+                                       data[offset+1] = g;
+                                       data[offset+2] = b;
+
+                               } while (--x);
+                       } while (--y);
+
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}
+
+
+
+/*
+ * Pixastic Lib - Histogram - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.histogram = {
+       process : function(params) {
+
+               var average = !!(params.options.average && params.options.average != "false");
+               var paint = !!(params.options.paint && params.options.paint != "false");
+               var color = params.options.color || "rgba(255,255,255,0.5)";
+               var values = [];
+               if (typeof params.options.returnValue != "object") {
+                       params.options.returnValue = {values:[]};
+               }
+               var returnValue = params.options.returnValue;
+               if (typeof returnValue.values != "array") {
+                       returnValue.values = [];
+               }
+               values = returnValue.values;
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       params.useData = false;
+
+                       for (var i=0;i<256;i++) {
+                               values[i] = 0;
+                       }
+
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x*4-4);
+                                       var brightness = average ? 
+                                               Math.round((data[offset]+data[offset+1]+data[offset+2])/3)
+                                               : Math.round(data[offset]*0.3 + data[offset+1]*0.59 + data[offset+2]*0.11);
+                                       values[brightness]++;
+
+                               } while (--x);
+                       } while (--y);
+
+                       if (paint) {
+                               var maxValue = 0;
+                               for (var i=0;i<256;i++) {
+                                       if (values[i] > maxValue) {
+                                               maxValue = values[i];
+                                       }
+                               }
+                               var heightScale = params.height / maxValue;
+                               var widthScale = params.width / 256;
+                               var ctx = params.canvas.getContext("2d");
+                               ctx.fillStyle = color;
+                               for (var i=0;i<256;i++) {
+                                       ctx.fillRect(
+                                               i * widthScale, params.height - heightScale * values[i],
+                                               widthScale, values[i] * heightScale
+                                       );
+                               }
+                       }
+
+                       returnValue.values = values;
+
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}
+/*
+ * Pixastic Lib - HSL Adjust  - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.hsl = {
+       process : function(params) {
+
+               var hue = parseInt(params.options.hue,10)||0;
+               var saturation = (parseInt(params.options.saturation,10)||0) / 100;
+               var lightness = (parseInt(params.options.lightness,10)||0) / 100;
+
+
+               // this seems to give the same result as Photoshop
+               if (saturation < 0) {
+                       var satMul = 1+saturation;
+               } else {
+                       var satMul = 1+saturation*2;
+               }
+
+               hue = (hue%360) / 360;
+               var hue6 = hue * 6;
+
+               var rgbDiv = 1 / 255;
+
+               var light255 = lightness * 255;
+               var lightp1 = 1 + lightness;
+               var lightm1 = 1 - lightness;
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       var w4 = w*4;
+                       var y = h;
+
+                       do {
+                               var offsetY = (y-1)*w4;
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x*4-4);
+
+                                       var r = data[offset];
+                                       var g = data[offset+1];
+                                       var b = data[offset+2];
+
+                                       if (hue != 0 || saturation != 0) {
+                                               // ok, here comes rgb to hsl + adjust + hsl to rgb, all in one jumbled mess. 
+                                               // It's not so pretty, but it's been optimized to get somewhat decent performance.
+                                               // The transforms were originally adapted from the ones found in Graphics Gems, but have been heavily modified.
+                                               var vs = r;
+                                               if (g > vs) vs = g;
+                                               if (b > vs) vs = b;
+                                               var ms = r;
+                                               if (g < ms) ms = g;
+                                               if (b < ms) ms = b;
+                                               var vm = (vs-ms);
+                                               var l = (ms+vs)/255 * 0.5;
+                                               if (l > 0) {
+                                                       if (vm > 0) {
+                                                               if (l <= 0.5) {
+                                                                       var s = vm / (vs+ms) * satMul;
+                                                                       if (s > 1) s = 1;
+                                                                       var v = (l * (1+s));
+                                                               } else {
+                                                                       var s = vm / (510-vs-ms) * satMul;
+                                                                       if (s > 1) s = 1;
+                                                                       var v = (l+s - l*s);
+                                                               }
+                                                               if (r == vs) {
+                                                                       if (g == ms)
+                                                                               var h = 5 + ((vs-b)/vm) + hue6;
+                                                                       else
+                                                                               var h = 1 - ((vs-g)/vm) + hue6;
+                                                               } else if (g == vs) {
+                                                                       if (b == ms)
+                                                                               var h = 1 + ((vs-r)/vm) + hue6;
+                                                                       else
+                                                                               var h = 3 - ((vs-b)/vm) + hue6;
+                                                               } else {
+                                                                       if (r == ms)
+                                                                               var h = 3 + ((vs-g)/vm) + hue6;
+                                                                       else
+                                                                               var h = 5 - ((vs-r)/vm) + hue6;
+                                                               }
+                                                               if (h < 0) h+=6;
+                                                               if (h >= 6) h-=6;
+                                                               var m = (l+l-v);
+                                                               var sextant = h>>0;
+                                                               switch (sextant) {
+                                                                       case 0: r = v*255; g = (m+((v-m)*(h-sextant)))*255; b = m*255; break;
+                                                                       case 1: r = (v-((v-m)*(h-sextant)))*255; g = v*255; b = m*255; break;
+                                                                       case 2: r = m*255; g = v*255; b = (m+((v-m)*(h-sextant)))*255; break;
+                                                                       case 3: r = m*255; g = (v-((v-m)*(h-sextant)))*255; b = v*255; break;
+                                                                       case 4: r = (m+((v-m)*(h-sextant)))*255; g = m*255; b = v*255; break;
+                                                                       case 5: r = v*255; g = m*255; b = (v-((v-m)*(h-sextant)))*255; break;
+                                                               }
+                                                       }
+                                               }
+                                       }
+
+                                       if (lightness < 0) {
+                                               r *= lightp1;
+                                               g *= lightp1;
+                                               b *= lightp1;
+                                       } else if (lightness > 0) {
+                                               r = r * lightm1 + light255;
+                                               g = g * lightm1 + light255;
+                                               b = b * lightm1 + light255;
+                                       }
+
+                                       if (r < 0) r = 0;
+                                       if (g < 0) g = 0;
+                                       if (b < 0) b = 0;
+                                       if (r > 255) r = 255;
+                                       if (g > 255) g = 255;
+                                       if (b > 255) b = 255;
+
+                                       data[offset] = r;
+                                       data[offset+1] = g;
+                                       data[offset+2] = b;
+
+                               } while (--x);
+                       } while (--y);
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+
+}
+/*
+ * Pixastic Lib - Invert filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.invert = {
+       process : function(params) {
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+
+                       var invertAlpha = !!params.options.invertAlpha;
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x-1)*4;
+                                       data[offset] = 255 - data[offset];
+                                       data[offset+1] = 255 - data[offset+1];
+                                       data[offset+2] = 255 - data[offset+2];
+                                       if (invertAlpha) data[offset+3] = 255 - data[offset+3];
+                               } while (--x);
+                       } while (--y);
+
+                       return true;
+               } else if (Pixastic.Client.isIE()) {
+                       params.image.style.filter += " invert";
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
+       }
+}
+/*
+ * Pixastic Lib - Laplace filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.laplace = {
+       process : function(params) {
+
+               var strength = 1.0;
+               var invert = !!(params.options.invert && params.options.invert != "false");
+               var contrast = parseFloat(params.options.edgeStrength)||0;
+
+               var greyLevel = parseInt(params.options.greyLevel)||0;
+
+               contrast = -contrast;
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var dataCopy = Pixastic.prepareData(params, true)
+
+                       var kernel = [
+                               [-1,    -1,     -1],
+                               [-1,    8,      -1],
+                               [-1,    -1,     -1]
+                       ];
+
+                       var weight = 1/8;
+
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+
+                               var nextY = (y == h) ? y - 1 : y;
+                               var prevY = (y == 1) ? 0 : y-2;
+
+                               var offsetYPrev = prevY*w*4;
+                               var offsetYNext = nextY*w*4;
+
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x*4-4);
+
+                                       var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
+                                       var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
+       
+                                       var r = ((-dataCopy[offsetPrev-4]
+                                               - dataCopy[offsetPrev]
+                                               - dataCopy[offsetPrev+4]
+                                               - dataCopy[offset-4]
+                                               - dataCopy[offset+4]
+                                               - dataCopy[offsetNext-4]
+                                               - dataCopy[offsetNext]
+                                               - dataCopy[offsetNext+4])
+                                               + dataCopy[offset] * 8) 
+                                               * weight;
+       
+                                       var g = ((-dataCopy[offsetPrev-3]
+                                               - dataCopy[offsetPrev+1]
+                                               - dataCopy[offsetPrev+5]
+                                               - dataCopy[offset-3]
+                                               - dataCopy[offset+5]
+                                               - dataCopy[offsetNext-3]
+                                               - dataCopy[offsetNext+1]
+                                               - dataCopy[offsetNext+5])
+                                               + dataCopy[offset+1] * 8)
+                                               * weight;
+       
+                                       var b = ((-dataCopy[offsetPrev-2]
+                                               - dataCopy[offsetPrev+2]
+                                               - dataCopy[offsetPrev+6]
+                                               - dataCopy[offset-2]
+                                               - dataCopy[offset+6]
+                                               - dataCopy[offsetNext-2]
+                                               - dataCopy[offsetNext+2]
+                                               - dataCopy[offsetNext+6])
+                                               + dataCopy[offset+2] * 8)
+                                               * weight;
+
+                                       var brightness = ((r + g + b)/3) + greyLevel;
+
+                                       if (contrast != 0) {
+                                               if (brightness > 127) {
+                                                       brightness += ((brightness + 1) - 128) * contrast;
+                                               } else if (brightness < 127) {
+                                                       brightness -= (brightness + 1) * contrast;
+                                               }
+                                       }
+                                       if (invert) {
+                                               brightness = 255 - brightness;
+                                       }
+                                       if (brightness < 0 ) brightness = 0;
+                                       if (brightness > 255 ) brightness = 255;
+
+                                       data[offset] = data[offset+1] = data[offset+2] = brightness;
+
+                               } while (--x);
+                       } while (--y);
+
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}
+
+/*
+ * Pixastic Lib - Lighten filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.lighten = {
+
+       process : function(params) {
+               var amount = parseFloat(params.options.amount) || 0;
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x-1)*4;
+
+                                       var r = data[offset];
+                                       var g = data[offset+1];
+                                       var b = data[offset+2];
+
+                                       r += r*amount;
+                                       g += g*amount;
+                                       b += b*amount;
+
+                                       if (r < 0 ) r = 0;
+                                       if (g < 0 ) g = 0;
+                                       if (b < 0 ) b = 0;
+                                       if (r > 255 ) r = 255;
+                                       if (g > 255 ) g = 255;
+                                       if (b > 255 ) b = 255;
+
+                                       data[offset] = r;
+                                       data[offset+1] = g;
+                                       data[offset+2] = b;
+
+                               } while (--x);
+                       } while (--y);
+                       return true;
+
+               } else if (Pixastic.Client.isIE()) {
+                       var img = params.image;
+                       if (amount < 0) {
+                               img.style.filter += " light()";
+                               img.filters[img.filters.length-1].addAmbient(
+                                       255,255,255,
+                                       100 * -amount
+                               );
+                       } else if (amount > 0) {
+                               img.style.filter += " light()";
+                               img.filters[img.filters.length-1].addAmbient(
+                                       255,255,255,
+                                       100
+                               );
+                               img.filters[img.filters.length-1].addAmbient(
+                                       255,255,255,
+                                       100 * amount
+                               );
+                       }
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
+       }
+}
+/*
+ * Pixastic Lib - Mosaic filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.mosaic = {
+
+       process : function(params) {
+               var blockSize = Math.max(1,parseInt(params.options.blockSize,10));
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+                       var w4 = w*4;
+                       var y = h;
+
+                       var ctx = params.canvas.getContext("2d");
+
+                       var pixel = document.createElement("canvas");
+                       pixel.width = pixel.height = 1;
+                       var pixelCtx = pixel.getContext("2d");
+
+                       var copy = document.createElement("canvas");
+                       copy.width = w;
+                       copy.height = h;
+                       var copyCtx = copy.getContext("2d");
+                       copyCtx.drawImage(params.canvas,rect.left,rect.top,w,h, 0,0,w,h);
+
+                       for (var y=0;y<h;y+=blockSize) {
+                               for (var x=0;x<w;x+=blockSize) {
+                                       var blockSizeX = blockSize;
+                                       var blockSizeY = blockSize;
+               
+                                       if (blockSizeX + x > w)
+                                               blockSizeX = w - x;
+                                       if (blockSizeY + y > h)
+                                               blockSizeY = h - y;
+
+                                       pixelCtx.drawImage(copy, x, y, blockSizeX, blockSizeY, 0, 0, 1, 1);
+                                       var data = pixelCtx.getImageData(0,0,1,1).data;
+                                       ctx.fillStyle = "rgb(" + data[0] + "," + data[1] + "," + data[2] + ")";
+                                       ctx.fillRect(rect.left + x, rect.top + y, blockSize, blockSize);
+                               }
+                       }
+                       params.useData = false;
+
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvasImageData());
+       }
+}/*
+ * Pixastic Lib - Noise filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.noise = {
+
+       process : function(params) {
+               var amount = 0;
+               var strength = 0;
+               var mono = false;
+
+               if (typeof params.options.amount != "undefined")
+                       amount = parseFloat(params.options.amount)||0;
+               if (typeof params.options.strength != "undefined")
+                       strength = parseFloat(params.options.strength)||0;
+               if (typeof params.options.mono != "undefined")
+                       mono = !!(params.options.mono && params.options.mono != "false");
+
+               amount = Math.max(0,Math.min(1,amount));
+               strength = Math.max(0,Math.min(1,strength));
+
+               var noise = 128 * strength;
+               var noise2 = noise / 2;
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+                       var w4 = w*4;
+                       var y = h;
+                       var random = Math.random;
+
+                       do {
+                               var offsetY = (y-1)*w4;
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x-1)*4;
+                                       if (random() < amount) {
+                                               if (mono) {
+                                                       var pixelNoise = - noise2 + random() * noise;
+                                                       var r = data[offset] + pixelNoise;
+                                                       var g = data[offset+1] + pixelNoise;
+                                                       var b = data[offset+2] + pixelNoise;
+                                               } else {
+                                                       var r = data[offset] - noise2 + (random() * noise);
+                                                       var g = data[offset+1] - noise2 + (random() * noise);
+                                                       var b = data[offset+2] - noise2 + (random() * noise);
+                                               }
+
+                                               if (r < 0 ) r = 0;
+                                               if (g < 0 ) g = 0;
+                                               if (b < 0 ) b = 0;
+                                               if (r > 255 ) r = 255;
+                                               if (g > 255 ) g = 255;
+                                               if (b > 255 ) b = 255;
+
+                                               data[offset] = r;
+                                               data[offset+1] = g;
+                                               data[offset+2] = b;
+                                       }
+                               } while (--x);
+                       } while (--y);
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}
+
+/*
+ * Pixastic Lib - Posterize effect - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.posterize = {
+
+       process : function(params) {
+
+               
+               var numLevels = 256;
+               if (typeof params.options.levels != "undefined")
+                       numLevels = parseInt(params.options.levels,10)||1;
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+
+                       numLevels = Math.max(2,Math.min(256,numLevels));
+       
+                       var numAreas = 256 / numLevels;
+                       var numValues = 256 / (numLevels-1);
+
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x-1)*4;
+
+                                       var r = numValues * ((data[offset] / numAreas)>>0);
+                                       var g = numValues * ((data[offset+1] / numAreas)>>0);
+                                       var b = numValues * ((data[offset+2] / numAreas)>>0);
+
+                                       if (r > 255) r = 255;
+                                       if (g > 255) g = 255;
+                                       if (b > 255) b = 255;
+
+                                       data[offset] = r;
+                                       data[offset+1] = g;
+                                       data[offset+2] = b;
+
+                               } while (--x);
+                       } while (--y);
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}
+
+
+/*
+ * Pixastic Lib - Pointillize filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.pointillize = {
+
+       process : function(params) {
+               var radius = Math.max(1,parseInt(params.options.radius,10));
+               var density = Math.min(5,Math.max(0,parseFloat(params.options.density)||0));
+               var noise = Math.max(0,parseFloat(params.options.noise)||0);
+               var transparent = !!(params.options.transparent && params.options.transparent != "false");
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+                       var w4 = w*4;
+                       var y = h;
+
+                       var ctx = params.canvas.getContext("2d");
+                       var canvasWidth = params.canvas.width;
+                       var canvasHeight = params.canvas.height;
+
+                       var pixel = document.createElement("canvas");
+                       pixel.width = pixel.height = 1;
+                       var pixelCtx = pixel.getContext("2d");
+
+                       var copy = document.createElement("canvas");
+                       copy.width = w;
+                       copy.height = h;
+                       var copyCtx = copy.getContext("2d");
+                       copyCtx.drawImage(params.canvas,rect.left,rect.top,w,h, 0,0,w,h);
+
+                       var diameter = radius * 2;
+
+                       if (transparent)
+                               ctx.clearRect(rect.left, rect.top, rect.width, rect.height);
+
+                       var noiseRadius = radius * noise;
+
+                       var dist = 1 / density;
+
+                       for (var y=0;y<h+radius;y+=diameter*dist) {
+                               for (var x=0;x<w+radius;x+=diameter*dist) {
+                                       rndX = noise ? (x+((Math.random()*2-1) * noiseRadius))>>0 : x;
+                                       rndY = noise ? (y+((Math.random()*2-1) * noiseRadius))>>0 : y;
+
+                                       var pixX = rndX - radius;
+                                       var pixY = rndY - radius;
+                                       if (pixX < 0) pixX = 0;
+                                       if (pixY < 0) pixY = 0;
+
+                                       var cx = rndX + rect.left;
+                                       var cy = rndY + rect.top;
+                                       if (cx < 0) cx = 0;
+                                       if (cx > canvasWidth) cx = canvasWidth;
+                                       if (cy < 0) cy = 0;
+                                       if (cy > canvasHeight) cy = canvasHeight;
+
+                                       var diameterX = diameter;
+                                       var diameterY = diameter;
+
+                                       if (diameterX + pixX > w)
+                                               diameterX = w - pixX;
+                                       if (diameterY + pixY > h)
+                                               diameterY = h - pixY;
+                                       if (diameterX < 1) diameterX = 1;
+                                       if (diameterY < 1) diameterY = 1;
+
+                                       pixelCtx.drawImage(copy, pixX, pixY, diameterX, diameterY, 0, 0, 1, 1);
+                                       var data = pixelCtx.getImageData(0,0,1,1).data;
+
+                                       ctx.fillStyle = "rgb(" + data[0] + "," + data[1] + "," + data[2] + ")";
+                                       ctx.beginPath();
+                                       ctx.arc(cx, cy, radius, 0, Math.PI*2, true);
+                                       ctx.closePath();
+                                       ctx.fill();
+                               }
+                       }
+
+                       params.useData = false;
+
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvasImageData());
+       }
+}/*
+ * Pixastic Lib - Resize - v0.1.0
+ * Copyright (c) 2009 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.resize = {
+       process : function(params) {
+               if (Pixastic.Client.hasCanvas()) {
+                       var width = parseInt(params.options.width,10);
+                       var height = parseInt(params.options.height,10);
+                       var canvas = params.canvas;
+
+                       if (width < 1) width = 1;
+                       if (width < 2) width = 2;
+
+                       var copy = document.createElement("canvas");
+                       copy.width = width;
+                       copy.height = height;
+
+                       copy.getContext("2d").drawImage(canvas,0,0,width,height);
+                       canvas.width = width;
+                       canvas.height = height;
+
+                       canvas.getContext("2d").drawImage(copy,0,0);
+
+                       params.useData = false;
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvas();
+       }
+}
+
+
+/*
+ * Pixastic Lib - Remove noise - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.removenoise = {
+       process : function(params) {
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+
+                               var nextY = (y == h) ? y - 1 : y;
+                               var prevY = (y == 1) ? 0 : y-2;
+
+                               var offsetYPrev = prevY*w*4;
+                               var offsetYNext = nextY*w*4;
+
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x*4-4);
+
+                                       var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
+                                       var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
+
+                                       var minR, maxR, minG, maxG, minB, maxB;
+
+                                       minR = maxR = data[offsetPrev];
+                                       var r1 = data[offset-4], r2 = data[offset+4], r3 = data[offsetNext];
+                                       if (r1 < minR) minR = r1;
+                                       if (r2 < minR) minR = r2;
+                                       if (r3 < minR) minR = r3;
+                                       if (r1 > maxR) maxR = r1;
+                                       if (r2 > maxR) maxR = r2;
+                                       if (r3 > maxR) maxR = r3;
+
+                                       minG = maxG = data[offsetPrev+1];
+                                       var g1 = data[offset-3], g2 = data[offset+5], g3 = data[offsetNext+1];
+                                       if (g1 < minG) minG = g1;
+                                       if (g2 < minG) minG = g2;
+                                       if (g3 < minG) minG = g3;
+                                       if (g1 > maxG) maxG = g1;
+                                       if (g2 > maxG) maxG = g2;
+                                       if (g3 > maxG) maxG = g3;
+
+                                       minB = maxB = data[offsetPrev+2];
+                                       var b1 = data[offset-2], b2 = data[offset+6], b3 = data[offsetNext+2];
+                                       if (b1 < minB) minB = b1;
+                                       if (b2 < minB) minB = b2;
+                                       if (b3 < minB) minB = b3;
+                                       if (b1 > maxB) maxB = b1;
+                                       if (b2 > maxB) maxB = b2;
+                                       if (b3 > maxB) maxB = b3;
+
+                                       if (data[offset] > maxR) {
+                                               data[offset] = maxR;
+                                       } else if (data[offset] < minR) {
+                                               data[offset] = minR;
+                                       }
+                                       if (data[offset+1] > maxG) {
+                                               data[offset+1] = maxG;
+                                       } else if (data[offset+1] < minG) {
+                                               data[offset+1] = minG;
+                                       }
+                                       if (data[offset+2] > maxB) {
+                                               data[offset+2] = maxB;
+                                       } else if (data[offset+2] < minB) {
+                                               data[offset+2] = minB;
+                                       }
+
+                               } while (--x);
+                       } while (--y);
+
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}/*
+ * Pixastic Lib - Rotate - v0.1.0
+ * Copyright (c) 2009 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.rotate = {
+       process : function(params) {
+               if (Pixastic.Client.hasCanvas()) {
+                       var canvas = params.canvas;
+
+                       var width = params.width;
+                       var height = params.height;
+
+                       var copy = document.createElement("canvas");
+                       copy.width = width;
+                       copy.height = height;
+                       copy.getContext("2d").drawImage(canvas,0,0,width,height);
+
+                       var angle = -parseFloat(params.options.angle) * Math.PI / 180;
+
+                       var dimAngle = angle;
+                       if (dimAngle > Math.PI*0.5)
+                               dimAngle = Math.PI - dimAngle;
+                       if (dimAngle < -Math.PI*0.5)
+                               dimAngle = -Math.PI - dimAngle;
+
+                       var diag = Math.sqrt(width*width + height*height);
+
+                       var diagAngle1 = Math.abs(dimAngle) - Math.abs(Math.atan2(height, width));
+                       var diagAngle2 = Math.abs(dimAngle) + Math.abs(Math.atan2(height, width));
+
+                       var newWidth = Math.abs(Math.cos(diagAngle1) * diag);
+                       var newHeight = Math.abs(Math.sin(diagAngle2) * diag);
+
+                       canvas.width = newWidth;
+                       canvas.height = newHeight;
+
+                       var ctx = canvas.getContext("2d");
+                       ctx.translate(newWidth/2, newHeight/2);
+                       ctx.rotate(angle);
+                       ctx.drawImage(copy,-width/2,-height/2);
+
+                       params.useData = false;
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvas();
+       }
+}
+
+
+/*
+ * Pixastic Lib - Sepia filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.sepia = {
+
+       process : function(params) {
+               var mode = (parseInt(params.options.mode,10)||0);
+               if (mode < 0) mode = 0;
+               if (mode > 1) mode = 1;
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x-1)*4;
+
+                                       if (mode) {
+                                               // a bit faster, but not as good
+                                               var d = data[offset] * 0.299 + data[offset+1] * 0.587 + data[offset+2] * 0.114;
+                                               var r = (d + 39);
+                                               var g = (d + 14);
+                                               var b = (d - 36);
+                                       } else {
+                                               // Microsoft
+                                               var or = data[offset];
+                                               var og = data[offset+1];
+                                               var ob = data[offset+2];
+       
+                                               var r = (or * 0.393 + og * 0.769 + ob * 0.189);
+                                               var g = (or * 0.349 + og * 0.686 + ob * 0.168);
+                                               var b = (or * 0.272 + og * 0.534 + ob * 0.131);
+                                       }
+
+                                       if (r < 0) r = 0; if (r > 255) r = 255;
+                                       if (g < 0) g = 0; if (g > 255) g = 255;
+                                       if (b < 0) b = 0; if (b > 255) b = 255;
+
+                                       data[offset] = r;
+                                       data[offset+1] = g;
+                                       data[offset+2] = b;
+
+                               } while (--x);
+                       } while (--y);
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}/*
+ * Pixastic Lib - Sharpen filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.sharpen = {
+       process : function(params) {
+
+               var strength = 0;
+               if (typeof params.options.amount != "undefined")
+                       strength = parseFloat(params.options.amount)||0;
+
+               if (strength < 0) strength = 0;
+               if (strength > 1) strength = 1;
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var dataCopy = Pixastic.prepareData(params, true)
+
+                       var mul = 15;
+                       var mulOther = 1 + 3*strength;
+
+                       var kernel = [
+                               [0,     -mulOther,      0],
+                               [-mulOther,     mul,    -mulOther],
+                               [0,     -mulOther,      0]
+                       ];
+
+                       var weight = 0;
+                       for (var i=0;i<3;i++) {
+                               for (var j=0;j<3;j++) {
+                                       weight += kernel[i][j];
+                               }
+                       }
+
+                       weight = 1 / weight;
+
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+
+                       mul *= weight;
+                       mulOther *= weight;
+
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+
+                               var nextY = (y == h) ? y - 1 : y;
+                               var prevY = (y == 1) ? 0 : y-2;
+
+                               var offsetYPrev = prevY*w4;
+                               var offsetYNext = nextY*w4;
+
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x*4-4);
+
+                                       var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
+                                       var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
+
+                                       var r = ((
+                                               - dataCopy[offsetPrev]
+                                               - dataCopy[offset-4]
+                                               - dataCopy[offset+4]
+                                               - dataCopy[offsetNext])         * mulOther
+                                               + dataCopy[offset]      * mul
+                                               );
+
+                                       var g = ((
+                                               - dataCopy[offsetPrev+1]
+                                               - dataCopy[offset-3]
+                                               - dataCopy[offset+5]
+                                               - dataCopy[offsetNext+1])       * mulOther
+                                               + dataCopy[offset+1]    * mul
+                                               );
+
+                                       var b = ((
+                                               - dataCopy[offsetPrev+2]
+                                               - dataCopy[offset-2]
+                                               - dataCopy[offset+6]
+                                               - dataCopy[offsetNext+2])       * mulOther
+                                               + dataCopy[offset+2]    * mul
+                                               );
+
+
+                                       if (r < 0 ) r = 0;
+                                       if (g < 0 ) g = 0;
+                                       if (b < 0 ) b = 0;
+                                       if (r > 255 ) r = 255;
+                                       if (g > 255 ) g = 255;
+                                       if (b > 255 ) b = 255;
+
+                                       data[offset] = r;
+                                       data[offset+1] = g;
+                                       data[offset+2] = b;
+
+                               } while (--x);
+                       } while (--y);
+
+                       return true;
+
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}
+/*
+ * Pixastic Lib - Solarize filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.solarize = {
+
+       process : function(params) {
+               var useAverage = !!(params.options.average && params.options.average != "false");
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var data = Pixastic.prepareData(params);
+                       var rect = params.options.rect;
+                       var w = rect.width;
+                       var h = rect.height;
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x-1)*4;
+
+                                       var r = data[offset];
+                                       var g = data[offset+1];
+                                       var b = data[offset+2];
+
+                                       if (r > 127) r = 255 - r;
+                                       if (g > 127) g = 255 - g;
+                                       if (b > 127) b = 255 - b;
+
+                                       data[offset] = r;
+                                       data[offset+1] = g;
+                                       data[offset+2] = b;
+
+                               } while (--x);
+                       } while (--y);
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return (Pixastic.Client.hasCanvasImageData());
+       }
+}/*
+ * Pixastic Lib - USM - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+
+Pixastic.Actions.unsharpmask = {
+       process : function(params) {
+
+               var amount = (parseFloat(params.options.amount)||0);
+               var blurAmount = parseFloat(params.options.radius)||0;
+               var threshold = parseFloat(params.options.threshold)||0;
+
+               amount = Math.min(500,Math.max(0,amount)) / 2;
+               blurAmount = Math.min(5,Math.max(0,blurAmount)) / 10;
+               threshold = Math.min(255,Math.max(0,threshold));
+
+               threshold--;
+               var thresholdNeg = -threshold;
+
+               amount *= 0.016;
+               amount++;
+
+               if (Pixastic.Client.hasCanvasImageData()) {
+                       var rect = params.options.rect;
+
+                       var blurCanvas = document.createElement("canvas");
+                       blurCanvas.width = params.width;
+                       blurCanvas.height = params.height;
+                       var blurCtx = blurCanvas.getContext("2d");
+                       blurCtx.drawImage(params.canvas,0,0);
+
+                       var scale = 2;
+                       var smallWidth = Math.round(params.width / scale);
+                       var smallHeight = Math.round(params.height / scale);
+
+                       var copy = document.createElement("canvas");
+                       copy.width = smallWidth;
+                       copy.height = smallHeight;
+
+                       var steps = Math.round(blurAmount * 20);
+
+                       var copyCtx = copy.getContext("2d");
+                       for (var i=0;i<steps;i++) {
+                               var scaledWidth = Math.max(1,Math.round(smallWidth - i));
+                               var scaledHeight = Math.max(1,Math.round(smallHeight - i));
+
+                               copyCtx.clearRect(0,0,smallWidth,smallHeight);
+
+                               copyCtx.drawImage(
+                                       blurCanvas,
+                                       0,0,params.width,params.height,
+                                       0,0,scaledWidth,scaledHeight
+                               );
+       
+                               blurCtx.clearRect(0,0,params.width,params.height);
+       
+                               blurCtx.drawImage(
+                                       copy,
+                                       0,0,scaledWidth,scaledHeight,
+                                       0,0,params.width,params.height
+                               );
+                       }
+
+                       var data = Pixastic.prepareData(params);
+                       var blurData = Pixastic.prepareData({canvas:blurCanvas,options:params.options});
+                       var w = rect.width;
+                       var h = rect.height;
+                       var w4 = w*4;
+                       var y = h;
+                       do {
+                               var offsetY = (y-1)*w4;
+                               var x = w;
+                               do {
+                                       var offset = offsetY + (x*4-4);
+
+                                       var difR = data[offset] - blurData[offset];
+                                       if (difR > threshold || difR < thresholdNeg) {
+                                               var blurR = blurData[offset];
+                                               blurR = amount * difR + blurR;
+                                               data[offset] = blurR > 255 ? 255 : (blurR < 0 ? 0 : blurR);
+                                       }
+
+                                       var difG = data[offset+1] - blurData[offset+1];
+                                       if (difG > threshold || difG < thresholdNeg) {
+                                               var blurG = blurData[offset+1];
+                                               blurG = amount * difG + blurG;
+                                               data[offset+1] = blurG > 255 ? 255 : (blurG < 0 ? 0 : blurG);
+                                       }
+
+                                       var difB = data[offset+2] - blurData[offset+2];
+                                       if (difB > threshold || difB < thresholdNeg) {
+                                               var blurB = blurData[offset+2];
+                                               blurB = amount * difB + blurB;
+                                               data[offset+2] = blurB > 255 ? 255 : (blurB < 0 ? 0 : blurB);
+                                       }
+
+                               } while (--x);
+                       } while (--y);
+
+                       return true;
+               }
+       },
+       checkSupport : function() {
+               return Pixastic.Client.hasCanvasImageData();
+       }
+}
+
+
+
+
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/pixastic-editor/pixastic.css b/js2/mwEmbed/libClipEdit/pixastic-lib/pixastic-editor/pixastic.css
new file mode 100644 (file)
index 0000000..bda133c
--- /dev/null
@@ -0,0 +1,423 @@
+/* http://meyerweb.com/eric/thoughts/2007/05/01/reset-reloaded/ */
+
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, font, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td {
+       margin: 0;
+       padding: 0;
+       border: 0;
+       outline: 0;
+       font-weight: inherit;
+       font-style: inherit;
+       font-size: 100%;
+       font-family: inherit;
+       vertical-align: baseline;
+}
+/* remember to define focus styles! */
+:focus {
+       outline: 0;
+}
+body {
+       line-height: 1;
+       color: black;
+       background: white;
+}
+ol, ul {
+       list-style: none;
+}
+/* tables still need 'cellspacing="0"' in the markup */
+table {
+       border-collapse: separate;
+       border-spacing: 0;
+}
+caption, th, td {
+       text-align: left;
+       font-weight: normal;
+}
+blockquote:before, blockquote:after,
+q:before, q:after {
+       content: "";
+}
+blockquote, q {
+       quotes: "" "";
+}
+/* end reset */
+
+/* -----------------------
+ *   Base
+ * -----------------------
+ */
+
+/* main container element for editor app */
+#pixastic-editor {
+       margin : 0;
+       position : absolute;
+       left : 0;
+       top : 0;
+       padding: 0px;
+       width: 100%;
+       height: 100%;
+       font-family : Helvetica,Arial,sans-serif;
+       overflow : hidden;
+       z-index : 10000000;
+} 
+
+
+/* -----------------------
+ *   Loading screen
+ * -----------------------
+ */
+
+/* container for loading screen */
+#loading-screen {
+       margin : 0;
+       position : absolute;
+       left : 0;
+       top : 0;
+       padding: 0px;
+       width: 100%;
+       height: 100%;
+       font-family : Helvetica,Arial,sans-serif;
+       overflow : hidden;
+       z-index : 10000000;
+       background-color : #111;
+       opacity : 0.9;
+       display : table;
+       text-align : center;
+} 
+
+/* container for spinner in loading screen */
+#loading-screen-cell {
+       display : table-cell;
+       vertical-align : middle;
+       text-align : center;
+}
+
+
+/* -----------------------
+ *   Misc
+ * -----------------------
+ */
+
+
+// UI error dialog
+.ui-dialog .error-dialog {
+       background-color : #544;
+}
+
+/* loading spinner */
+.spinner {
+       width : 31px;
+       height : 31px;
+       display : inline-block;
+       background: url(spinner.gif);
+       overflow : hidden;
+}
+
+canvas.display-canvas,
+canvas.undo-canvas {
+       /*
+       background : url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAC1JREFUeNpiPHPmDAM2YGxsjFWciYFEMKqBGMD4//9/rBJnz54dDSX6aQAIMABCtQiAsDRF+wAAAABJRU5ErkJggg==');
+       */
+       background : url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAC5JREFUeNpiPHPmTAMDHmBsbIxPmoGJgUIwasBgMICFUDyfPXt2NBCHvwEAAQYAICIGn294LYEAAAAASUVORK5CYII=');
+
+}
+
+.far-far-away {
+       position : absolute;
+       left : -9999px;
+       top : -9999px;
+}
+
+#powered-by-pixastic {
+       position : absolute;
+       bottom : 0px;
+       margin-bottom : 23px;
+       margin-left : 42px;
+}
+#powered-by-pixastic a {
+       font-size : 12px;
+       font-family : Helvetica,Arial,sans-serif;
+       letter-spacing : 0.1em;
+       color : rgb(100,100,100);
+       color : rgba(255,255,255,0.2);
+       text-decoration : none;
+}
+
+#powered-by-pixastic a:hover {
+       color : rgb(200,200,200);
+       color : rgba(255,255,255,0.7);
+       text-decoration : underline;
+}
+
+
+/* -----------------------
+ *   Skeleton structure
+ * -----------------------
+ */
+
+/* editor background underlay */
+#background {
+       background-color : #111;
+       opacity : 0.9;
+       width : 100%;
+       height : 100%;
+       position : absolute;
+       z-index : -1;
+}
+
+#image-area {
+       position : relative;
+       background-color : #222;
+       border : 1px solid #444;
+       width : 100%;
+       height : 100%;
+       -moz-box-sizing:border-box;
+       overflow : auto;
+       text-align : center;
+}
+
+#image-area-sub {
+}
+
+#image-container {
+}
+
+#image-overlay-container {
+       -moz-box-sizing:border-box;
+       width:100%;
+       height:100%;
+       position:absolute;
+       top:0;
+       left:0;
+}
+
+#image-overlay {
+}
+
+
+/* structure elements */
+#edit-ctr-1 {
+       position : absolute;
+       top : 0;
+       left : 0;
+       width : 100%;
+       height : 100%;
+}
+
+#edit-ctr-2 {
+       -moz-box-sizing : border-box;
+       box-sizing : border-box;
+       padding-left:40px;
+       padding-right:420px;
+       padding-top:70px;
+       padding-bottom : 40px;
+       height : 100%;
+       width : 100%;
+}
+
+
+/* main menu bar */
+#main-bar {
+       position : absolute;
+       width : 100%;
+       text-align : right;
+       margin-top : 20px;
+       margin-right : 30px;
+}
+
+/* area on the right with accordion widgets and undo bar */
+#controls-bar {
+       margin-right : -385px;
+       width : 372px;
+       float : right;
+       height : 100%;
+}
+
+/* accordion area */
+#action-bar {
+       padding : 10px;
+       width : 290px;
+       background-color : #222;
+       border : 1px solid #444;
+       -moz-box-sizing : border-box;
+       box-sizing : border-box;
+       height : 100%;
+       overflow-x : hidden;
+       overflow-y : auto;
+       float: right; 
+       position : relative;
+}
+
+#action-bar-overlay {
+       position : absolute;
+       z-index : 1000000;
+       width : 100%;
+       height : 100%;
+       left : 0;
+       top : 0;
+       background-color : #444;
+       opacity : 0.2;
+       display : none;
+}
+
+
+/* vertical bar with undo image states */
+#undo-bar {
+       -moz-box-sizing : border-box;
+       box-sizing : border-box;
+       background-color : #222;
+       border : 1px solid #444;
+       width: 70px; 
+       height: 100%;
+       overflow: hidden;
+       padding-top : 3px;
+}
+
+
+
+/* -----------------------
+ *   Main menu styles
+ * -----------------------
+ */
+
+.main-tab {
+       color : #999;
+       display : inline-block;
+       width : 150px;
+       text-transform : lowercase;
+       font-size : 22px;
+       cursor : pointer;
+       text-align : center;
+       text-decoration : none;
+       padding-top : 4px;
+       padding-bottom : 5px;
+       outline : 0;
+}
+
+.main-tab.hover {
+       color : white !important;
+}
+
+.main-tab.active {
+       color : white;
+}
+
+
+
+/* -----------------------
+ *   Undo list
+ * -----------------------
+ */
+
+
+.undo-canvas-small {
+       width : 60px;
+       height : 40px;
+       cursor : pointer;
+}
+
+.undo-link {
+       width : 60px;
+       height : 40px;
+       display : block;
+       margin : 4px;
+       cursor : pointer;
+       opacity : 0.8;
+}
+
+.undo-link.hover {
+       opacity : 1;
+}
+
+
+
+/* -----------------------
+ *   Action UI controls
+ * -----------------------
+ */
+
+
+.ui-slider-label, 
+.ui-checkbox-label, 
+.ui-textinput-label, 
+.ui-select-label {
+       width : 70px;
+       text-align : right;
+       margin-right : 5px;
+       display : inline-block;
+}
+
+.ui-textinput-label-right {
+       margin-left : 5px;
+}
+
+.ui-textinput {
+}
+
+.ui-numericinput {
+       width : 35px;
+}
+
+.ui-slider {
+       width : 125px;
+       display : inline-block;
+       margin-left : 3px;
+       background-color : #222;
+}
+
+.ui-slider-value {
+       font-size : 11px;
+       width : 25px;
+       display : inline-block;
+       margin-left : 10px;
+}
+
+.ui-action-output {
+       margin-bottom : 10px;
+}
+
+.ui-accordion .ui-accordion-content-active {
+       font-size : 11px;
+       overflow : hidden;
+}
+
+.ui-slider-horizontal {
+}
+
+.ui-slider-container, 
+.ui-checkbox-container, 
+.ui-textinput-container, 
+.ui-select-container {
+       margin-top : 0px;
+       margin-bottom : 10px;
+       white-space : nowrap;
+}
+
+.ui-preview-checkbox-container {
+       display : inline-block;
+}
+
+.ui-checkbox {
+       margin-bottom:3px;
+       margin-left:5px;
+       margin-right:5px;
+       margin-top:0px;
+       vertical-align:middle;
+}
+
+input::-moz-focus-inner { border: 0; }
+
+.action-output-text {
+       margin-bottom : 5px;
+}
+
+button {
+       margin-right : 5px;
+}
+
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/pixastic-editor/ui.js b/js2/mwEmbed/libClipEdit/pixastic-lib/pixastic-editor/ui.js
new file mode 100644 (file)
index 0000000..6b267ac
--- /dev/null
@@ -0,0 +1,237 @@
+(function($) {
+
+       var PE = PixasticEditor;
+
+       function makeSlider(label, id, min, max, step, defaultVal, onChange) {
+               var $ctr = $j("<div></div>", PE.getDocument())
+                       .addClass("ui-slider-container");
+
+               var $label = $j("<label></label>", PE.getDocument())
+                       .addClass("ui-slider-label")
+                       .attr("for", "input-slider-" + id)
+                       .html(label + ":")
+                       .appendTo($ctr);
+
+               var $value = $j("<div></div>", PE.getDocument())
+                       .addClass("ui-slider-value")
+                       .html(defaultVal());
+
+               var $valueField = $j("<input type='hidden'>", PE.getDocument())
+                       .attr("id", "input-hidden-" + id)
+                       .val(defaultVal())
+                       .appendTo($ctr);
+
+               var performOnChange = true;
+
+               var $slider = $j("<div class='ui-slider'><div class='ui-slider-handle'></div><div class='ui-slider-range'></div></div>", PE.getDocument())
+                       .appendTo($ctr)
+                       .attr("id", "input-slider-" + id)
+                       .slider({
+                               slide: function() {
+                                       $value.html($j(this).slider("value"));
+                                       $valueField.val($j(this).slider("value"));
+                               },
+                               change : function() {
+                                       $value.html($j(this).slider("value"));
+                                       $valueField.val($j(this).slider("value"));
+                                       if (onChange && performOnChange)
+                                               onChange();
+                               },
+                               min : min,
+                               max : max,
+                               step : step,
+                               value : defaultVal()
+                       });
+
+               $value.appendTo($ctr);
+
+               return {
+                       container : $ctr,
+                       label : $label,
+                       slider : $slider,
+                       valueText : $value,
+                       valueField : $valueField,
+                       reset : function() {
+                               performOnChange = false;
+                               $value.html(defaultVal());
+                               $valueField.val(defaultVal());
+                               $slider.slider("value", defaultVal());
+                               performOnChange = true;
+                       }
+               };
+       }
+
+       function makeCheckbox(label, id, defaultVal, onChange) {
+               var $ctr = $j("<div></div>", PE.getDocument())
+                       .addClass("ui-checkbox-container");
+
+               var $label = $j("<label></label>", PE.getDocument())
+                       .addClass("ui-checkbox-label")
+                       .attr("for", "input-checkbox-" + id)
+                       .html(label + ":")
+                       .appendTo($ctr);
+
+               var $valueField = $j("<input type='hidden'>", PE.getDocument())
+                       .attr("id", "input-hidden-" + id)
+                       .val(defaultVal())
+                       .appendTo($ctr);
+
+               var performOnChange = true;
+
+               var $checkbox = $j("<input type=\"checkbox\"></input>", PE.getDocument())
+                       .addClass("ui-checkbox")
+                       .attr("id", "input-checkbox-" + id)
+                       .attr("checked", defaultVal())
+                       .appendTo($ctr)
+                       .change(function() {
+                               $valueField.val(this.checked);
+                               if (onChange && performOnChange)
+                                       onChange();
+                       });
+
+               return {
+                       container : $ctr,
+                       label : $label,
+                       checkbox : $checkbox,
+                       valueField : $valueField,
+                       reset : function() {
+                               performOnChange = false;
+                               $checkbox.attr("checked", defaultVal());
+                               $valueField.val(defaultVal());
+                               performOnChange = true;
+                       }
+               };
+       }
+
+       function makeSelect(label, id, values, defaultVal, onChange) {
+               var $ctr = $j("<div></div>", PE.getDocument())
+                       .addClass("ui-select-container");
+
+               var $label = $j("<label></label>", PE.getDocument())
+                       .addClass("ui-checkbox-label")
+                       .attr("for", "input-checkbox-" + id)
+                       .html(label + ":")
+                       .appendTo($ctr);
+
+               var $valueField = $j("<input type='hidden'>", PE.getDocument())
+                       .attr("id", "input-hidden-" + id)
+                       .val(defaultVal())
+                       .appendTo($ctr);
+
+               var selectHtml = "<select>";
+               for (var i=0;i<values.length;i++) {
+                       selectHtml += "<option value='" + values[i].value + "' " 
+                               + (defaultVal() == values[i].value ? "selected" : "") 
+                               + ">" + values[i].name + "</option>";
+               }
+               selectHtml += "</select>";
+
+               var $select = $j(selectHtml).appendTo($ctr);
+
+               var performOnChange = true;
+
+               $select.change(
+                       function() {
+                               $valueField.val(this.options[this.selectedIndex].value);
+                               if (onChange && performOnChange)
+                                       onChange();
+                       }
+               );
+
+               return {
+                       container : $ctr,
+                       label : $label,
+                       select : $select,
+                       valueField : $valueField,
+                       reset : function() {
+                               performOnChange = false;
+                               var defVal = defaultVal();
+                               $select.val(defVal);
+                               $valueField.val(defVal);
+                               performOnChange = true;
+                       }
+               };
+       }
+
+       function makeNumericInput(label, labelRight, id, min, max, step, defaultVal, onChange) {
+               var $ctr = $j("<div></div>", PE.getDocument())
+                       .addClass("ui-textinput-container");
+
+               var $label = $j("<label></label>", PE.getDocument())
+                       .addClass("ui-textinput-label")
+                       .attr("for", "input-numeric-" + id)
+                       .html(label + ":")
+                       .appendTo($ctr);
+
+               var $valueField = $j("<input type='hidden'>", PE.getDocument())
+                       .attr("id", "input-hidden-" + id)
+                       .val(defaultVal())
+                       .appendTo($ctr);
+
+               var performOnChange = true;
+
+               function setVal(val) {
+                       val = Math.min(max, val);
+                       val = Math.max(min, val);
+                       $textInput.val(val);
+                       $valueField.val(val);
+               }
+
+               var $textInput = $j("<input type=\"text\"></input>", PE.getDocument())
+                       .addClass("ui-textinput")
+                       .addClass("ui-numericinput")
+                       .appendTo($ctr)
+                       .val(defaultVal())
+                       .attr("id", "input-numeric-" + id)
+                       .change(function() {
+                               var val = parseFloat(this.value);
+                               setVal(val);
+                               if (onChange && performOnChange)
+                                       onChange();
+                       })
+                       .keydown(function(e) {
+                               var val = parseFloat($j(this).val());
+                               if (e.keyCode == 38) { // up
+                                       setVal(val + step);
+                               }
+                               if (e.keyCode == 40) { // down
+                                       setVal(val - step);
+                               }
+                       });
+
+               if (labelRight) {
+                       var $labelRight = $j("<label></label>", PE.getDocument())
+                               .addClass("ui-textinput-label-right")
+                               .html(labelRight)
+                               .appendTo($ctr);
+               }
+
+               return {
+                       container : $ctr,
+                       label : $label,
+                       textinput : $textInput,
+                       valueField : $valueField,
+                       reset : function() {
+                               performOnChange = false;
+                               setVal(defaultVal());
+                               performOnChange = true;
+                       }
+               };
+       }
+
+       function makeButton(text) {
+               var $button = $j("<button></button>", PE.getDocument()).html(text);
+               return $button;
+       }
+
+
+       PE.UI = {
+               makeSlider : makeSlider,
+               makeCheckbox : makeCheckbox,
+               makeNumericInput : makeNumericInput,
+               makeSelect : makeSelect,
+               makeButton : makeButton
+       }
+
+})(PixasticEditor.jQuery);
+
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/pixastic-editor/uidata.js b/js2/mwEmbed/libClipEdit/pixastic-lib/pixastic-editor/uidata.js
new file mode 100644 (file)
index 0000000..ef648f6
--- /dev/null
@@ -0,0 +1,966 @@
+(function($) {
+
+var PE = PixasticEditor;
+
+PE.UI.data = {
+       tabs : [
+               {
+                       title : "Reshape",
+                       id : "reshape",
+                       actions : [
+                               {
+                                       title : "Resize",
+                                       id : "resize",
+                                       isAction : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Enter new dimensions below."
+                                               },
+                                               {
+                                                       label : "Width",
+                                                       labelRight : "px",
+                                                       option : "width",
+                                                       type : "number", 
+                                                       range : [1,10000], 
+                                                       step : 1,
+                                                       defaultValue : function() { return PE.getImageWidth(); },
+                                                       ui : "text"
+                                               },
+                                               {
+                                                       label : "Height",
+                                                       labelRight : "px",
+                                                       option : "height",
+                                                       type : "number", 
+                                                       range : [1,10000], 
+                                                       step : 1,
+                                                       defaultValue : function() { return PE.getImageHeight(); },
+                                                       ui : "text"
+                                               }
+                                       ]
+                               },
+                               {
+                                       title : "Crop",
+                                       id : "crop",
+                                       isAction : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Enter new crop values below or use mouse to select crop area."
+                                               },
+                                               {
+                                                       label : "X",
+                                                       labelRight : "px",
+                                                       option : "left",
+                                                       type : "number", 
+                                                       range : [0,10000], 
+                                                       step : 1,
+                                                       defaultValue : 0,
+                                                       ui : "text"
+                                               },
+                                               {
+                                                       label : "Y",
+                                                       labelRight : "px",
+                                                       option : "top",
+                                                       type : "number", 
+                                                       range : [0,10000], 
+                                                       step : 1,
+                                                       defaultValue : 0,
+                                                       ui : "text"
+                                               },
+                                               {
+                                                       label : "Width",
+                                                       labelRight : "px",
+                                                       option : "width",
+                                                       type : "number", 
+                                                       range : [1,10000], 
+                                                       step : 1,
+                                                       defaultValue : function() { return PE.getImageWidth(); },
+                                                       ui : "text"
+                                               },
+                                               {
+                                                       label : "Height",
+                                                       labelRight : "px",
+                                                       option : "height",
+                                                       type : "number", 
+                                                       range : [1,10000], 
+                                                       step : 1,
+                                                       defaultValue : function() { return PE.getImageHeight(); },
+                                                       ui : "text"
+                                               }
+                                       ],
+                                       onactivate : function() {
+                                               var $canvas = PE.getDisplayCanvas();
+                                               var onchange = function(c) {
+                                                       var doc = PE.getDocument();
+                                                       $j("#input-numeric-crop-left", doc).val(c.x).change();
+                                                       $j("#input-numeric-crop-top", doc).val(c.y).change();
+                                                       $j("#input-numeric-crop-width", doc).val(c.w).change();
+                                                       $j("#input-numeric-crop-height", doc).val(c.h).change();
+                                                       $j("#input-hidden-crop-left", doc).val(c.x).change();
+                                                       $j("#input-hidden-crop-top", doc).val(c.y).change();
+                                                       $j("#input-hidden-crop-width", doc).val(c.w).change();
+                                                       $j("#input-hidden-crop-height", doc).val(c.h).change();
+                                               }
+                                               $canvas.data("Jcrop-onchange", onchange);
+                                               $canvas.Jcrop({onChange:onchange}, PE.getDocument());
+                                       },
+                                       ondeactivate : function() {
+                                               var $canvas = PE.getDisplayCanvas();
+                                               if ($canvas.data("Jcrop") && $canvas.data("Jcrop").destroy)
+                                                       $canvas.data("Jcrop").destroy();
+                                       },
+                                       onafteraction : function(action, isPreview) {
+                                               action.ondeactivate();
+                                               action.onactivate();
+                                               /*
+                                               var $canvas = PE.getDisplayCanvas();
+                                               if ($canvas.data("Jcrop") && $canvas.data("Jcrop").destroy)
+                                                       $canvas.data("Jcrop").destroy();
+                                               var onchange = $canvas.data("Jcrop-onchange");
+                                               $canvas.Jcrop({onChange:onchange});
+                                               */
+                                       }
+                               },
+                               {
+                                       title : "Rotate",
+                                       id : "rotate",
+                                       isAction : true,
+                                       preview : true,
+                                       forcePreview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Enter the angle (-180&deg; to 180&deg;) you want to rotate the picture. Use negative values for clockwise rotation, positive for counterclockwise."
+                                               },
+                                               {
+                                                       label : "Angle",
+                                                       labelRight : "&deg;",
+                                                       option : "angle",
+                                                       type : "number", 
+                                                       range : [-180,180], 
+                                                       step : 1,
+                                                       defaultValue : 0,
+                                                       ui : "text"
+                                               }
+                                       ],
+                                       onactivate : function() {
+                                               var doc = PE.getDocument();
+                                               var $displayCanvas = PE.getDisplayCanvas();
+                                               var dim = Math.min($displayCanvas.attr("height"), 200);
+                                               var $canvas = $j("<canvas></canvas>", doc);
+                                               PE.getOverlay().append($canvas);
+
+                                               $canvas.attr("width", dim);
+                                               $canvas.attr("height", dim);
+                                               $canvas.width(dim);
+                                               $canvas.height(dim);
+
+                                               $canvas.css("marginTop", (($displayCanvas.attr("height") - dim) * 0.5) + "px");
+
+                                               var lineWidth = 20;
+                                               var radius = dim/2 - lineWidth;
+                                               if (radius < 1) radius = 1;
+
+                                               var ctx = $canvas.get(0).getContext("2d");
+                                               ctx.beginPath()
+                                               ctx.arc(dim/2, dim/2, radius, 0, Math.PI*2, true);
+                                               ctx.closePath();
+                                               ctx.fillStyle = "rgba(200,200,200,0.2)";
+                                               ctx.fill();
+                                               ctx.strokeStyle = "rgba(200,200,200,0.5)";
+                                               ctx.lineWidth = 20;
+                                               ctx.stroke();
+
+                                               $j("#image-area", doc).css("cursor", "move");
+
+                                               $overlay = PE.getOverlay();
+
+                                               $canvas.get(0).ondragstart = function() {return false;}
+                                               $canvas.get(0).onselectstart = function() {return false;}
+
+                                               var mx = 0, my = 0;
+                                               var startMouseAngle = 0;
+                                               var startAngle = 0;
+                                               var deltaAngle = 0;
+                                               var angle = 0;
+
+                                               var mouseIsDown = false;
+                                               var onmousedown = function(e) {
+                                                       mouseIsDown = true;
+                                                       var offset = $displayCanvas.offset();
+                                                       mx = (e.pageX - offset.left) - $displayCanvas.attr("width")*0.5;
+                                                       my = (e.pageY - offset.top) - $displayCanvas.attr("height")*0.5;
+                                                       startMouseAngle = Math.atan2(my, mx);
+                                                       startAngle = parseInt($j("#input-numeric-rotate-angle", doc).val(), 10) * Math.PI / 180;
+                                               }
+                                               var onmousemove = function(e) {
+                                                       if (!mouseIsDown) return;
+
+                                                       var offset = $displayCanvas.offset();
+                                                       mx = (e.pageX - offset.left) - $displayCanvas.attr("width")*0.5;
+                                                       my = (e.pageY - offset.top) - $displayCanvas.attr("height")*0.5;
+                                                       deltaAngle = Math.atan2(my, mx) - startMouseAngle;
+                                                       angle = startAngle - deltaAngle;
+                                                       if (angle < -Math.PI) angle += 2*Math.PI;
+                                                       if (angle > Math.PI) angle -= 2*Math.PI;
+                                                       $j("#input-numeric-rotate-angle", doc).val(Math.round(angle * 180 / Math.PI));
+                                                       $j("#input-numeric-rotate-angle", doc).change();
+                                               }
+                                               var onmouseup = function() {
+                                                       mouseIsDown = false;
+                                               }
+
+                                               $j("#image-area", doc).bind("mousedown", onmousedown);
+                                               $j("#image-area", doc).bind("mousemove", onmousemove);
+                                               $j("#image-area", doc).bind("mouseup", onmouseup);
+                                               $canvas.data("onmousedown", onmousedown);
+                                               $canvas.data("onmousemove", onmousemove);
+                                               $canvas.data("onmouseup", onmouseup);
+                                               $displayCanvas.data("rotateCanvas", $canvas);
+                                       },
+                                       ondeactivate : function() {
+                                               var doc = PE.getDocument();
+                                               var $displayCanvas = PE.getDisplayCanvas();
+                                               $overlay = PE.getOverlay();
+                                               $j("#image-area", doc).css("cursor", "default");
+
+                                               var $canvas = $displayCanvas.data("rotateCanvas");
+
+                                               $j("#image-area", doc).unbind("mousedown", $canvas.data("onmousedown"));
+                                               $j("#image-area", doc).unbind("mousemove", $canvas.data("onmousemove"));
+                                               $j("#image-area", doc).unbind("mouseup", $canvas.data("onmouseup"));
+                                               $displayCanvas.removeData("rotateCanvas");
+                                               $canvas.remove();
+                                       },
+                                       onafteraction : function(action, isPreview) {
+                                               if (!isPreview) { // rebuild the rotate widget
+                                                       action.ondeactivate();
+                                                       action.onactivate();
+                                               }
+                                       },
+                                       onoverlayupdate : function() {
+                                               var $canvas = PE.getDisplayCanvas().data("rotateCanvas");
+                                               if ($canvas) {
+                                                       $canvas.css("marginTop", ((PE.getDisplayCanvas().get(0).height - $canvas.get(0).height) * 0.5) + "px");
+                                               }
+                                       }
+                               },
+                               {
+                                       title : "Flip",
+                                       id : "flip",
+                                       isAction : true,
+                                       controls : [
+                                               {
+                                                       label : "Axis",
+                                                       option : "axis",
+                                                       type : "string", 
+                                                       values : [
+                                                               {name:"Horizontal", value:"horizontal"},
+                                                               {name:"Vertical", value:"vertical"}
+                                                       ],
+                                                       defaultValue : "vertical",
+                                                       ui : "select"
+                                               }
+                                       ]
+                               }
+                       ]
+               },
+               {
+                       title : "Develop",
+                       id : "develop",
+                       actions : [
+                               {
+                                       title : "Brightness & Contrast",
+                                       id : "brightness",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Use the sliders below to adjust the brightness and/or contrast of the image."
+                                               },
+                                               {
+                                                       label : "Brightness",
+                                                       option : "brightness",
+                                                       type : "number", 
+                                                       range : [-100,100], 
+                                                       defaultValue : 0,
+                                                       ui : "slider",
+                                                       step : 1
+                                               },
+                                               {
+                                                       label : "Contrast",
+                                                       option : "contrast",
+                                                       type : "number", 
+                                                       range : [-1,1], 
+                                                       defaultValue : 0,
+                                                       ui : "slider",
+                                                       step : 0.01
+                                               },
+                                               {
+                                                       label : "Legacy mode",
+                                                       option : "legacy",
+                                                       type : "boolean", 
+                                                       defaultValue : false,
+                                                       ui : "checkbox"
+                                               }
+                                       ]
+                               },
+                               {
+                                       title : "Hue/Saturation/Lightness",
+                                       id : "hsl",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Use the sliders below to adjust the hue, saturation and/or lightness of the image."
+                                               },
+                                               {
+                                                       label : "Hue",
+                                                       option : "hue",
+                                                       type : "number", 
+                                                       range : [-180,180], 
+                                                       defaultValue : 0,
+                                                       ui : "slider",
+                                                       step : 1
+                                               },
+                                               {
+                                                       label : "Saturation",
+                                                       option : "saturation",
+                                                       type : "number", 
+                                                       range : [-100,100], 
+                                                       defaultValue : 0,
+                                                       ui : "slider",
+                                                       step : 1
+                                               },
+                                               {
+                                                       label : "Lightness",
+                                                       option : "lightness",
+                                                       type : "number", 
+                                                       range : [-100,100], 
+                                                       defaultValue : 0,
+                                                       ui : "slider",
+                                                       step : 1
+                                               }
+                                       ]
+                               },
+                               {
+                                       title : "Adjust colors",
+                                       id : "coloradjust",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Use the sliders below to shift the R, G and B channels of the image."
+                                               },
+                                               {
+                                                       label : "Red",
+                                                       option : "red",
+                                                       type : "number", 
+                                                       range : [-1,1], 
+                                                       defaultValue : 0,
+                                                       ui : "slider",
+                                                       step : 0.01
+                                               },
+                                               {
+                                                       label : "Green",
+                                                       option : "green",
+                                                       type : "number", 
+                                                       range : [-1,1], 
+                                                       defaultValue : 0,
+                                                       ui : "slider",
+                                                       step : 0.01
+                                               },
+                                               {
+                                                       label : "Blue",
+                                                       option : "blue",
+                                                       type : "number", 
+                                                       range : [-1,1], 
+                                                       defaultValue : 0,
+                                                       ui : "slider",
+                                                       step : 0.01
+                                               }
+                                       ]
+                               },
+                               {
+                                       title : "Desaturate",
+                                       id : "desaturate",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "This will desaturate the image. Select \"Use average\" to use the average value of the R, G and B channels rather than the default mix of 30% red, 59% green and 11% blue."
+                                               },
+                                               {
+                                                       label : "Use average",
+                                                       option : "average",
+                                                       type : "boolean", 
+                                                       defaultValue : false,
+                                                       ui : "checkbox"
+                                               }
+                                       ]
+                               },
+                               {
+                                       title : "Sepia toning",
+                                       id : "sepia",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Applies a sepia toning effect to the image."
+                                               }
+                                       ]
+                               },
+                               {
+                                       title : "Invert",
+                                       id : "invert",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "This will invert the colors of the image."
+                                               }
+                                       ]
+                               },
+                               {
+                                       title : "Lighten",
+                                       id : "lighten",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Use the slider below to lighten or darken the image."
+                                               },
+                                               {
+                                                       label : "Amount",
+                                                       option : "amount",
+                                                       type : "number", 
+                                                       range : [-1,1], 
+                                                       defaultValue : 0,
+                                                       ui : "slider",
+                                                       step : 0.01
+                                               }
+                                       ]
+                               },
+                               {
+                                       title : "Unsharp mask",
+                                       id : "unsharpmask",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Use the sliders below to adjust the unsharp mask parameters."
+                                               },
+                                               {
+                                                       label : "Amount",
+                                                       option : "amount",
+                                                       type : "number", 
+                                                       range : [0,500], 
+                                                       defaultValue : 200,
+                                                       ui : "slider",
+                                                       step : 2
+                                               },
+                                               {
+                                                       label : "Radius",
+                                                       option : "radius",
+                                                       type : "number", 
+                                                       range : [0,5], 
+                                                       defaultValue : 2,
+                                                       ui : "slider",
+                                                       step : 0.1
+                                               },
+                                               {
+                                                       label : "Threshold",
+                                                       option : "amount",
+                                                       type : "number", 
+                                                       range : [0,255], 
+                                                       defaultValue : 25,
+                                                       ui : "slider",
+                                                       step : 1
+                                               }
+                                       ]
+                               }
+
+                       ]
+               },
+               {
+                       title : "Effects",
+                       id : "effects",
+                       actions : [
+                               {
+                                       title : "Blur",
+                                       id : "blurfast",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Use the slider to set the blur amount."
+                                               },
+                                               {
+                                                       label : "Amount",
+                                                       option : "amount",
+                                                       type : "number", 
+                                                       range : [0,1], 
+                                                       defaultValue : 0.5,
+                                                       ui : "slider",
+                                                       step : 0.01
+                                               }
+                                       ]
+
+                               },
+                               {
+                                       title : "Edge detection",
+                                       id : "edges",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Performs edge detection on the image."
+                                               },
+                                               {
+                                                       label : "Greyscale",
+                                                       option : "mono",
+                                                       type : "boolean", 
+                                                       defaultValue : false,
+                                                       ui : "checkbox"
+                                               },
+                                               {
+                                                       label : "Invert",
+                                                       option : "invert",
+                                                       type : "boolean", 
+                                                       defaultValue : false,
+                                                       ui : "checkbox"
+                                               }
+                                       ]
+                               },
+                               {
+                                       title : "Emboss",
+                                       id : "emboss",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Adds an emboss-like effect to the image. Use the controls below to control the appearance of the effect. Choose \"Blend\" to blend the effect with the original image."
+                                               },
+                                               {
+                                                       label : "Strength",
+                                                       option : "strength",
+                                                       type : "number", 
+                                                       range : [0,10], 
+                                                       defaultValue : 1,
+                                                       ui : "slider",
+                                                       step : 0.1
+                                               },
+                                               {
+                                                       label : "Grey level",
+                                                       option : "greyLevel",
+                                                       type : "number", 
+                                                       range : [0,255], 
+                                                       defaultValue : 180,
+                                                       ui : "slider",
+                                                       step : 1
+                                               },
+                                               {
+                                                       label : "Direction",
+                                                       option : "direction",
+                                                       type : "string", 
+                                                       values : [
+                                                               {name:"Top left", value:"topleft"},
+                                                               {name:"Top", value:"top"},
+                                                               {name:"Top right", value:"topright"},
+                                                               {name:"Right", value:"right"},
+                                                               {name:"Bottom right", value:"bottomright"},
+                                                               {name:"Bottom", value:"bottom"},
+                                                               {name:"Bottom left", value:"bottomleft"},
+                                                               {name:"Left", value:"left"}
+                                                       ],
+                                                       defaultValue : "topleft",
+                                                       ui : "select"
+                                               },
+                                               {
+                                                       label : "Blend",
+                                                       option : "blend",
+                                                       type : "boolean", 
+                                                       defaultValue : false,
+                                                       ui : "checkbox"
+                                               }
+                                       ]
+
+                               },
+                               {
+                                       title : "Glow",
+                                       id : "glow",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Creates a glowing effect on the image."
+                                               },
+                                               {
+                                                       label : "Amount",
+                                                       option : "amount",
+                                                       type : "number", 
+                                                       range : [0,1], 
+                                                       defaultValue : 0.5,
+                                                       ui : "slider",
+                                                       step : 0.01
+                                               },
+                                               {
+                                                       label : "Radius",
+                                                       option : "radius",
+                                                       type : "number", 
+                                                       range : [0,1], 
+                                                       defaultValue : 0.5,
+                                                       ui : "slider",
+                                                       step : 0.01
+                                               }
+                                       ]
+                               },
+                               {
+                                       title : "Add noise",
+                                       id : "noise",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Add random noise to the image."
+                                               },
+                                               {
+                                                       label : "Amount",
+                                                       option : "amount",
+                                                       type : "number", 
+                                                       range : [0,1], 
+                                                       defaultValue : 0.5,
+                                                       ui : "slider",
+                                                       step : 0.01
+                                               },
+                                               {
+                                                       label : "Strength",
+                                                       option : "strength",
+                                                       type : "number", 
+                                                       range : [0,1], 
+                                                       defaultValue : 0.5,
+                                                       ui : "slider",
+                                                       step : 0.01
+                                               },
+                                               {
+                                                       label : "Greyscale",
+                                                       option : "mono",
+                                                       type : "boolean", 
+                                                       defaultValue : false,
+                                                       ui : "checkbox"
+                                               }
+                                       ]
+                               },
+                               {
+                                       title : "Remove noise",
+                                       id : "removenoise",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Attempts to remove noise from the image. Works best for getting rid of single pixels that stand out."
+                                               }
+                                       ]
+                               },
+                               {
+                                       title : "Pointillize",
+                                       id : "pointillize",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Paints the picture with circular points."
+                                               },
+                                               {
+                                                       label : "Point radius",
+                                                       option : "radius",
+                                                       type : "number", 
+                                                       range : [1,50], 
+                                                       defaultValue : 5,
+                                                       ui : "slider",
+                                                       step : 1
+                                               },
+                                               {
+                                                       label : "Density",
+                                                       option : "density",
+                                                       type : "number", 
+                                                       range : [0,5], 
+                                                       defaultValue : 1,
+                                                       ui : "slider",
+                                                       step : 0.01
+                                               },
+                                               {
+                                                       label : "Noise",
+                                                       option : "noise",
+                                                       type : "number", 
+                                                       range : [0,2], 
+                                                       defaultValue : 1,
+                                                       ui : "slider",
+                                                       step : 0.01
+                                               },
+                                               {
+                                                       label : "Transparent",
+                                                       option : "transparent",
+                                                       type : "boolean", 
+                                                       defaultValue : false,
+                                                       ui : "checkbox"
+                                               }
+                                       ]
+                               },
+                               {
+                                       title : "Posterize",
+                                       id : "posterize",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Reduces the number of colours to a specified number of levels."
+                                               },
+                                               {
+                                                       label : "Levels",
+                                                       option : "levels",
+                                                       type : "number", 
+                                                       range : [1,32], 
+                                                       defaultValue : 5,
+                                                       ui : "slider",
+                                                       step : 1
+                                               }
+                                       ]
+                               },
+                               {
+                                       title : "Solarize",
+                                       id : "solarize",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Applies a solarize effect to the image."
+                                               }
+                                       ]
+                               },
+                               {
+                                       title : "Mosaic",
+                                       id : "mosaic",
+                                       isAction : true,
+                                       preview : true,
+                                       controls : [
+                                               {
+                                                       type : "output",
+                                                       content : "Creates a pixelated look."
+                                               },
+                                               {
+                                                       label : "Block size",
+                                                       option : "blockSize",
+                                                       type : "number", 
+                                                       range : [1,100], 
+                                                       defaultValue : 5,
+                                                       ui : "slider",
+                                                       step : 1
+                                               }
+                                       ]
+                               }
+
+
+                       ]
+               },
+               {
+                       title : "Done",
+                       id : "done",
+                       actions : [
+                               {
+                                       title : "Save to page",
+                                       id : "savepage",
+                                       content : function($ctr) {
+                                               var doc = PE.getDocument();
+                                               $j("<div></div>", doc)
+                                                       .addClass("action-output-text")
+                                                       .html("This will save the image to the page.")
+                                                       .appendTo($ctr);
+
+                                               var $buttonCtr = $j("<div></div>", doc).appendTo($ctr);
+                                               var $saveButton = $j("<button></button>", doc)
+                                                       .html("Save image")
+                                                       .appendTo($buttonCtr)
+                                                       .click(function() {
+                                                               PE.saveToPage();
+                                                       });
+
+                                       }
+                               },
+                               {
+                                       title : "Save to file",
+                                       id : "savefile",
+                                       content : function(ctr) {
+                                               var doc = PE.getDocument();
+                                               $j("<div></div>", doc)
+                                                       .addClass("action-output-text")
+                                                       .html("This will save the image to your local computer.")
+                                                       .appendTo(ctr);
+
+                                               var formats = PE.validSaveFormats();
+
+                                               var selectHtml = "<select>";
+                                               for (var i=0;i<formats.length;i++) {
+                                                       selectHtml += "<option value='" + formats[i].mime + "'>" + formats[i].name + "</option>";
+                                               }
+                                               selectHtml += "</select>";
+
+                                               var selectCtr = $j("<div></div>", doc)
+                                                       .addClass("ui-select-container");
+
+
+                                               var label = $j("<div></div>", doc)
+                                                       .addClass("ui-select-label")
+                                                       .html("Format:")
+                                                       .appendTo(selectCtr);
+
+                                               var formatSelect = $j(selectHtml, doc).appendTo(selectCtr);
+
+
+                                               selectCtr.appendTo(ctr);
+
+                                               var buttonCtr = $j("<div></div>", doc).appendTo(ctr);
+                                               var saveButton = $j("<button></button>", doc)
+                                                       .html("Save file")
+                                                       .appendTo(buttonCtr)
+
+                                               saveButton.click(function() {
+                                                       var selectElement = formatSelect.get(0);
+                                                       var formatMime = selectElement.options[selectElement.selectedIndex].value;
+                                                       var dataString = PE.getDataURI(formatMime);
+
+                                                       var dialog = $j("<div></div>", doc)
+                                                               .attr("id", "save-dialog")
+                                                               .attr("title", "Download file")
+                                                               .html(
+                                                                       "Right click the link below and select \"Save as...\" to save your file.<br/>"
+                                                                       + "<br/>"
+                                                                       + "<a href=\"" + dataString + "\">Image Link</a>"
+                                                               )
+                                                               .dialog();
+
+                                                       // the dialog is added outside the Pixastic container, so get it back in.
+                                                       var dialogParent = $j(dialog.get(0).parentNode);
+                                                       $j("#pixastic-editor", doc).append(dialogParent);
+                                               });
+                                       }
+                               },
+                               /*
+                               {
+                                       title : "Upload to Flickr",
+                                       id : "flickrupload",
+                                       content : function($ctr) {
+                                               var doc = PE.getDocument();
+
+                                               function flickrAuthed() {
+                                                       var $text = $j("<div />", doc)
+                                                               .addClass("action-output-text")
+                                                               .html("Authorized as: " + PE.Flickr.getAuthName());
+
+                                                       var $buttonCtr = $j("<div></div>", doc);
+                                                       var $uploadButton = $j("<button></button>", doc)
+                                                               .html("Upload image")
+                                                               .appendTo($buttonCtr)
+
+                                                       $uploadButton.click(function() {
+                                                               PE.Flickr.uploadImage(PE.getDataURI());
+                                                       });
+
+                                                       $ctr.append($text, $buttonCtr);
+                                               }
+
+                                               var $authCtr = $j("<div />", doc).appendTo($ctr);
+
+                                               $j("<div />", doc)
+                                                       .addClass("action-output-text")
+                                                       .html("If you have a Flickr account you can now upload your image to Flickr. You will need to give access to your account first. Click the button below to open an authorization window.")
+                                                       .appendTo($authCtr);
+
+                                               var $buttonCtr = $j("<div></div>", doc).appendTo($authCtr);
+                                               var $authButton = $j("<button></button>", doc)
+                                                       .html("Authenticate")
+                                                       .appendTo($buttonCtr)
+
+                                               var checkButtonAdded = false;
+                                               $authButton.click(function() {
+                                                       PE.Flickr.auth();
+                                                       if (!checkButtonAdded) {
+                                                               checkButtonAdded = true;
+
+                                                               var $text = $j("<div />", doc)
+                                                                       .addClass("action-output-text")
+                                                                       .html("Now click the button below when you have authorized access to your Flickr account.");
+       
+                                                               var $buttonCtr = $j("<div></div>", doc);
+       
+                                                               $authCtr.append($text, $buttonCtr);
+       
+                                                               var $checkButton = $j("<button></button>", doc)
+                                                                       .html("I have authenticated!")
+                                                                       .appendTo($buttonCtr);
+       
+                                                               $checkButton.click(function() {
+                                                                       PE.Flickr.checkAuth(function(res) {
+                                                                               if (res.stat == "ok") {
+                                                                                       $authCtr.remove();
+                                                                                       flickrAuthed();
+                                                                               }
+                                                                       });
+                                                               });
+                                                       }
+
+                                               });
+                                       }
+                               },
+                               */
+                               {
+                                       title : "Quit",
+                                       id : "quit", 
+                                       content : function(ctr) {
+                                               var doc = PE.getDocument();
+
+                                               $j("<div>Are you sure you want to quit?</div>", doc)
+                                                       .addClass("action-output-text")
+                                                       .appendTo(ctr);
+                                               var $buttonCtr = $j("<div></div>", doc).appendTo(ctr);
+
+                                               var $quitButton = PE.UI.makeButton("Yes, quit now!")
+                                                       .appendTo($buttonCtr)
+
+                                               $quitButton.click(function() {
+                                                       PE.unload();
+                                               });
+
+                                               var $saveButton = PE.UI.makeButton("Save to page and quit")
+                                                       .appendTo($buttonCtr)
+                                                       .click(function() {
+                                                               PE.saveToPage();
+                                                               PE.unload();
+                                                       });
+                                       }
+                               }
+                       ]
+               }
+       ]
+};
+
+
+})(PixasticEditor.jQuery);
\ No newline at end of file
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/pixastic.core.js b/js2/mwEmbed/libClipEdit/pixastic-lib/pixastic.core.js
new file mode 100644 (file)
index 0000000..5988428
--- /dev/null
@@ -0,0 +1,332 @@
+/*
+ * Pixastic Lib - Core Functions - v0.1.1
+ * Copyright (c) 2008 Jacob Seidelin, cupboy@gmail.com, http://blog.nihilogic.dk/
+ * MIT License [http://www.opensource.org/licenses/mit-license.php]
+ */
+
+var Pixastic = (function() {
+
+
+
+       function addEvent(el, event, handler) {
+               if (el.addEventListener)
+                       el.addEventListener(event, handler, false); 
+               else if (el.attachEvent)
+                       el.attachEvent("on" + event, handler); 
+       }
+
+       function onready(handler) {
+               var handlerDone = false;
+               var execHandler = function() {
+                       if (!handlerDone) {
+                               handlerDone = true;
+                               handler();
+                       }
+               }
+               document.write("<"+"script defer src=\"//:\" id=\"__onload_ie_sumbox__\"></"+"script>");
+               var script = document.getElementById("__onload_ie_sumbox__");
+               script.onreadystatechange = function() {
+                       if (script.readyState == "complete") {
+                               script.parentNode.removeChild(script);
+                               execHandler();
+                       }
+               }
+               if (document.addEventListener)
+                       document.addEventListener("DOMContentLoaded", execHandler, false); 
+               addEvent(window, "load", execHandler);
+       }
+
+
+       function init() {
+               if (!Pixastic.parseOnLoad) return;
+               var imgEls = getElementsByClass("pixastic", null, "img");
+               var canvasEls = getElementsByClass("pixastic", null, "canvas");
+               var elements = imgEls.concat(canvasEls);
+               for (var i=0;i<elements.length;i++) {
+                       (function() {
+
+                       var el = elements[i];
+                       var actions = [];
+                       var classes = el.className.split(" ");
+                       for (var c=0;c<classes.length;c++) {
+                               var cls = classes[c];
+                               if (cls.substring(0,9) == "pixastic-") {
+                                       var actionName = cls.substring(9);
+                                       if (actionName != "")
+                                               actions.push(actionName);
+                               }
+                       }
+                       if (actions.length) {
+                               if (el.tagName == "IMG") {
+                                       var dataImg = new Image();
+                                       dataImg.src = el.src;
+                                       if (dataImg.complete) {
+                                               for (var a=0;a<actions.length;a++) {
+                                                       var res = Pixastic.applyAction(el, el, actions[a], null);
+                                                       if (res) 
+                                                               el = res;
+                                               }
+                                       } else {
+                                               dataImg.onload = function() {
+                                                       for (var a=0;a<actions.length;a++) {
+                                                               var res = Pixastic.applyAction(el, el, actions[a], null)
+                                                               if (res) 
+                                                                       el = res;
+                                                       }
+                                               }
+                                       }
+                               } else {
+                                       setTimeout(function() {
+                                               for (var a=0;a<actions.length;a++) {
+                                                       var res = Pixastic.applyAction(
+                                                               el, el, actions[a], null
+                                                       );
+                                                       if (res) 
+                                                               el = res;
+                                               }
+                                       },1);
+                               }
+                       }
+
+                       })();
+               }
+       }
+
+       onready(init);
+
+
+       // getElementsByClass by Dustin Diaz, http://www.dustindiaz.com/getelementsbyclass/
+       function getElementsByClass(searchClass,node,tag) {
+                       var classElements = new Array();
+                       if ( node == null )
+                                       node = document;
+                       if ( tag == null )
+                                       tag = '*';
+
+                       var els = node.getElementsByTagName(tag);
+                       var elsLen = els.length;
+                       var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
+                       for (i = 0, j = 0; i < elsLen; i++) {
+                                       if ( pattern.test(els[i].className) ) {
+                                                       classElements[j] = els[i];
+                                                       j++;
+                                       }
+                       }
+                       return classElements;
+       }
+
+       var debugElement;
+
+       function writeDebug(text, level) {
+               if (!Pixastic.debug) return;
+
+               try {
+                       switch (level) {
+                               case "warn" : 
+                                       console.warn("Pixastic:", text);
+                                       break;
+                               case "error" :
+                                       console.error("Pixastic:", text);
+                                       break;
+                               default:
+                                       console.log("Pixastic:", text);
+                       }
+               } catch(e) {
+               }
+               if (!debugElement) {
+                       
+               }
+       }
+
+
+       return {
+
+               parseOnLoad : false,
+
+               debug : false,
+               
+               applyAction : function(img, dataImg, actionName, options) {
+
+                       options = options || {};
+
+                       var imageIsCanvas = (img.tagName == "CANVAS");
+                       if (imageIsCanvas && Pixastic.Client.isIE()) {
+                               if (Pixastic.debug) writeDebug("Tried to process a canvas element but browser is IE.");
+                               return false;
+                       }
+
+                       var canvas, ctx;
+                       if (Pixastic.Client.hasCanvas()) {
+                               canvas = document.createElement("canvas");
+                               ctx = canvas.getContext("2d");
+                       }
+
+                       var w = parseInt(img.offsetWidth);
+                       var h = parseInt(img.offsetHeight);
+
+                       if (actionName.indexOf("(") > -1) {
+                               var tmp = actionName;
+                               actionName = tmp.substr(0, tmp.indexOf("("));
+                               var arg = tmp.match(/\((.*?)\)/);
+                               if (arg[1]) {
+                                       arg = arg[1].split(";");
+                                       for (var a=0;a<arg.length;a++) {
+                                               thisArg = arg[a].split("=");
+                                               if (thisArg.length == 2) {
+                                                       if (thisArg[0] == "rect") {
+                                                               var rectVal = thisArg[1].split(",");
+                                                               options[thisArg[0]] = {
+                                                                       left : parseInt(rectVal[0],10)||0,
+                                                                       top : parseInt(rectVal[1],10)||0,
+                                                                       width : parseInt(rectVal[2],10)||0,
+                                                                       height : parseInt(rectVal[3],10)||0
+                                                               }
+                                                       } else {
+                                                               options[thisArg[0]] = thisArg[1];
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+
+                       if (!options.rect) {
+                               options.rect = {
+                                       left : 0, top : 0, width : w, height : h
+                               };
+                       }
+                       var validAction = false;
+                       if (Pixastic.Actions[actionName] && typeof Pixastic.Actions[actionName].process == "function") {
+                               validAction = true;
+                       }
+                       if (!validAction) {
+                               if (Pixastic.debug) writeDebug("Invalid action \"" + actionName + "\". Maybe file not included?");
+                               return false;
+                       }
+                       if (!Pixastic.Actions[actionName].checkSupport()) {
+                               if (Pixastic.debug) writeDebug("Action \"" + actionName + "\" not supported by this browser.");
+                               return false;
+                       }
+
+                       if (Pixastic.Client.hasCanvas()) {
+                               canvas.width = w;
+                               canvas.height = h;
+                               canvas.style.width = w+"px";
+                               canvas.style.height = h+"px";
+                               ctx.drawImage(dataImg,0,0,w,h);
+                       }
+
+                       var params = {
+                               image : img,
+                               canvas : canvas,
+                               width : w,
+                               height : h,
+                               useData : true,
+                               options : options
+                       }
+       
+                       var res = Pixastic.Actions[actionName].process(params);
+
+                       if (!res) {
+                               return false;
+                       }
+
+                       if (Pixastic.Client.hasCanvas()) {
+                               if (params.useData) {
+                                       if (Pixastic.Client.hasCanvasImageData()) {
+                                               canvas.getContext("2d").putImageData(params.canvasData, options.rect.left, options.rect.top);
+                                               // Opera doesn't seem to update the canvas until we draw something on it, lets draw a 0x0 rectangle.
+                                               canvas.getContext("2d").fillRect(0,0,0,0);
+                                       }
+                               }
+                               // copy properties and stuff from the source image
+                               canvas.title = img.title;
+                               canvas.imgsrc = img.imgsrc;
+                               if (!imageIsCanvas) canvas.alt  = img.alt;
+                               if (!imageIsCanvas) canvas.imgsrc = img.src;
+                               canvas.className = img.className;
+                               if (img.getAttribute("style"))
+                                       canvas.setAttribute("style", img.getAttribute("style"));
+                               canvas.cssText = img.cssText;
+                               canvas.name = img.name;
+                               canvas.tabIndex = img.tabIndex;
+                               canvas.id = img.id;
+
+                               if (img.parentNode && img.parentNode.replaceChild) {
+                                       img.parentNode.replaceChild(canvas, img);
+                               }
+
+                               return canvas;
+                       }
+
+                       return img;
+               },
+
+               prepareData : function(params, getCopy) {
+                       var ctx = params.canvas.getContext("2d");
+                       var rect = params.options.rect;
+                       var dataDesc = ctx.getImageData(rect.left, rect.top, rect.width, rect.height);
+                       var data = dataDesc.data;
+                       if (!getCopy) params.canvasData = dataDesc;
+                       return data;
+               },
+
+               // load the image file
+               process : function(img, actionName, options, callback)
+               {
+                       if (img.tagName == "IMG") {
+                               var dataImg = new Image();
+                               dataImg.src = img.src;
+                               if (dataImg.complete) {
+                                       var res = Pixastic.applyAction(img, dataImg, actionName, options);
+                                       if (callback) callback(res);
+                                       return res;
+                               } else {
+                                       dataImg.onload = function() {
+                                               var res = Pixastic.applyAction(img, dataImg, actionName, options)
+                                               if (callback) callback(res);
+                                       }
+                               }
+                       }
+                       if (img.tagName == "CANVAS") {
+                               var res = Pixastic.applyAction(img, img, actionName, options);
+                               if (callback) callback(res);
+                               return res;
+                       }
+               },
+
+               Client : {
+                       hasCanvas : (function() {
+                               var c = document.createElement("canvas");
+                               var val = false;
+                               try {
+                                       val = !!((typeof c.getContext == "function") && c.getContext("2d"));
+                               } catch(e) {}
+                               return function() {
+                                       return val;
+                               }
+                       })(),
+
+                       hasCanvasImageData : (function() {
+                               var c = document.createElement("canvas");
+                               var val = false;
+                               var ctx;
+                               try {
+                                       if (typeof c.getContext == "function" && (ctx = c.getContext("2d"))) {
+                                               val = (typeof ctx.getImageData == "function");
+                                       }
+                               } catch(e) {}
+                               return function() {
+                                       return val;
+                               }
+                       })(),
+
+                       isIE : function() {
+                               return !!document.all && !!window.attachEvent && !window.opera;
+                       }
+               },
+
+               Actions : {}
+       }
+
+
+})();
diff --git a/js2/mwEmbed/libClipEdit/pixastic-lib/pixastic.jquery.js b/js2/mwEmbed/libClipEdit/pixastic-lib/pixastic.jquery.js
new file mode 100644 (file)
index 0000000..7664d29
--- /dev/null
@@ -0,0 +1,22 @@
+
+if (typeof jQuery != "undefined" && jQuery && jQuery.fn) {
+       jQuery.fn.pixastic = function(action, options) {
+               var newElements = [];
+               this.each(
+                       function () {
+                               if (this.tagName == "IMG" && !this.complete) {
+                                       return;
+                               }
+                               var res = Pixastic.process(this, action, options);
+                               if (res) {
+                                       newElements.push(res);
+                               }
+                       }
+               );
+               if (newElements.length > 0)
+                       return jQuery(newElements);
+               else
+                       return this;
+       };
+
+};
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/cortado/README b/js2/mwEmbed/libEmbedVideo/binPlayers/cortado/README
new file mode 100644 (file)
index 0000000..9b2c1ea
--- /dev/null
@@ -0,0 +1 @@
+This version of cortado comes form http://theora.org/cortado.jar
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/cortado/cortado-ovt-stripped-0.5.0.jar b/js2/mwEmbed/libEmbedVideo/binPlayers/cortado/cortado-ovt-stripped-0.5.0.jar
new file mode 100644 (file)
index 0000000..02c541f
Binary files /dev/null and b/js2/mwEmbed/libEmbedVideo/binPlayers/cortado/cortado-ovt-stripped-0.5.0.jar differ
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/LICENSE.txt b/js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/LICENSE.txt
new file mode 100644 (file)
index 0000000..20d40b6
--- /dev/null
@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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 3 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, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
\ No newline at end of file
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/README.txt b/js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/README.txt
new file mode 100644 (file)
index 0000000..22624ed
--- /dev/null
@@ -0,0 +1,52 @@
+Version history:
+
+RC2
+---
+- fixed: setting the screen height in configuration did not have any effect
+
+RC1
+-----
+- better error message if plugin loading fails, shows the URL used
+- validates our redesigned multidomain license key correctly
+- fix to prevent the play button going visible when the onBufferEmpty event occurs
+- the commercial swf now correctly loads the controls using version information
+- fixed: the play button overlay became invisible with long fadeOutSpeeds
+
+beta6
+-----
+- removed the onFirstFramePause event
+- playing a clip for the second time caused a doubled sound
+- pausing on first frame did not work on some FLV files
+
+beta5
+-----
+- logo only uses percentage scaling if it's a SWF file (there is ".swf" in it's url)
+- context menu now correctly builds up from string entries in configuration
+-always closes the previous connection before starting a new clip
+
+beta4
+-----
+- now it's possible to load a plugin into the panel without specifying any position/dimensions
+ information, the plugin is placed to left: "50%", top: "50%" and using the plugin DisplayObject's width & height
+- The Flowplayer API was not fully initialized when onLoad was invoked on Flash plugins
+
+beta3
+-----
+- tweaking logo placement
+- "play" did not show up after repeated pause/resume
+- player now loads the latest controls SWF version, right now the latest SWF is called 'flowplayer.controls-3.0.0-beta2.swf'
+
+beta2
+-----
+- fixed support for RTMP stream groups
+- changed to loop through available fonts in order to find a suitable font also in IE
+- Preloader was broken on IE: When the player SWf was in browser's cache it did not initialize properly
+- Context menu now correctly handles menu items that are configured by their string labels only (not using json objects)
+- fixed custom logo positioning (was moved to the left edge of screen in fullscreen)
+- "play" now always follows the position and size of the screen
+- video was stretched below the controls in fullscreen when autoHide: 'never'
+- logo now takes 6.5% of the screen height, width is scaled so that the aspect ratio is preserved
+
+beta1
+-----
+- First public beta release
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer-3.0.0-rc2.js b/js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer-3.0.0-rc2.js
new file mode 100644 (file)
index 0000000..52f2780
--- /dev/null
@@ -0,0 +1,1520 @@
+/**
+ * flowplayer.js 3.0.0-rc2. The Flowplayer API.
+ * 
+ * This file is part of Flowplayer, http://flowplayer.org
+ *
+ * Author: Tero Piirainen, <support@flowplayer.org>
+ * Copyright (c) 2008 Flowplayer Ltd
+ *
+ * Released under the MIT License:
+ * http://www.opensource.org/licenses/mit-license.php
+ * 
+ * Version: 3.0.0-rc2 - Fri Nov 07 2008 16:50:59 GMT-0000 (GMT+00:00)
+ */
+(function() {
+/* 
+       FEATURES 
+       --------
+       - handling multiple instances 
+       - Flowplayer programming API 
+       - Flowplayer event model        
+       - player loading / unloading
+       - $f() function
+       - jQuery support
+*/ 
+
+/*jslint glovar: true, browser: true */
+/*global flowplayer, $f */
+
+// {{{ private utility methods
+       
+       function log(args) {
+               
+               // write into opera console
+               if (typeof opera == 'object') {
+                       opera.postError("$f.fireEvent: " + args.join(" | "));   
+
+                       
+               } else if (typeof console == 'object') {
+                       console.log("$f.fireEvent", [].slice.call(args));       
+               }
+       }
+
+               
+       // thanks: http://keithdevens.com/weblog/archive/2007/Jun/07/javascript.clone
+       function clone(obj) {   
+               if (!obj || typeof obj != 'object') { return obj; }             
+               var temp = new obj.constructor();       
+               for (var key in obj) {  
+                       if (obj.hasOwnProperty(key)) {
+                               temp[key] = clone(obj[key]);
+                       }
+               }               
+               return temp;
+       }
+
+       // stripped from jQuery, thanks John Resig 
+       function each(obj, fn) {
+               if (!obj) { return; }
+               
+               var name, i = 0, length = obj.length;
+       
+               // object
+               if (length === undefined) {
+                       for (name in obj) {
+                               if (fn.call(obj[name], name, obj[name]) === false) { break; }
+                       }
+                       
+               // array
+               } else {
+                       for (var value = obj[0];
+                               i < length && fn.call( value, i, value ) !== false; value = obj[++i]) {                         
+                       }
+               }
+       
+               return obj;
+       }
+
+       
+       // convenience
+       function el(id) {
+               return document.getElementById(id);     
+       }       
+
+       
+       // used extensively. a very simple implementation. 
+       function extend(to, from, skipFuncs) {
+               if (to && from) {                       
+                       each(from, function(name, value) {
+                               if (!skipFuncs || typeof value != 'function') {
+                                       to[name] = value;               
+                               }
+                       });
+               }
+       }
+       
+       // var arr = select("elem.className"); 
+       function select(query) {
+               var index = query.indexOf("."); 
+               if (index != -1) {
+                       var tag = query.substring(0, index) || "*";
+                       var klass = query.substring(index + 1, query.length);
+                       var els = [];
+                       each(document.getElementsByTagName(tag), function() {
+                               if (this.className && this.className.indexOf(klass) != -1) {
+                                       els.push(this);         
+                               }
+                       });
+                       return els;
+               }
+       }
+       
+       // fix event inconsistencies across browsers
+       function stopEvent(e) {
+               e = e || window.event;
+               
+               if (e.preventDefault) {
+                       e.stopPropagation();
+                       e.preventDefault();
+                       
+               } else {
+                       e.returnValue = false;  
+                       e.cancelBubble = true;
+               } 
+               return false;
+       }
+
+       // push an event listener into existing array of listeners
+       function bind(to, evt, fn) {
+               to[evt] = to[evt] || [];
+               to[evt].push(fn);               
+       }
+       
+       
+       // generates an unique id
+   function makeId() {
+         return "_" + ("" + Math.random()).substring(2, 10);   
+   }
+       
+//}}}  
+       
+
+// {{{ Clip
+
+       var Clip = function(json, index, player) {
+               
+               // private variables
+               var self = this;
+               var cuepoints = {};
+               var listeners = {}; 
+               this.index = index;
+               
+               // instance variables
+               if (typeof json == 'string') {
+                       json = {url:json};      
+               }
+       
+               extend(this, json, true);       
+               
+               // event handling 
+               each(("Start*,MetaData,Pause*,Resume*,Seek*,Stop*,Finish,LastSecond,Update,BufferFull,BufferEmpty").split(","),
+                       function() {
+                       
+                       var evt = "on" + this;
+                               
+                       // before event
+                       if (evt.indexOf("*") != -1) {
+                               evt = evt.substring(0, evt.length -1); 
+                               var before = "onBefore" + evt.substring(2); 
+                               
+                               self[before] = function(fn) {
+                                       bind(listeners, before, fn);
+                                       return self;
+                               };                              
+                       }  
+                       
+                       self[evt] = function(fn) {
+                               bind(listeners, evt, fn);
+                               return self;
+                       };
+                       
+                       
+                       // set common clip event listeners to player level
+                       if (index == -1) {
+                               if (self[before]) {
+                                       player[before] = self[before];          
+                               }                               
+                               if (self[evt])  {
+                                       player[evt] = self[evt];                
+                               }
+                       }
+                       
+               });                       
+               
+               extend(this, {
+                       
+                        
+                       onCuepoint: function(points, fn) {
+                               
+                               // embedded cuepoints
+                               if (arguments.length == 1) {
+                                       cuepoints.embedded = [null, points];
+                                       return self;
+                               }
+                               
+                               if (typeof points == 'number') {
+                                       points = [points];      
+                               }
+                               
+                               var fnId = makeId();  
+                               cuepoints[fnId] = [points, fn]; 
+                               
+                               if (player.isLoaded()) {
+                                       player._api().fp_addCuepoints(points, index, fnId);     
+                               }  
+                               
+                               return self;
+                       },
+                       
+                       update: function(json) {
+                               extend(self, json);
+
+                               if (player.isLoaded()) {
+                                       player._api().fp_updateClip(json, index);       
+                               }
+                               var conf = player._config(); 
+                               var clip = (index == -1) ? conf.clip : conf.playlist[index];
+                               extend(clip, json, true);
+                       },
+                       
+                       
+                       // internal event for performing clip tasks. should be made private someday
+                       _fireEvent: function(evt, arg1, arg2, target) {                                 
+                               
+                               if (evt == 'onLoad') { 
+                                       each(cuepoints, function(key, val) {
+                                               player._api().fp_addCuepoints(val[0], index, key);              
+                                       }); 
+                                       return false;
+                               }                                       
+                               
+                               // target clip we are working against
+                               if (index != -1) {
+                                       target = self;  
+                               }
+                               
+                               if (evt == 'onCuepoint') {
+                                       var fn = cuepoints[arg1];
+                                       if (fn) {
+                                               return fn[1].call(player, target, arg2);
+                                       }
+                               }  
+       
+                               if (evt == 'onMetaData' || evt == 'onUpdate') {
+                                       
+                                       extend(target, arg1);                                   
+                                       
+                                       if (!target.duration) {
+                                               target.duration = arg1.metaData.duration;       
+                                       } else {
+                                               target.fullDuration = arg1.metaData.duration;   
+                                       }                                       
+                               }  
+                               
+                               var ret = true;
+                               each(listeners[evt], function() {
+                                       ret = this.call(player, target, arg1);          
+                               }); 
+                               return ret;                             
+                       }                       
+                       
+               });
+               
+               
+               // get cuepoints from config
+               if (json.onCuepoint) {
+                       self.onCuepoint.apply(self, json.onCuepoint);
+                       delete json.onCuepoint;
+               } 
+               
+               // get other events
+               each(json, function(key, val) {
+                       if (typeof val == 'function') {
+                               bind(listeners, key, val);
+                               delete json[key];       
+                       }
+               });
+
+               
+               // setup common clip event callbacks for Player object too (shortcuts)
+               if (index == -1) {
+                       player.onCuepoint = this.onCuepoint;    
+               }
+       
+       };
+
+//}}}
+
+
+// {{{ Plugin
+               
+       var Plugin = function(name, json, player, fn) {
+       
+               var listeners = {};
+               var self = this;   
+               var hasMethods = false;
+       
+               if (fn) {
+                       extend(listeners, fn);  
+               }   
+               
+               // custom callback functions in configuration
+               each(json, function(key, val) {
+                       if (typeof val == 'function') {
+                               listeners[key] = val;
+                               delete json[key];       
+                       }
+               });  
+               
+               // core plugin methods          
+               extend(this, {
+  
+                       animate: function(props, speed, fn) { 
+                               if (!props) {
+                                       return self;    
+                               }
+                               
+                               if (typeof speed == 'function') { 
+                                       fn = speed; 
+                                       speed = 500;
+                               }
+                               
+                               if (typeof props == 'string') {
+                                       var key = props;
+                                       props = {};
+                                       props[key] = speed;
+                                       speed = 500; 
+                               }
+                               
+                               if (fn) {
+                                       var fnId = makeId();
+                                       listeners[fnId] = fn;
+                               }
+               
+                               if (speed === undefined) { speed = 500; }
+                               json = player._api().fp_animate(name, props, speed, fnId);      
+                               return self;
+                       },
+                       
+                       css: function(props, val) {
+                               if (val !== undefined) {
+                                       var css = {};
+                                       css[props] = val;
+                                       props = css;                                    
+                               }
+                               json = player._api().fp_css(name, props);
+                               extend(self, json);
+                               return self;
+                       },
+                       
+                       show: function() {
+                               this.display = 'block';
+                               player._api().fp_showPlugin(name);
+                               return self;
+                       },
+                       
+                       hide: function() {
+                               this.display = 'none';
+                               player._api().fp_hidePlugin(name);
+                               return self;
+                       },
+                       
+                       toggle: function() {
+                               this.display = player._api().fp_togglePlugin(name);
+                               return self;
+                       },                      
+                       
+                       fadeTo: function(o, speed, fn) {
+                               
+                               if (typeof speed == 'function') { 
+                                       fn = speed; 
+                                       speed = 500;
+                               }
+                               
+                               if (fn) {
+                                       var fnId = makeId();
+                                       listeners[fnId] = fn;
+                               }                               
+                               this.display = player._api().fp_fadeTo(name, o, speed, fnId);
+                               this.opacity = o;
+                               return self;
+                       },
+                       
+                       fadeIn: function(speed, fn) { 
+                               return self.fadeTo(1, speed, fn);                               
+                       },
+       
+                       fadeOut: function(speed, fn) {
+                               return self.fadeTo(0, speed, fn);       
+                       },
+                       
+                       getName: function() {
+                               return name;    
+                       },
+                       
+                       
+                       // internal method not meant to be used by clients
+                _fireEvent: function(evt, arg) {
+
+                               
+                       // update plugins properties & methods
+                       if (evt == 'onUpdate') {
+                          var json = arg || player._api().fp_getPlugin(name); 
+                                       if (!json) { return;    }                                       
+                                       
+                          extend(self, json);
+                          delete self.methods;
+                                       
+                          if (!hasMethods) {
+                                 each(json.methods, function() {
+                                        var method = "" + this;           
+                                                       
+                                        self[method] = function() {
+                                               var a = [].slice.call(arguments);
+                                               var ret = player._api().fp_invoke(name, method, a); 
+                                               return ret == 'undefined' ? self : ret;
+                                        };
+                                 });
+                                 hasMethods = true;             
+                          }
+                       }
+                       
+                       // plugin callbacks
+                       var fn = listeners[evt];
+
+                               if (fn) {
+                                       
+                                       fn.call(self, arg);
+                                       
+                                       // "one-shot" callback
+                                       if (evt.substring(0, 1) == "_") {
+                                               delete listeners[evt];  
+                                       } 
+                       }                
+                }                                      
+                       
+               });
+
+       };
+
+
+//}}}
+
+
+function Player(wrapper, params, conf) {   
+               
+       // private variables (+ arguments)
+       var 
+               self = this, 
+               api = null, 
+               html, 
+               commonClip, 
+               playlist = [], 
+               plugins = {},
+               listeners = {},
+               playerId,
+               apiId,
+               activeIndex,
+               swfHeight;      
+
+  
+// {{{ public methods 
+       
+       extend(self, {
+                       
+               id: function() {
+                       return playerId;        
+               }, 
+               
+               isLoaded: function() {
+                       return (api !== null);  
+               },
+               
+               getParent: function() {
+                       return wrapper; 
+               },
+               
+               hide: function() {
+                       if (api) { api.style.height = "0px"; } 
+                       return self;
+               },
+
+               show: function() {
+                       if (api) { api.style.height = swfHeight + "px"; }
+                       return self;
+               }, 
+                                       
+               isHidden: function() {
+                       return api && parseInt(api.style.height, 10) === 0;
+               },
+               
+               
+               load: function(fn) { 
+                       
+                       if (!api && self._fireEvent("onBeforeLoad") !== false) {
+                               
+                               // unload all instances
+                               each(players, function()  {
+                                       this.unload();          
+                               });
+                               
+                               html = wrapper.innerHTML; 
+                               flashembed(wrapper, params, {config: conf});
+                               
+                               // function argument
+                               if (fn) {
+                                       fn.cached = true;
+                                       bind(listeners, "onLoad", fn);  
+                               }
+                       }
+                       
+                       return self;    
+               },
+               
+               unload: function() {  
+                       
+                if (api && html.replace(/\s/g, '') !== '' && !api.fp_isFullscreen() && 
+                       self._fireEvent("onBeforeUnload") !== false) { 
+                               api.fp_close();
+                               wrapper.innerHTML = html; 
+                               self._fireEvent("onUnload");
+                               api = null;
+                       }
+                       
+                       return self;
+               },
+
+               getClip: function(index) {
+                       if (index === undefined) {
+                               index = activeIndex;    
+                       }
+                       return playlist[index];
+               },
+               
+               
+               getCommonClip: function() {
+                       return commonClip;      
+               },              
+               
+               getPlaylist: function() {
+                       return playlist; 
+               },
+               
+         getPlugin: function(name) {  
+                var plugin = plugins[name];
+                
+                       // create plugin if nessessary
+                if (!plugin && self.isLoaded()) {
+                               var json = self._api().fp_getPlugin(name);
+                               if (json) {
+                                       plugin = new Plugin(name, json, self);
+                                       plugins[name] = plugin;                                                 
+                               } 
+                }              
+                return plugin; 
+         },
+               
+               getScreen: function() { 
+                       return self.getPlugin("screen");
+               }, 
+               
+               getControls: function() { 
+                       return self.getPlugin("controls");
+               }, 
+
+               getConfig: function() { 
+                       return clone(conf);
+               },
+               
+               getFlashParams: function() { 
+                       return params;
+               },              
+               
+               loadPlugin: function(name, url, props, fn) { 
+
+                       // properties not supplied                      
+                       if (typeof props == 'function') { 
+                               fn = props; 
+                               props = {};
+                       } 
+                       
+                       // if fn not given, make a fake id so that plugin's onUpdate get's fired
+                       var fnId = fn ? makeId() : "_"; 
+                       self._api().fp_loadPlugin(name, url, props, fnId); 
+                       
+                       // create new plugin
+                       var arg = {};
+                       arg[fnId] = fn;
+                       var p = new Plugin(name, null, self, arg);
+                       plugins[name] = p;
+                       return p;                       
+               },
+               
+               
+               getState: function() {
+                       return api ? api.fp_getState() : -1;
+               },
+               
+               // "lazy" play
+               play: function(clip) {
+                       
+                       function play() {
+                               if (clip !== undefined) {
+                                       self._api().fp_play(clip);
+                               } else {
+                                       self._api().fp_play();  
+                               }
+                       }
+                       
+                       if (api) {
+                               play();
+                               
+                       } else {
+                               self.load(function() { 
+                                       play();
+                               });
+                       }
+                       
+                       return self;
+               },
+               
+               getVersion: function() {
+                       var js = "flowplayer.js 3.0.0-rc2";
+                       if (api) {
+                               var ver = api.fp_getVersion();
+                               ver.push(js);
+                               return ver;
+                       }
+                       return js; 
+               },
+               
+               _api: function() {
+                       if (!api) {
+                               throw "Flowplayer " +self.id()+ " not loaded. Try moving your call to player's onLoad event";
+                       }
+                       return api;                             
+               },
+               
+               _config: function() {
+                       return conf;    
+               }
+               
+       }); 
+       
+       
+       // event handlers
+       each(("Click*,Load*,Unload*,Keypress*,Volume*,Mute*,Unmute*,PlaylistReplace,Fullscreen*,FullscreenExit,Error").split(","),
+               function() {             
+                       var name = "on" + this;
+                       
+                       // before event
+                       if (name.indexOf("*") != -1) {
+                               name = name.substring(0, name.length -1); 
+                               var name2 = "onBefore" + name.substring(2);
+                               self[name2] = function(fn) {
+                                       bind(listeners, name2, fn);     
+                                       return self;
+                               };                                              
+                       }
+                       
+                       // normal event
+                       self[name] = function(fn) {
+                               bind(listeners, name, fn);      
+                               return self;
+                       };                       
+               }
+       ); 
+       
+       
+       // core API methods
+       each(("pause,resume,mute,unmute,stop,toggle,seek,getStatus,getVolume,setVolume,getTime,isPaused,isPlaying,startBuffering,stopBuffering,isFullscreen,reset").split(","),         
+               function() {             
+                       var name = this;
+                       
+                       self[name] = function(arg) {
+                               if (!api) { return self; }
+                               var ret = (arg === undefined) ? api["fp_" + name]() : api["fp_" + name](arg);
+                               return ret == 'undefined' ? self : ret;
+                       };                       
+               }
+       );              
+       
+//}}}
+
+
+// {{{ public method: _fireEvent
+               
+       self._fireEvent = function(evt, arg0, arg1, arg2) {             
+                               
+               if (conf.debug) {
+                       log(arguments);         
+               }                               
+               
+               // internal onLoad
+               if (evt == 'onLoad' && !api) {  
+                       
+                       api = api || el(apiId); 
+                       swfHeight = api.clientHeight;
+                       
+                       each(playlist, function() {
+                               this._fireEvent("onLoad");              
+                       });
+                       
+                       each(plugins, function(name, p) {
+                               p._fireEvent("onUpdate");               
+                       });
+                       
+                       
+                       commonClip._fireEvent("onLoad");  
+               }
+               
+         if (evt == 'onContextMenu') {
+                each(conf.contextMenu[arg0], function(key, fn)  {
+                       fn.call(self);
+                });
+                return;
+         }
+
+               if (evt == 'onPluginEvent') {
+                       var name = arg0.name || arg0;
+                       var p = plugins[name];
+                       if (p) {
+                               if (arg0.name) {
+                                       p._fireEvent("onUpdate", arg0);         
+                               }
+                               p._fireEvent(arg1);             
+                       }
+                       return;
+               }               
+
+               // onPlaylistReplace
+               if (evt == 'onPlaylistReplace') {
+                       playlist = [];
+                       var index = 0;
+                       each(arg0, function() {
+                               playlist.push(new Clip(this, index++));
+                       });             
+               }
+               
+               var ret = true;
+               
+               // clip event
+               if (arg0 === 0 || (arg0 && arg0 >= 0)) {
+                       
+                       activeIndex = arg0;
+                       var clip = playlist[arg0];                      
+                       
+                       if (!clip || clip._fireEvent(evt, arg1, arg2) !== false) {
+                               
+                               // clip argument is given for common clip, because it behaves as the target
+                               ret = commonClip._fireEvent(evt, arg1, arg2, clip);     
+                       }  
+               } 
+               
+               // player event 
+               var i = 0;
+               each(listeners[evt], function() {
+                       ret = this.call(self, arg0);            
+                       
+                       // remove cached entry
+                       if (this.cached) {
+                               listeners[evt].splice(i, 1);    
+                       }
+                       
+                       // break loop
+                       if (ret === false) { return false;       }
+                       i++;
+                       
+               }); 
+
+               return ret;
+       };
+
+//}}}
+
+// {{{ init
+       
+   function init() {
+               
+               if ($f(wrapper)) {
+                       return null;    
+               }               
+               
+               // register this player into global array of instances
+               players.push(self);  
+               
+               
+               // flashembed parameters
+               if (typeof params == 'string') {
+                       params = {src: params}; 
+               }       
+               
+               // playerId     
+               playerId = wrapper.id || "fp" + makeId();
+               apiId = params.id || playerId + "_api";                 
+               params.id = apiId;
+               conf.playerId = playerId;
+               
+               
+               // plain url is given as config
+               if (typeof conf == 'string') {
+                       conf = {clip:{url:conf}};       
+               } 
+               
+               // common clip is always there
+               conf.clip = conf.clip || {};
+               commonClip = new Clip(conf.clip, -1, self);  
+               
+               
+               // wrapper href as playlist
+               if (wrapper.getAttribute("href")) { 
+                       conf.playlist = [{url:wrapper.getAttribute("href", 2)}];                        
+               } 
+               
+               // playlist
+               conf.playlist = conf.playlist || [conf.clip]; 
+               
+               var index = 0;
+               each(conf.playlist, function() {
+
+                       var clip = this;
+                       
+                       // clip is an array, we don't allow that
+                       if (typeof clip == 'object' && clip.length)  {
+                               clip = "" + clip;       
+                       }
+                       
+                       if (!clip.url && typeof clip == 'string') {                             
+                               clip = {url: clip};                             
+                       } 
+                       
+                       // populate common clip properties to each clip
+                       extend(clip, conf.clip, true);          
+                       
+                       // modify configuration playlist
+                       conf.playlist[index] = clip;                    
+                       
+                       // populate playlist array
+                       clip = new Clip(clip, index, self);
+                       playlist.push(clip);                                            
+                       index++;                        
+               });
+                       
+               
+               // event listeners
+               each(conf, function(key, val) {
+                       if (typeof val == 'function') {
+                               bind(listeners, key, val);
+                               delete conf[key];       
+                       }
+               });              
+               
+               
+               // plugins
+               each(conf.plugins, function(name, val) {
+                       if (val) {
+                               plugins[name] = new Plugin(name, val, self);
+                       }
+               });
+               
+               
+               // setup controlbar plugin if not explicitly defined
+               if (!conf.plugins || conf.plugins.controls === undefined) {
+                       plugins.controls = new Plugin("controls", null, self);  
+               } 
+               
+               // Flowplayer uses black background by default
+               params.bgcolor = params.bgcolor || "#000000";
+               
+               
+               // setup default settings for express install
+               params.version = params.version || [9,0];               
+               params.expressInstall = 'http://www.flowplayer.org/swf/expressinstall.swf';
+               
+               
+               // click function
+               function doClick(e) {
+                       if (self._fireEvent("onBeforeClick") !== false) {
+                               self.load();            
+                       } 
+                       return stopEvent(e);                                    
+               }
+               
+               // defer loading upon click
+               html = wrapper.innerHTML;
+               if (html.replace(/\s/g, '') !== '') {    
+                       
+                       if (wrapper.addEventListener) {
+                               wrapper.addEventListener("click", doClick, false);      
+                               
+                       } else if (wrapper.attachEvent) {
+                               wrapper.attachEvent("onclick", doClick);        
+                       }
+                       
+               // player is loaded upon page load 
+               } else {
+                       
+                       // prevent default action from wrapper (safari problem) loaded
+                       if (wrapper.addEventListener) {
+                               wrapper.addEventListener("click", stopEvent, false);    
+                       }
+                       
+                       // load player
+                       self.load();
+               }
+               
+       }
+
+       // possibly defer initialization until DOM get's loaded
+       if (typeof wrapper == 'string') { 
+               flashembed.domReady(function() {
+                       var node = el(wrapper); 
+                       
+                       if (!node) {
+                               throw "Flowplayer cannot access element: " + wrapper;   
+                       } else {
+                               wrapper = node; 
+                               init();                                 
+                       } 
+               });
+               
+       // we have a DOM element so page is already loaded
+       } else {                
+               init();
+       }
+       
+       
+//}}}
+
+
+}
+
+
+// {{{ flowplayer() & statics 
+
+// container for player instances
+var players = [];
+
+
+// this object is returned when multiple player's are requested 
+function Iterator(arr) {
+       
+       this.length = arr.length;
+       
+       this.each = function(fn)  {
+               each(arr, fn);  
+       };
+       
+       this.size = function() {
+               return arr.length;      
+       };      
+}
+
+// these two variables are the only global variables
+window.flowplayer = window.$f = function() {
+       
+       var instance = null;
+       var arg = arguments[0]; 
+       
+       
+       // $f()
+       if (!arguments.length) {
+               each(players, function() {
+                       if (this.isLoaded())  {
+                               instance = this;        
+                               return false;
+                       }
+               });
+               
+               return instance || players[0];
+       } 
+       
+       if (arguments.length == 1) {
+               
+               // $f(index);
+               if (typeof arg == 'number') { 
+                       return players[arg];    
+       
+                       
+               // $f(wrapper || 'containerId' || '*');
+               } else {
+                       
+                       // $f("*");
+                       if (arg == '*') {
+                               return new Iterator(players);   
+                       }
+                       
+                       // $f(wrapper || 'containerId');
+                       each(players, function() {
+                               if (this.id() == arg.id || this.id() == arg || this.getParent() == arg)  {
+                                       instance = this;        
+                                       return false;
+                               }
+                       });
+                       
+                       return instance;                                        
+               }
+       }                       
+
+       // instance builder 
+       if (arguments.length > 1) {             
+
+               var swf = arguments[1];
+               var conf = (arguments.length == 3) ? arguments[2] : {};
+                                               
+               if (typeof arg == 'string') {
+                       
+                       // select arg by classname
+                       if (arg.indexOf(".") != -1) {
+                               var instances = [];
+                               
+                               each(select(arg), function() { 
+                                       instances.push(new Player(this, clone(swf), clone(conf)));              
+                               });     
+                               
+                               return new Iterator(instances);
+                               
+                       // select node by id
+                       } else {                
+                               var node = el(arg);
+                               return new Player(node !== null ? node : arg, swf, conf);       
+                       } 
+                       
+                       
+               // arg is a DOM element
+               } else if (arg) {
+                       return new Player(arg, swf, conf);                                              
+               }
+               
+       } 
+       
+       return null; 
+};
+       
+extend(window.$f, {
+
+       // called by Flash External Interface           
+       fireEvent: function(id, evt, a0, a1, a2) {              
+               var p = $f(id);         
+               return p ? p._fireEvent(evt, a0, a1, a2) : null;
+       },
+       
+       
+       // create plugins by modifying Player's prototype
+       addPlugin: function(name, fn) {
+               Player.prototype[name] = fn;
+               return $f;
+       },
+       
+       // utility methods for plugin developers
+       each: each,
+       
+       extend: extend
+       
+});
+       
+//}}}
+
+
+//{{{ jQuery support
+
+if (typeof jQuery == 'function') {
+       
+       jQuery.prototype.flowplayer = function(params, conf) {  
+               
+               // select instances
+               if (!arguments.length || typeof arguments[0] == 'number') {
+                       var arr = [];
+                       this.each(function()  {
+                               var p = $f(this);
+                               if (p) {
+                                       arr.push(p);    
+                               }
+                       });
+                       return arguments.length ? arr[arguments[0]] : new Iterator(arr);
+               }
+               
+               // create flowplayer instances
+               return this.each(function() { 
+                       $f(this, clone(params), conf ? clone(conf) : {});       
+               }); 
+               
+       };
+       
+}
+
+//}}}
+
+
+})();
+/** 
+ * flashembed 0.33. Adobe Flash embedding script
+ * 
+ * http://flowplayer.org/tools/flash-embed.html
+ *
+ * Copyright (c) 2008 Tero Piirainen (support@flowplayer.org)
+ *
+ * Released under the MIT License:
+ * http://www.opensource.org/licenses/mit-license.php
+ * 
+ * >> Basically you can do anything you want but leave this header as is <<
+ *
+ * first version 0.01 - 03/11/2008 
+ * version 0.33 - Mon Nov 03 2008 15:37:15 GMT-0000 (GMT+00:00)
+ */
+(function() { 
+//{{{ utility functions 
+               
+var jQ = typeof jQuery == 'function';
+
+
+// from "Pro JavaScript techniques" by John Resig
+function isDomReady() {
+       if (domReady.done)  { return false; }
+       
+       var d = document;
+       if (d && d.getElementsByTagName && d.getElementById && d.body) {
+               clearInterval(domReady.timer);
+               domReady.timer = null;
+               
+               for (var i = 0; i < domReady.ready.length; i++) {
+                       domReady.ready[i].call();       
+               }
+               
+               domReady.ready = null;
+               domReady.done = true;
+       } 
+}
+
+// if jQuery is present, use it's more effective domReady method
+var domReady = jQ ? jQuery : function(f) {
+       
+       if (domReady.done) {
+               return f();     
+       }
+       
+       if (domReady.timer) {
+               domReady.ready.push(f); 
+               
+       } else {
+               domReady.ready = [f];
+               domReady.timer = setInterval(isDomReady, 13);
+       } 
+};     
+
+
+// override extend params function 
+function extend(to, from) {
+       if (from) {
+               for (key in from) {
+                       if (from.hasOwnProperty(key)) {
+                               to[key] = from[key];
+                       }
+               }
+       }
+}      
+
+
+function concatVars(vars) {            
+       var out = "";
+       
+       for (var key in vars) { 
+               if (vars[key]) {
+                       out += [key] + '=' + toString(vars[key]) + '&';
+               }
+       }                       
+       return out.substring(0, out.length -1);                         
+}  
+
+
+
+// JSON.toString() function
+function toString(obj) {
+
+       switch (typeOf(obj)){
+               case 'string':
+                       obj = obj.replace(new RegExp('(["\\\\])', 'g'), '\\$1');
+                       
+                       // flash does not handle %- characters well. transforms "50%" to "50pct" (a dirty hack, I admit)
+                       obj = obj.replace(/^\s?(\d+)%/, "$1pct");
+                       return '"' +obj+ '"';
+                       
+               case 'array':
+                       return '['+ map(obj, function(el) {
+                               return toString(el);
+                       }).join(',') +']'; 
+                       
+               case 'function':
+                       return '"function()"';
+                       
+               case 'object':
+                       var str = [];
+                       for (var prop in obj) {
+                               if (obj.hasOwnProperty(prop)) {
+                                       str.push('"'+prop+'":'+ toString(obj[prop]));
+                               }
+                       }
+                       return '{'+str.join(',')+'}';
+       }
+       
+       // replace ' --> "  and remove spaces
+       return String(obj).replace(/\s/g, " ").replace(/\'/g, "\"");
+}
+
+
+// private functions
+function typeOf(obj) {
+       if (obj === null || obj === undefined) { return false; }
+       var type = typeof obj;
+       return (type == 'object' && obj.push) ? 'array' : type;
+}
+
+
+// version 9 bugfix: (http://blog.deconcept.com/2006/07/28/swfobject-143-released/)
+if (window.attachEvent) {
+       window.attachEvent("onbeforeunload", function() {
+               __flash_unloadHandler = function() {};
+               __flash_savedUnloadHandler = function() {};
+       });
+}
+
+function map(arr, func) {
+       var newArr = []; 
+       for (var i in arr) {
+               if (arr.hasOwnProperty(i)) {
+                       newArr[i] = func(arr[i]);
+               }
+       }
+       return newArr;
+}
+       
+//}}}
+
+       
+window.flashembed = function(root, userParams, flashvars) {    
+       
+       
+//{{{ getHTML 
+               
+       function getHTML() {
+               
+               var html = "";
+               if (typeof flashvars == 'function') { flashvars = flashvars(); }
+               
+               
+               // sometimes ie fails to load flash if it's on cache
+               params.src += ((params.src.indexOf("?") != -1 ? "&" : "?") + Math.random());
+               
+               
+               // mozilla
+               if (navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length) {  
+
+                       html = '<embed type="application/x-shockwave-flash" ';
+
+                       if (params.id) {
+                               extend(params, {name:params.id});
+                       }
+                       
+                       for (var key in params) { 
+                               if (params[key] !== null) { 
+                                       html += [key] + '="' +params[key]+ '"\n\t';
+                               }
+                       }
+
+                       if (flashvars) {
+                                html += 'flashvars=\'' + concatVars(flashvars) + '\'';
+                       }
+                       
+                       // thanks Tom Price (07/17/2008)
+                       html += '/>';
+                       
+               // ie
+               } else { 
+
+                       html = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" ';
+                       html += 'width="' + params.width + '" height="' + params.height + '"'; 
+                       
+                       // force id for IE. otherwise embedded Flash object cannot be returned
+                       if (!params.id && document.all) {
+                               params.id = "_" + ("" + Math.random()).substring(5);
+                       } 
+                       
+                       if (params.id) {
+                               html += ' id="' + params.id + '"';
+                       }
+                       
+                       html += '>';  
+                       html += '\n\t<param name="movie" value="'+ params.src +'" />';
+                       
+                       params.id = params.src = params.width = params.height = null;
+                       
+                       for (var k in params) {
+                               if (params[k] !== null) {
+                                       html += '\n\t<param name="'+ k +'" value="'+ params[k] +'" />';
+                               }
+                       }
+                       
+                       if (flashvars) {
+                               html += '\n\t<param name="flashvars" value=\'' + concatVars(flashvars) + '\' />';
+                       }
+                        
+                       html += "</object>";
+                       if (debug) { 
+                               alert(html);
+                       }
+                       
+               }  
+
+               return html;
+       }
+
+       //}}}
+
+       
+//{{{ construction
+               
+       // setup params
+       var params = {
+               
+               // very common params
+               src: '#',
+               width: '100%',
+               height: '100%',         
+               
+               // flashembed specific options
+               version:null,
+               onFail:null,
+               expressInstall:null,  
+               debug: false,
+               
+               // flashembed defaults
+               // bgcolor: 'transparent',
+               allowfullscreen: true,
+               allowscriptaccess: 'always',
+               quality: 'high',
+               type: 'application/x-shockwave-flash',
+               pluginspage: 'http://www.adobe.com/go/getflashplayer'
+       };
+       
+       
+       if (typeof userParams == 'string') {
+               userParams = {src: userParams}; 
+       }
+       
+       extend(params, userParams);                      
+               
+       var version = flashembed.getVersion(); 
+       var required = params.version; 
+       var express = params.expressInstall;             
+       var debug = params.debug;
+
+       
+       if (typeof root == 'string') {
+               var el = document.getElementById(root);
+               if (el) {
+                       root = el;      
+               } else {
+                       domReady(function() {
+                               flashembed(root, userParams, flashvars);
+                       });
+                       return;                 
+               } 
+       }
+       
+       if (!root) { return; }
+
+       
+       // is supported 
+       if (!required || flashembed.isSupported(required)) {
+               params.onFail = params.version = params.expressInstall = params.debug = null;
+               
+               // root.innerHTML may cause broplems: http://domscripting.com/blog/display/99
+               // thanks to: Ryan Rud
+               // var tmp = document.createElement("extradiv");
+               // tmp.innerHTML = getHTML();
+               // root.appendChild(tmp);
+               
+               root.innerHTML = getHTML();
+               
+               // return our API                       
+               return root.firstChild;
+               
+       // custom fail event
+       } else if (params.onFail) {
+               var ret = params.onFail.call(params, flashembed.getVersion(), flashvars);
+               if (ret === true) { root.innerHTML = ret; }             
+               
+
+       // express install
+       } else if (required && express && flashembed.isSupported([6,65])) {
+               
+               extend(params, {src: express});
+               
+               flashvars = {
+                       MMredirectURL: location.href,
+                       MMplayerType: 'PlugIn',
+                       MMdoctitle: document.title
+               };
+               
+               root.innerHTML = getHTML();     
+               
+       // not supported
+       } else {
+
+               // minor bug fixed here 08.04.2008 (thanks JRodman)
+               
+               if (root.innerHTML.replace(/\s/g, '') !== '') {
+                       // custom content was supplied
+               
+               } else {
+                       root.innerHTML = 
+                               "<h2>Flash version " + required + " or greater is required</h2>" + 
+                               "<h3>" + 
+                                       (version[0] > 0 ? "Your version is " + version : "You have no flash plugin installed") +
+                               "</h3>" + 
+                               "<p>Download latest version from <a href='" + params.pluginspage + "'>here</a></p>";
+               }
+       }
+
+       return root;
+       
+//}}}
+       
+       
+};
+
+
+//{{{ static methods
+
+extend(window.flashembed, {
+
+       // arr[major, minor, fix]
+       getVersion: function() {
+       
+               var version = [0, 0];
+               
+               if (navigator.plugins && typeof navigator.plugins["Shockwave Flash"] == "object") {
+                       var _d = navigator.plugins["Shockwave Flash"].description;
+                       if (typeof _d != "undefined") {
+                               _d = _d.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
+                               var _m = parseInt(_d.replace(/^(.*)\..*$/, "$1"), 10);
+                               var _r = /r/.test(_d) ? parseInt(_d.replace(/^.*r(.*)$/, "$1"), 10) : 0;
+                               version = [_m, _r];
+                       }
+                       
+               } else if (window.ActiveXObject) {
+                       
+                       try { // avoid fp 6 crashes
+                               var _a = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
+                               
+                       } catch(e) {
+                               try { 
+                                       _a = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
+                                       version = [6, 0];
+                                       _a.AllowScriptAccess = "always"; // throws if fp < 6.47 
+                                       
+                               } catch(ee) {
+                                       if (version[0] == 6) { return; }
+                               }
+                               try {
+                                       _a = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
+                               } catch(eee) {
+                               
+                               }
+                               
+                       }
+                       
+                       if (typeof _a == "object") {
+                               _d = _a.GetVariable("$version"); // bugs in fp 6.21 / 6.23
+                               if (typeof _d != "undefined") {
+                                       _d = _d.replace(/^\S+\s+(.*)$/, "$1").split(",");
+                                       version = [parseInt(_d[0], 10), parseInt(_d[2], 10)];
+                               }
+                       }
+               } 
+               
+               return version;
+       },
+       
+       isSupported: function(version) {
+               var now = flashembed.getVersion();
+               var ret = (now[0] > version[0]) || (now[0] == version[0] && now[1] >= version[1]);                      
+               return ret;
+       },
+       
+       domReady: domReady,
+       
+       // returns a String representation from JSON object 
+       toString: toString
+       
+});
+
+//}}}
+
+
+// setup jquery support
+if (jQ) {
+       
+       jQuery.prototype.flashembed = function(params, flashvars) { 
+               return this.each(function() { 
+                       flashembed(this, params, flashvars);
+               });
+       };
+
+}
+
+})();
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer-3.0.0-rc2.min.js b/js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer-3.0.0-rc2.min.js
new file mode 100644 (file)
index 0000000..a0fcabd
--- /dev/null
@@ -0,0 +1,15 @@
+/**
+ * flowplayer.js 3.0.0-rc2. The Flowplayer API.
+ * 
+ * This file is part of Flowplayer, http://flowplayer.org
+ *
+ * Author: Tero Piirainen, <support@flowplayer.org>
+ * Copyright (c) 2008 Flowplayer Ltd
+ *
+ * Released under the MIT License:
+ * http://www.opensource.org/licenses/mit-license.php
+ * 
+ * Version: 3.0.0-rc2 - Fri Nov 07 2008 16:50:52 GMT-0000 (GMT+00:00)
+ */
+(function(){function log(args){if(typeof opera=='object'){opera.postError("$f.fireEvent: "+args.join(" | "));}else if(typeof console=='object'){console.log("$f.fireEvent",[].slice.call(args));}}function clone(obj){if(!obj||typeof obj!='object'){return obj;}var temp=new obj.constructor();for(var key in obj){if(obj.hasOwnProperty(key)){temp[key]=clone(obj[key]);}}return temp;}function each(obj,fn){if(!obj){return;}var name,i=0,length=obj.length;if(length===undefined){for(name in obj){if(fn.call(obj[name],name,obj[name])===false){break;}}}else{for(var value=obj[0];i<length&&fn.call(value,i,value)!==false;value=obj[++i]){}}return obj;}function el(id){return document.getElementById(id);}function extend(to,from,skipFuncs){if(to&&from){each(from,function(name,value){if(!skipFuncs||typeof value!='function'){to[name]=value;}});}}function select(query){var index=query.indexOf(".");if(index!=-1){var tag=query.substring(0,index)||"*";var klass=query.substring(index+1,query.length);var els=[];each(document.getElementsByTagName(tag),function(){if(this.className&&this.className.indexOf(klass)!=-1){els.push(this);}});return els;}}function stopEvent(e){e=e||window.event;if(e.preventDefault){e.stopPropagation();e.preventDefault();}else{e.returnValue=false;e.cancelBubble=true;}return false;}function bind(to,evt,fn){to[evt]=to[evt]||[];to[evt].push(fn);}function makeId(){return"_"+(""+Math.random()).substring(2,10);}var Clip=function(json,index,player){var self=this;var cuepoints={};var listeners={};this.index=index;if(typeof json=='string'){json={url:json};}extend(this,json,true);each(("Start*,MetaData,Pause*,Resume*,Seek*,Stop*,Finish,LastSecond,Update,BufferFull,BufferEmpty").split(","),function(){var evt="on"+this;if(evt.indexOf("*")!=-1){evt=evt.substring(0,evt.length-1);var before="onBefore"+evt.substring(2);self[before]=function(fn){bind(listeners,before,fn);return self;};}self[evt]=function(fn){bind(listeners,evt,fn);return self;};if(index==-1){if(self[before]){player[before]=self[before];}if(self[evt]){player[evt]=self[evt];}}});extend(this,{onCuepoint:function(points,fn){if(arguments.length==1){cuepoints.embedded=[null,points];return self;}if(typeof points=='number'){points=[points];}var fnId=makeId();cuepoints[fnId]=[points,fn];if(player.isLoaded()){player._api().fp_addCuepoints(points,index,fnId);}return self;},update:function(json){extend(self,json);if(player.isLoaded()){player._api().fp_updateClip(json,index);}var conf=player._config();var clip=(index==-1)?conf.clip:conf.playlist[index];extend(clip,json,true);},_fireEvent:function(evt,arg1,arg2,target){if(evt=='onLoad'){each(cuepoints,function(key,val){player._api().fp_addCuepoints(val[0],index,key);});return false;}if(index!=-1){target=self;}if(evt=='onCuepoint'){var fn=cuepoints[arg1];if(fn){return fn[1].call(player,target,arg2);}}if(evt=='onMetaData'||evt=='onUpdate'){extend(target,arg1);if(!target.duration){target.duration=arg1.metaData.duration;}else{target.fullDuration=arg1.metaData.duration;}}var ret=true;each(listeners[evt],function(){ret=this.call(player,target,arg1);});return ret;}});if(json.onCuepoint){self.onCuepoint.apply(self,json.onCuepoint);delete json.onCuepoint;}each(json,function(key,val){if(typeof val=='function'){bind(listeners,key,val);delete json[key];}});if(index==-1){player.onCuepoint=this.onCuepoint;}};var Plugin=function(name,json,player,fn){var listeners={};var self=this;var hasMethods=false;if(fn){extend(listeners,fn);}each(json,function(key,val){if(typeof val=='function'){listeners[key]=val;delete json[key];}});extend(this,{animate:function(props,speed,fn){if(!props){return self;}if(typeof speed=='function'){fn=speed;speed=500;}if(typeof props=='string'){var key=props;props={};props[key]=speed;speed=500;}if(fn){var fnId=makeId();listeners[fnId]=fn;}if(speed===undefined){speed=500;}json=player._api().fp_animate(name,props,speed,fnId);return self;},css:function(props,val){if(val!==undefined){var css={};css[props]=val;props=css;}json=player._api().fp_css(name,props);extend(self,json);return self;},show:function(){this.display='block';player._api().fp_showPlugin(name);return self;},hide:function(){this.display='none';player._api().fp_hidePlugin(name);return self;},toggle:function(){this.display=player._api().fp_togglePlugin(name);return self;},fadeTo:function(o,speed,fn){if(typeof speed=='function'){fn=speed;speed=500;}if(fn){var fnId=makeId();listeners[fnId]=fn;}this.display=player._api().fp_fadeTo(name,o,speed,fnId);this.opacity=o;return self;},fadeIn:function(speed,fn){return self.fadeTo(1,speed,fn);},fadeOut:function(speed,fn){return self.fadeTo(0,speed,fn);},getName:function(){return name;},_fireEvent:function(evt,arg){if(evt=='onUpdate'){var json=arg||player._api().fp_getPlugin(name);if(!json){return;}extend(self,json);delete self.methods;if(!hasMethods){each(json.methods,function(){var method=""+this;self[method]=function(){var a=[].slice.call(arguments);var ret=player._api().fp_invoke(name,method,a);return ret=='undefined'?self:ret;};});hasMethods=true;}}var fn=listeners[evt];if(fn){fn.call(self,arg);if(evt.substring(0,1)=="_"){delete listeners[evt];}}}});};function Player(wrapper,params,conf){var
+self=this,api=null,html,commonClip,playlist=[],plugins={},listeners={},playerId,apiId,activeIndex,swfHeight;extend(self,{id:function(){return playerId;},isLoaded:function(){return(api!==null);},getParent:function(){return wrapper;},hide:function(){if(api){api.style.height="0px";}return self;},show:function(){if(api){api.style.height=swfHeight+"px";}return self;},isHidden:function(){return api&&parseInt(api.style.height,10)===0;},load:function(fn){if(!api&&self._fireEvent("onBeforeLoad")!==false){each(players,function(){this.unload();});html=wrapper.innerHTML;flashembed(wrapper,params,{config:conf});if(fn){fn.cached=true;bind(listeners,"onLoad",fn);}}return self;},unload:function(){if(api&&html.replace(/\s/g,'')!==''&&!api.fp_isFullscreen()&&self._fireEvent("onBeforeUnload")!==false){api.fp_close();wrapper.innerHTML=html;self._fireEvent("onUnload");api=null;}return self;},getClip:function(index){if(index===undefined){index=activeIndex;}return playlist[index];},getCommonClip:function(){return commonClip;},getPlaylist:function(){return playlist;},getPlugin:function(name){var plugin=plugins[name];if(!plugin&&self.isLoaded()){var json=self._api().fp_getPlugin(name);if(json){plugin=new Plugin(name,json,self);plugins[name]=plugin;}}return plugin;},getScreen:function(){return self.getPlugin("screen");},getControls:function(){return self.getPlugin("controls");},getConfig:function(){return clone(conf);},getFlashParams:function(){return params;},loadPlugin:function(name,url,props,fn){if(typeof props=='function'){fn=props;props={};}var fnId=fn?makeId():"_";self._api().fp_loadPlugin(name,url,props,fnId);var arg={};arg[fnId]=fn;var p=new Plugin(name,null,self,arg);plugins[name]=p;return p;},getState:function(){return api?api.fp_getState():-1;},play:function(clip){function play(){if(clip!==undefined){self._api().fp_play(clip);}else{self._api().fp_play();}}if(api){play();}else{self.load(function(){play();});}return self;},getVersion:function(){var js="flowplayer.js 3.0.0-rc2";if(api){var ver=api.fp_getVersion();ver.push(js);return ver;}return js;},_api:function(){if(!api){throw"Flowplayer "+self.id()+" not loaded. Try moving your call to player's onLoad event";}return api;},_config:function(){return conf;}});each(("Click*,Load*,Unload*,Keypress*,Volume*,Mute*,Unmute*,PlaylistReplace,Fullscreen*,FullscreenExit,Error").split(","),function(){var name="on"+this;if(name.indexOf("*")!=-1){name=name.substring(0,name.length-1);var name2="onBefore"+name.substring(2);self[name2]=function(fn){bind(listeners,name2,fn);return self;};}self[name]=function(fn){bind(listeners,name,fn);return self;};});each(("pause,resume,mute,unmute,stop,toggle,seek,getStatus,getVolume,setVolume,getTime,isPaused,isPlaying,startBuffering,stopBuffering,isFullscreen,reset").split(","),function(){var name=this;self[name]=function(arg){if(!api){return self;}var ret=(arg===undefined)?api["fp_"+name]():api["fp_"+name](arg);return ret=='undefined'?self:ret;};});self._fireEvent=function(evt,arg0,arg1,arg2){if(conf.debug){log(arguments);}if(evt=='onLoad'&&!api){api=api||el(apiId);swfHeight=api.clientHeight;each(playlist,function(){this._fireEvent("onLoad");});each(plugins,function(name,p){p._fireEvent("onUpdate");});commonClip._fireEvent("onLoad");}if(evt=='onContextMenu'){each(conf.contextMenu[arg0],function(key,fn){fn.call(self);});return;}if(evt=='onPluginEvent'){var name=arg0.name||arg0;var p=plugins[name];if(p){if(arg0.name){p._fireEvent("onUpdate",arg0);}p._fireEvent(arg1);}return;}if(evt=='onPlaylistReplace'){playlist=[];var index=0;each(arg0,function(){playlist.push(new Clip(this,index++));});}var ret=true;if(arg0===0||(arg0&&arg0>=0)){activeIndex=arg0;var clip=playlist[arg0];if(!clip||clip._fireEvent(evt,arg1,arg2)!==false){ret=commonClip._fireEvent(evt,arg1,arg2,clip);}}var i=0;each(listeners[evt],function(){ret=this.call(self,arg0);if(this.cached){listeners[evt].splice(i,1);}if(ret===false){return false;}i++;});return ret;};function init(){if($f(wrapper)){return null;}players.push(self);if(typeof params=='string'){params={src:params};}playerId=wrapper.id||"fp"+makeId();apiId=params.id||playerId+"_api";params.id=apiId;conf.playerId=playerId;if(typeof conf=='string'){conf={clip:{url:conf}};}conf.clip=conf.clip||{};commonClip=new Clip(conf.clip,-1,self);if(wrapper.getAttribute("href")){conf.playlist=[{url:wrapper.getAttribute("href",2)}];}conf.playlist=conf.playlist||[conf.clip];var index=0;each(conf.playlist,function(){var clip=this;if(typeof clip=='object'&&clip.length){clip=""+clip;}if(!clip.url&&typeof clip=='string'){clip={url:clip};}extend(clip,conf.clip,true);conf.playlist[index]=clip;clip=new Clip(clip,index,self);playlist.push(clip);index++;});each(conf,function(key,val){if(typeof val=='function'){bind(listeners,key,val);delete conf[key];}});each(conf.plugins,function(name,val){if(val){plugins[name]=new Plugin(name,val,self);}});if(!conf.plugins||conf.plugins.controls===undefined){plugins.controls=new Plugin("controls",null,self);}params.bgcolor=params.bgcolor||"#000000";params.version=params.version||[9,0];params.expressInstall='http://www.flowplayer.org/swf/expressinstall.swf';function doClick(e){if(self._fireEvent("onBeforeClick")!==false){self.load();}return stopEvent(e);}html=wrapper.innerHTML;if(html.replace(/\s/g,'')!==''){if(wrapper.addEventListener){wrapper.addEventListener("click",doClick,false);}else if(wrapper.attachEvent){wrapper.attachEvent("onclick",doClick);}}else{if(wrapper.addEventListener){wrapper.addEventListener("click",stopEvent,false);}self.load();}}if(typeof wrapper=='string'){flashembed.domReady(function(){var node=el(wrapper);if(!node){throw"Flowplayer cannot access element: "+wrapper;}else{wrapper=node;init();}});}else{init();}}var players=[];function Iterator(arr){this.length=arr.length;this.each=function(fn){each(arr,fn);};this.size=function(){return arr.length;};}window.flowplayer=window.$f=function(){var instance=null;var arg=arguments[0];if(!arguments.length){each(players,function(){if(this.isLoaded()){instance=this;return false;}});return instance||players[0];}if(arguments.length==1){if(typeof arg=='number'){return players[arg];}else{if(arg=='*'){return new Iterator(players);}each(players,function(){if(this.id()==arg.id||this.id()==arg||this.getParent()==arg){instance=this;return false;}});return instance;}}if(arguments.length>1){var swf=arguments[1];var conf=(arguments.length==3)?arguments[2]:{};if(typeof arg=='string'){if(arg.indexOf(".")!=-1){var instances=[];each(select(arg),function(){instances.push(new Player(this,clone(swf),clone(conf)));});return new Iterator(instances);}else{var node=el(arg);return new Player(node!==null?node:arg,swf,conf);}}else if(arg){return new Player(arg,swf,conf);}}return null;};extend(window.$f,{fireEvent:function(id,evt,a0,a1,a2){var p=$f(id);return p?p._fireEvent(evt,a0,a1,a2):null;},addPlugin:function(name,fn){Player.prototype[name]=fn;return $f;},each:each,extend:extend});if(typeof jQuery=='function'){jQuery.prototype.flowplayer=function(params,conf){if(!arguments.length||typeof arguments[0]=='number'){var arr=[];this.each(function(){var p=$f(this);if(p){arr.push(p);}});return arguments.length?arr[arguments[0]]:new Iterator(arr);}return this.each(function(){$f(this,clone(params),conf?clone(conf):{});});};}})();(function(){var jQ=typeof jQuery=='function';function isDomReady(){if(domReady.done){return false;}var d=document;if(d&&d.getElementsByTagName&&d.getElementById&&d.body){clearInterval(domReady.timer);domReady.timer=null;for(var i=0;i<domReady.ready.length;i++){domReady.ready[i].call();}domReady.ready=null;domReady.done=true;}}var domReady=jQ?jQuery:function(f){if(domReady.done){return f();}if(domReady.timer){domReady.ready.push(f);}else{domReady.ready=[f];domReady.timer=setInterval(isDomReady,13);}};function extend(to,from){if(from){for(key in from){if(from.hasOwnProperty(key)){to[key]=from[key];}}}}function concatVars(vars){var out="";for(var key in vars){if(vars[key]){out+=[key]+'='+toString(vars[key])+'&';}}return out.substring(0,out.length-1);}function toString(obj){switch(typeOf(obj)){case'string':obj=obj.replace(new RegExp('(["\\\\])','g'),'\\$1');obj=obj.replace(/^\s?(\d+)%/,"$1pct");return'"'+obj+'"';case'array':return'['+map(obj,function(el){return toString(el);}).join(',')+']';case'function':return'"function()"';case'object':var str=[];for(var prop in obj){if(obj.hasOwnProperty(prop)){str.push('"'+prop+'":'+toString(obj[prop]));}}return'{'+str.join(',')+'}';}return String(obj).replace(/\s/g," ").replace(/\'/g,"\"");}function typeOf(obj){if(obj===null||obj===undefined){return false;}var type=typeof obj;return(type=='object'&&obj.push)?'array':type;}if(window.attachEvent){window.attachEvent("onbeforeunload",function(){__flash_unloadHandler=function(){};__flash_savedUnloadHandler=function(){};});}function map(arr,func){var newArr=[];for(var i in arr){if(arr.hasOwnProperty(i)){newArr[i]=func(arr[i]);}}return newArr;}window.flashembed=function(root,userParams,flashvars){function getHTML(){var html="";if(typeof flashvars=='function'){flashvars=flashvars();}params.src+=((params.src.indexOf("?")!=-1?"&":"?")+Math.random());if(navigator.plugins&&navigator.mimeTypes&&navigator.mimeTypes.length){html='<embed type="application/x-shockwave-flash" ';if(params.id){extend(params,{name:params.id});}for(var key in params){if(params[key]!==null){html+=[key]+'="'+params[key]+'"\n\t';}}if(flashvars){html+='flashvars=\''+concatVars(flashvars)+'\'';}html+='/>';}else{html='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" ';html+='width="'+params.width+'" height="'+params.height+'"';if(!params.id&&document.all){params.id="_"+(""+Math.random()).substring(5);}if(params.id){html+=' id="'+params.id+'"';}html+='>';html+='\n\t<param name="movie" value="'+params.src+'" />';params.id=params.src=params.width=params.height=null;for(var k in params){if(params[k]!==null){html+='\n\t<param name="'+k+'" value="'+params[k]+'" />';}}if(flashvars){html+='\n\t<param name="flashvars" value=\''+concatVars(flashvars)+'\' />';}html+="</object>";if(debug){alert(html);}}return html;}var params={src:'#',width:'100%',height:'100%',version:null,onFail:null,expressInstall:null,debug:false,allowfullscreen:true,allowscriptaccess:'always',quality:'high',type:'application/x-shockwave-flash',pluginspage:'http://www.adobe.com/go/getflashplayer'};if(typeof userParams=='string'){userParams={src:userParams};}extend(params,userParams);var version=flashembed.getVersion();var required=params.version;var express=params.expressInstall;var debug=params.debug;if(typeof root=='string'){var el=document.getElementById(root);if(el){root=el;}else{domReady(function(){flashembed(root,userParams,flashvars);});return;}}if(!root){return;}if(!required||flashembed.isSupported(required)){params.onFail=params.version=params.expressInstall=params.debug=null;root.innerHTML=getHTML();return root.firstChild;}else if(params.onFail){var ret=params.onFail.call(params,flashembed.getVersion(),flashvars);if(ret===true){root.innerHTML=ret;}}else if(required&&express&&flashembed.isSupported([6,65])){extend(params,{src:express});flashvars={MMredirectURL:location.href,MMplayerType:'PlugIn',MMdoctitle:document.title};root.innerHTML=getHTML();}else{if(root.innerHTML.replace(/\s/g,'')!==''){}else{root.innerHTML="<h2>Flash version "+required+" or greater is required</h2>"+"<h3>"+(version[0]>0?"Your version is "+version:"You have no flash plugin installed")+"</h3>"+"<p>Download latest version from <a href='"+params.pluginspage+"'>here</a></p>";}}return root;};extend(window.flashembed,{getVersion:function(){var version=[0,0];if(navigator.plugins&&typeof navigator.plugins["Shockwave Flash"]=="object"){var _d=navigator.plugins["Shockwave Flash"].description;if(typeof _d!="undefined"){_d=_d.replace(/^.*\s+(\S+\s+\S+$)/,"$1");var _m=parseInt(_d.replace(/^(.*)\..*$/,"$1"),10);var _r=/r/.test(_d)?parseInt(_d.replace(/^.*r(.*)$/,"$1"),10):0;version=[_m,_r];}}else if(window.ActiveXObject){try{var _a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");}catch(e){try{_a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");version=[6,0];_a.AllowScriptAccess="always";}catch(ee){if(version[0]==6){return;}}try{_a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");}catch(eee){}}if(typeof _a=="object"){_d=_a.GetVariable("$version");if(typeof _d!="undefined"){_d=_d.replace(/^\S+\s+(.*)$/,"$1").split(",");version=[parseInt(_d[0],10),parseInt(_d[2],10)];}}}return version;},isSupported:function(version){var now=flashembed.getVersion();var ret=(now[0]>version[0])||(now[0]==version[0]&&now[1]>=version[1]);return ret;},domReady:domReady,toString:toString});if(jQ){jQuery.prototype.flashembed=function(params,flashvars){return this.each(function(){flashembed(this,params,flashvars);});};}})();
\ No newline at end of file
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer-3.0.0-rc2.swf b/js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer-3.0.0-rc2.swf
new file mode 100644 (file)
index 0000000..70f6a17
Binary files /dev/null and b/js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer-3.0.0-rc2.swf differ
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer-3.0.0-rc4.swf b/js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer-3.0.0-rc4.swf
new file mode 100644 (file)
index 0000000..9c7b3b4
Binary files /dev/null and b/js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer-3.0.0-rc4.swf differ
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer-3.0.1.swf b/js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer-3.0.1.swf
new file mode 100644 (file)
index 0000000..fcb9cf5
Binary files /dev/null and b/js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer-3.0.1.swf differ
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer.controls-3.0.0-beta5.swf b/js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer.controls-3.0.0-beta5.swf
new file mode 100644 (file)
index 0000000..c5bec77
Binary files /dev/null and b/js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer.controls-3.0.0-beta5.swf differ
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer.controls-3.0.0-beta7.swf b/js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer.controls-3.0.0-beta7.swf
new file mode 100644 (file)
index 0000000..703a96a
Binary files /dev/null and b/js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer.controls-3.0.0-beta7.swf differ
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer.controls-3.0.1.swf b/js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer.controls-3.0.1.swf
new file mode 100644 (file)
index 0000000..9f08f4d
Binary files /dev/null and b/js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer.controls-3.0.1.swf differ
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer.pseudostreaming-3.0.0-beta3.swf b/js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer.pseudostreaming-3.0.0-beta3.swf
new file mode 100644 (file)
index 0000000..65a5605
Binary files /dev/null and b/js2/mwEmbed/libEmbedVideo/binPlayers/flowplayer/flowplayer.pseudostreaming-3.0.0-beta3.swf differ
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/kaltura-player/README b/js2/mwEmbed/libEmbedVideo/binPlayers/kaltura-player/README
new file mode 100644 (file)
index 0000000..3ec8757
--- /dev/null
@@ -0,0 +1,11 @@
+This Kaltura Dynamic Player +Playlist (KDP) is a sub package of the taken Kaltura Community Edition (CE) Built from Kaltura.org source.
+
+The full Kaltura Community Edition is licensed under the (GNU Affero General Public License v3)
+
+And the source code is available on the kaltura.org site:
+http://www.kaltura.org/project/kalturaCE
+
+More info about the KDP: 
+http://www.kaltura.org/kdp-dynamic-player-and-playlist-widget
+
+
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/kaltura-player/kdp.swf b/js2/mwEmbed/libEmbedVideo/binPlayers/kaltura-player/kdp.swf
new file mode 100755 (executable)
index 0000000..c105546
Binary files /dev/null and b/js2/mwEmbed/libEmbedVideo/binPlayers/kaltura-player/kdp.swf differ
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/kaltura-player/wrapper.swf b/js2/mwEmbed/libEmbedVideo/binPlayers/kaltura-player/wrapper.swf
new file mode 100755 (executable)
index 0000000..812a32b
Binary files /dev/null and b/js2/mwEmbed/libEmbedVideo/binPlayers/kaltura-player/wrapper.swf differ
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/LICENSE.txt b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/LICENSE.txt
new file mode 100644 (file)
index 0000000..878ca2a
--- /dev/null
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright 2008 Tor-Einar Jarnbjo
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/README.txt b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/README.txt
new file mode 100644 (file)
index 0000000..f8416e0
--- /dev/null
@@ -0,0 +1,17 @@
+
+ *** PRELIMINARY SOFTWARE ***
+Please note that this is a prerelease of the OMTK Flash library. No
+quality of this software can be guaranteed.
+
+
+ *** haXe notes ***
+You need at least haXe 2.01 (with support for the new Flash 10 types)
+to compile the haXe source.
+
+ *** Flash notes ***
+I am not able to create a .SWC library from the haXe .SWF file. It's
+therefore dynamically linked at runtime and hxmdct.swf must be placed
+in the same directory as the "real" Flash movie.
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/hxmdct.swf b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/hxmdct.swf
new file mode 100644 (file)
index 0000000..d314dee
Binary files /dev/null and b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/hxmdct.swf differ
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/omtkp.swf b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/omtkp.swf
new file mode 100644 (file)
index 0000000..4ec9bfa
Binary files /dev/null and b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/omtkp.swf differ
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/Player.as b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/Player.as
new file mode 100644 (file)
index 0000000..6abe5d2
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+
+package {
+
+       import org.omtk.vorbis.VorbisSound;
+       
+       import flash.display.Shape;
+       import flash.display.Sprite;
+       import flash.display.StageAlign;
+       import flash.display.StageQuality;
+       import flash.display.StageScaleMode;
+       import flash.net.*;
+       import flash.events.Event;
+       import flash.text.TextField;
+       import flash.utils.ByteArray;
+       import flash.utils.Endian;
+       import flash.utils.getTimer;
+       import flash.utils.setTimeout;
+       import flash.utils.setInterval;
+       import flash.external.ExternalInterface;
+       
+       [ SWF( backgroundColor = '#ffffff', width = '1', height = '1' ) ]
+       
+       public class Player extends Sprite {
+       
+               private var sound: VorbisSound;
+               private var initialized: Boolean = false;
+               
+               public function Player() {
+                       if(stage != null) {
+                               stage.frameRate = 20;
+                       }
+                       
+                       setTimeout(registerJSCallbacks, 100);
+                       initialized = true;
+               }
+
+               private function registerJSCallbacks(): void {
+                       if (ExternalInterface.available) {
+                               ExternalInterface.addCallback("play", playJS);
+                               ExternalInterface.addCallback("getMetaData", getMetaDataJS);
+                               ExternalInterface.addCallback("getPosition", getPositionJS);            
+                       }
+               }
+
+               public function playJS(url: String): void {
+                       if(sound != null) {
+                               sound.stop();
+                       }
+                       sound = new VorbisSound(new URLRequest(url));
+                       sound.addEventListener(Event.COMPLETE, complete);       
+                       sound.addEventListener(VorbisSound.METADATA_UPDATE, metadataUpdate);
+                       sound.play();
+               }
+
+               public function getMetaDataJS(key: String): String {
+                       if(sound == null) {
+                               return null;
+                       }
+                       else {
+                               return sound.getMetaData(key);
+                       }
+               }
+               
+               public function getPositionJS(): int {
+                       if(sound == null) {
+                               return -1;
+                       }
+                       else {
+                               return sound.position;
+                       }
+               }
+               
+               private function complete(event: Event):void {
+                       trace("complete");
+                       if(ExternalInterface.available) {
+                               ExternalInterface.call("OMTK_P_complete");
+                       }
+               }
+
+               private function metadataUpdate(event: Event):void {
+                       trace("metadata update: " + sound.getMetaData("TITLE"));
+                       if(ExternalInterface.available) {
+                               ExternalInterface.call("OMTK_P_metadataUpdate");
+                       }
+               }
+
+       }
+       
+}
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/ogg/EndOfOggStreamError.as b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/ogg/EndOfOggStreamError.as
new file mode 100644 (file)
index 0000000..9b8a82a
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+
+package org.omtk.ogg {
+
+       public class EndOfOggStreamError extends Error {
+       
+               public function EndOfOggStreamError(message:String = null) {
+                       super(message);
+               }
+       
+       }
+
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/ogg/LogicalOggStream.as b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/ogg/LogicalOggStream.as
new file mode 100644 (file)
index 0000000..d9d5d35
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+
+package org.omtk.ogg {
+
+       import org.omtk.util.BitByteArray;      
+       import flash.utils.Endian;
+
+       public class LogicalOggStream {
+       
+               private var source:UncachedUrlStream;
+               
+               private var pageIndex:int;
+               private var currentPage:OggPage;
+               private var currentSegmentIndex:int;
+               
+               public function LogicalOggStream(source:UncachedUrlStream) {
+                       this.source = source;
+               }
+               
+               public function getNextOggPacket(): OggPacket {
+               
+                       var res:BitByteArray = new BitByteArray();
+
+                       var segmentLength:int = 0;
+
+                       if(currentPage == null) {
+                               currentPage = source.getNextOggPage();
+                       }
+
+                       do {
+                               if(currentSegmentIndex >= currentPage.segmentOffsets.length) {
+                       currentSegmentIndex=0;
+
+                       if(currentPage.eos) {
+                               throw new EndOfOggStreamError("End of OGG stream");
+                       }
+                       
+                               currentPage = source.getNextOggPage();
+                               }
+
+                               segmentLength = currentPage.segmentLengths[currentSegmentIndex];
+                               res.writeBytes(currentPage.data, currentPage.segmentOffsets[currentSegmentIndex], segmentLength);
+                               currentSegmentIndex++;
+                       }
+                       while(segmentLength==255);
+                       
+                       res.position = 0;
+                       
+                       var lastPacket: Boolean = currentPage.eos && currentSegmentIndex == currentPage.segmentOffsets.length;
+                       var lastGranulePosition: int = currentPage.absoluteGranulePosition;
+                       
+                       return new OggPacket(res, lastPacket, lastGranulePosition);
+               }
+       
+       }
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/ogg/OggPacket.as b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/ogg/OggPacket.as
new file mode 100644 (file)
index 0000000..b7876ca
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+
+package org.omtk.ogg {
+
+       import org.omtk.util.BitByteArray;
+
+       public class OggPacket {
+       
+               private var _data: BitByteArray;
+               private var _lastPacket: Boolean;
+               private var _lastGranulePosition: int;
+               
+               public function OggPacket(data: BitByteArray, lastPacket: Boolean, lastGranulePosition: int) {
+                       _data = data;
+                       _lastPacket = lastPacket;
+                       _lastGranulePosition = lastGranulePosition;
+               }
+       
+               public function get data(): BitByteArray {
+                       return _data;
+               }
+               
+               public function get lastPacket(): Boolean {
+                       return _lastPacket;
+               }
+               
+               public function get lastGranulePosition(): int {
+                       return _lastGranulePosition;
+               }
+       
+       }
+       
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/ogg/OggPage.as b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/ogg/OggPage.as
new file mode 100644 (file)
index 0000000..8e90b08
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+
+package org.omtk.ogg {
+
+       import flash.net.*;
+       import flash.utils.ByteArray;
+       
+       public class OggPage {
+
+               private var _version:int;
+               private var _continued:Boolean;
+               private var _bos:Boolean;
+               private var _eos:Boolean;
+               private var _absoluteGranulePosition:int;
+               private var _streamSerialNumber:int;
+               private var _pageSequenceNumber:int;
+               private var _pageCheckSum:int;
+               private var _segmentOffsets:Array;
+               private var _segmentLengths:Array;
+               private var _totalLength:int;
+               private var _data:ByteArray;
+                       
+               public function OggPage(stream:URLStream) {
+
+                       var capture:int = stream.readInt();
+                       if(capture != 0x5367674f) {
+                               throw new Error("Ogg page does not start with 'OggS': "+capture);
+                       }
+               
+                       _version = stream.readByte()&0xff;
+                       var tmp:int = stream.readByte();
+               
+                       _continued = (tmp&1)!=0;;
+                       _bos = (tmp&2)!=0;
+                       _eos = (tmp&4)!=0;
+                       
+                       // absoluteGranulePosition is really 64 bits
+                       _absoluteGranulePosition = stream.readUnsignedInt();
+                       stream.readUnsignedInt(); // last 32 bits of _absoluteGranulePosition
+                       
+                       _streamSerialNumber = stream.readUnsignedInt();
+                       _pageSequenceNumber = stream.readUnsignedInt();
+                       _pageCheckSum = stream.readUnsignedInt();
+                       
+                       //trace("_pageSequenceNumber: " + _pageSequenceNumber);
+                       
+                       var pageSegments:int = stream.readUnsignedByte();
+                       
+                       //stream.waitFor(pageSegments);
+                       
+                       _segmentOffsets = [];
+                       _segmentLengths = [];
+                       _data = new ByteArray();
+                       
+                       var totalLength:int;
+                       
+                       var i:int;
+                       var l:int;
+                       
+                       for( i= 0 ; i < pageSegments ; i++ ) {
+                               l = stream.readUnsignedByte();
+                               _segmentLengths.push( l );
+                               _segmentOffsets.push( totalLength );
+                               totalLength += l;
+                       }       
+                       
+                       stream.readBytes(_data, 0, totalLength);
+               }
+       
+               public function get absoluteGranulePosition():int {
+                       return _absoluteGranulePosition;
+               }
+
+               public function get segmentOffsets():Array {
+                       return _segmentOffsets;
+               }
+               
+               public function get segmentLengths():Array {
+                       return _segmentLengths;
+               }
+               
+               public function get data():ByteArray {
+                       return _data;
+               }
+
+               public function get eos():Boolean {
+                       return _eos;
+               }
+               
+               public function get bos():Boolean {
+                       return _bos;
+               }
+               
+               public function get continued():Boolean {
+                       return _continued;
+               }
+               
+       }
+
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/ogg/UncachedUrlStream.as b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/ogg/UncachedUrlStream.as
new file mode 100644 (file)
index 0000000..6e4a34a
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+
+package org.omtk.ogg {
+
+       import flash.net.*;
+       import flash.utils.Endian;
+       import flash.events.HTTPStatusEvent;
+       import flash.events.ProgressEvent;
+       
+       public class UncachedUrlStream {
+               
+               private var source:URLStream;
+       
+               public function UncachedUrlStream(source: URLStream) {
+                       this.source = source;
+               }
+       
+               public function get bytesAvailable():int {
+                       return source.bytesAvailable;
+               }       
+       
+               public function addEventListener(type:String, listener:Function):void {
+                       source.addEventListener(type, listener);
+               }
+       
+               public function getLogicalOggStream():LogicalOggStream {
+                       return new LogicalOggStream(this);
+               }
+       
+               public function getNextOggPage():OggPage {
+                       return new OggPage(source);
+               }
+               
+       }
+
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/util/BitByteArray.as b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/util/BitByteArray.as
new file mode 100644 (file)
index 0000000..3c54f6f
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+
+package org.omtk.util {
+
+       import flash.utils.ByteArray;
+       import flash.utils.Endian;
+       import flash.errors.IllegalOperationError;
+       
+       public class BitByteArray extends ByteArray {
+       
+               private var currentByte:uint;
+               private var bitIndex:int = 8;
+       
+               public function BitByteArray() {
+                       this.endian = Endian.LITTLE_ENDIAN;
+               }
+
+               public function readBit():Boolean {
+                       if (bitIndex > 7) {
+                               bitIndex = 0;
+                               currentByte = readUnsignedByte();
+                       }
+                       return (currentByte & (1 << (bitIndex++))) != 0;
+               }
+               
+               public function readUnsignedBitwiseInt(bits:int):uint {
+       
+                       var res:uint = 0;
+                       
+                       for (var i : int = 0; i < bits; i++) {
+                               if (bitIndex > 7) {
+                                       bitIndex = 0;
+                                       currentByte = readUnsignedByte();
+                               }
+                               if((currentByte & (1 << (bitIndex++))) != 0) {
+                                       res |= (1 << i);
+                               }
+                       }
+                       
+                       return res;
+               }       
+
+               public function readUnsignedHuffmanInt(root:HuffmanNode):uint {
+
+                       while (!root.hasValue) {
+                               if (bitIndex > 7) {
+                                       bitIndex = 0;
+                                       currentByte = readUnsignedByte();
+                               }
+                               root = (currentByte & (1 << (bitIndex++))) != 0 ? root._o1 : root._o0;
+                       }
+                       
+                       return root._value;                     
+               }
+       
+       }
+       
+
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/util/HuffmanNode.as b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/util/HuffmanNode.as
new file mode 100644 (file)
index 0000000..c8ce3ae
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+package org.omtk.util {
+
+       public class HuffmanNode {
+       
+               private var _parent:HuffmanNode;
+       
+               public var _o0:HuffmanNode;
+               public var _o1:HuffmanNode;
+               
+               private var _depth:int;
+       
+               public var _value:int;
+               public var hasValue: Boolean;
+               private var _full:Boolean = false;
+       
+               public function HuffmanNode(parent:HuffmanNode = null, value:int = -1) {
+                       _parent = parent;
+                       if(_parent != null) {
+                               _depth = _parent.depth+1;
+                       }
+                       _value = value;                 
+                       _full = value >= 0;
+                       hasValue = value >= 0;
+               }
+       
+               public function setNewValue(depth:int, value:uint):Boolean {
+             if (full) {
+                return false;
+             }
+             if (depth == 1) {
+                if (_o0 == null) {
+                   _o0 = new HuffmanNode(this, value);
+                   return true;
+                } else if (_o1 == null) {
+                   _o1 = new HuffmanNode(this, value);
+                   return true;
+                } else {
+                   return false;
+                }
+             } else {
+                return o0.setNewValue(depth - 1, value)
+                       ? true : o1.setNewValue(depth - 1, value);
+             }
+          }    
+       
+               public function get value():uint {
+                       return _value;
+               }
+       
+               public function get o0():HuffmanNode {
+                       if(_o0 == null) {
+                               _o0 = new HuffmanNode(this);
+                       }
+                       return _o0;
+               }
+
+               public function get o1():HuffmanNode {
+                       if(_o1 == null) {
+                               _o1 = new HuffmanNode(this);
+                       }
+                       return _o1;
+               }
+       
+               public function get depth():int {
+                       return _depth;
+               }
+               
+               public function get full():Boolean {
+                       return _full ? true
+                       : (_full = (_o0 != null && _o0.full && _o1 != null && _o1.full));
+               }
+               
+       }
+       
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/AudioPacket.as b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/AudioPacket.as
new file mode 100644 (file)
index 0000000..8cec996
--- /dev/null
@@ -0,0 +1,340 @@
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+       import flash.utils.getTimer;
+       import flash.utils.ByteArray;
+       import org.omtk.ogg.*;
+       import org.omtk.util.BitByteArray;
+
+       public class AudioPacket {
+       
+               private var modeNumber:int;
+               private var mode:Mode;
+               private var mapping:Mapping;
+               private var n:int;
+               
+               private var blockFlag:Boolean;
+               private var previousWindowFlag:Boolean;
+               private var nextWindowFlag:Boolean;
+
+               private var windowCenter:int;
+               private var leftWindowStart:int;
+               private var leftWindowEnd:int;
+               private var leftN:int;
+               private var rightWindowStart:int;
+               private var rightWindowEnd:int;
+               private var rightN:int;
+               
+               private var window:Vector.<Number>;
+               private var freq0:Vector.<Number>;
+               private var freq1:Vector.<Number>;
+               private var pcm0:Vector.<Number>;
+               private var pcm1:Vector.<Number>;
+               
+               private var channelFloors:Vector.<Floor>;
+               private var noResidues:Vector.<Boolean>;                
+
+               private var _lastPacket: Boolean;
+               private var _lastGranulePosition: int;
+
+               public function AudioPacket(vorbis:VorbisStream, packet: OggPacket, currentGranulePosition: int) {
+               
+                       var source: BitByteArray = packet.data;
+                       _lastPacket = packet.lastPacket;
+                       _lastGranulePosition = packet.lastGranulePosition;
+                       
+                       var i:int;
+                       var j:int;
+                       var k:int;
+       
+                       var sHeader:SetupHeader = vorbis.setupHeader;
+                       var iHeader:IdentificationHeader = vorbis.identificationHeader;
+                       var modes:Vector.<Mode> = sHeader.modes;
+                       var mappings:Vector.<Mapping> = sHeader.mappings;
+                       var residues:Vector.<Residue> = sHeader.residues;
+                       var channels:int = iHeader.channels;
+       
+                       if (source.readUnsignedBitwiseInt(1) != 0) {
+                               throw new Error("Packet type mismatch when trying to create an audio packet.");
+                       }
+       
+                       modeNumber = source.readUnsignedBitwiseInt(Util.ilog(modes.length - 1));
+       
+                       mode = modes[modeNumber];
+                       
+                       if(mode == null) {
+                               throw new Error("Reference to invalid mode in audio packet.");
+                       }
+       
+                       mapping = mappings[mode.mapping];
+       
+                       var magnitudes:Vector.<int> = mapping.magnitudes;
+                       var angles:Vector.<int> = mapping.angles;
+       
+                       blockFlag = mode.blockFlag;
+       
+                       var blockSize0:int = iHeader.blockSize0;
+                       var blockSize1:int = iHeader.blockSize1;
+       
+                       n = blockFlag ? blockSize1 : blockSize0;
+       
+                       if (blockFlag) {
+                               previousWindowFlag = source.readBit();
+                               nextWindowFlag = source.readBit();
+                       }
+       
+                       windowCenter = n / 2;
+       
+                       if (blockFlag && !previousWindowFlag) {
+                               leftWindowStart = n / 4 - blockSize0 / 4;
+                               leftWindowEnd = n / 4 + blockSize0 / 4;
+                               leftN = blockSize0 / 2;
+                       } else {
+                               leftWindowStart = 0;
+                               leftWindowEnd = n / 2;
+                               leftN = windowCenter;
+                       }
+       
+                       if (blockFlag && !nextWindowFlag) {
+                               rightWindowStart = n * 3 / 4 - blockSize0 / 4;
+                               rightWindowEnd = n * 3 / 4 + blockSize0 / 4;
+                               rightN = blockSize0 / 2;
+                       } else {
+                               rightWindowStart = windowCenter;
+                               rightWindowEnd = n;
+                               rightN = n / 2;
+                       }
+       
+                       window = getComputedWindow(vorbis);
+       
+                       channelFloors = new Vector.<Floor>(channels, true);
+                       noResidues = new Vector.<Boolean>(channels, true);
+       
+                       freq0 = new Vector.<Number>(n, true);
+                       freq1 = new Vector.<Number>(n, true);
+                       pcm0 = new Vector.<Number>(n, true);
+                       pcm1 = new Vector.<Number>(n, true);
+
+                       var allFloorsEmpty: Boolean = true;
+                       var submapNumber: int;
+                       var floorNumber: int;
+                       var decodedFloor: Floor;
+       
+                       for(i = 0; i < channels; i++) {
+                               submapNumber = mapping.mux[i];
+                               floorNumber = mapping.submapFloors[submapNumber];
+                               decodedFloor = sHeader.floors[floorNumber].decodeFloor(vorbis, source);
+                               channelFloors[i] = decodedFloor;
+                               noResidues[i] = decodedFloor == null;
+                               if (decodedFloor != null) {
+                                       allFloorsEmpty = false;
+                               }
+                       }
+       
+                       if(allFloorsEmpty) {
+                               return;
+                       }
+                       
+                       var mag: int;
+                       var ang: int;
+
+                       for(i = 0; i < magnitudes.length; i++) {
+                               mag = magnitudes[i];
+                               ang = angles[i];
+                               if (!noResidues[mag] || !noResidues[ang]) {
+                                       noResidues[mag] = false;
+                                       noResidues[ang] = false;
+                               }
+                       }
+       
+                       var ch: int;
+                       var doNotDecodeFlags: Vector.<Boolean>;
+                       var residue:Residue;
+                       
+                       for(i = 0; i < mapping.submaps; i++) {
+                       
+                               doNotDecodeFlags = new Vector.<Boolean>();
+                               
+                               for(j = 0; j < channels; j++) {
+                                       if(mapping.mux[j] == i) {
+                                               doNotDecodeFlags.push(noResidues[j]);
+                                       }
+                               }
+
+                               residue = residues[mapping.submapResidues[i]];
+                               
+                               residue.decodeResidue(vorbis, source, mode, ch, doNotDecodeFlags, freq0, freq1);
+                       }
+
+                       var a: Number;
+                       var m: Number;
+       
+                       for(i = mapping.couplingSteps - 1; i >= 0; i--) {
+                       
+                               mag = magnitudes[i];
+                               ang = angles[i];
+                               
+                               for (j = 0; j < freq0.length; j++) {
+                                       
+                                       a = ang == 0 ? freq0[j] : freq1[j];
+                                       m = mag == 0 ? freq0[j] : freq1[j];
+                                       
+                                       if(a > 0) {
+                                               if(ang == 0) {
+                                                       freq0[j] = m > 0 ? m - a : m + a;
+                                               }
+                                               else {
+                                                       freq1[j] = m > 0 ? m - a : m + a;
+                                               }
+                                       }
+                                       else {
+                                               if(mag == 0) {
+                                                       freq0[j] = m > 0 ? m + a : m - a;
+                                               }
+                                               else {
+                                                       freq1[j] = m > 0 ? m + a : m - a;
+                                               }
+                                               
+                                               if(ang == 0) {
+                                                       freq0[j] = m;
+                                               }
+                                               else {
+                                                       freq1[j] = m;
+                                               }
+                                       }
+                               }
+                       }
+                       
+                       if(channelFloors[0] != null) {
+                               Floor(channelFloors[0]).computeFloor(freq0);
+                       }
+                       
+                       if(channelFloors[1] != null) {
+                               Floor(channelFloors[1]).computeFloor(freq1);
+                       }
+
+                       // perform an inverse mdct to all channels
+                       var mdct: Mdct = blockFlag ? iHeader.mdct1 : iHeader.mdct0;
+                       mdct.imdct(freq0, window, pcm0);
+                       mdct.imdct(freq1, window, pcm1);
+
+                       if(_lastPacket) {
+                               if(leftWindowEnd - leftWindowStart > _lastGranulePosition - currentGranulePosition) {
+                                       leftWindowEnd = leftWindowStart + _lastGranulePosition - currentGranulePosition
+                               }
+                               if(rightWindowStart - leftWindowStart > _lastGranulePosition - currentGranulePosition) {
+                                       rightWindowStart = leftWindowStart + _lastGranulePosition - currentGranulePosition
+                               }
+                       }
+
+               }       
+       
+               private function getComputedWindow(vorbis:VorbisStream):Vector.<Number> {
+                       
+                       var i:int;
+                       
+                       var ix:int = (blockFlag ? 4 : 0) + (previousWindowFlag ? 2 : 0) + (nextWindowFlag ? 1 : 0);
+                       var w:Vector.<Number> = vorbis.windows[ix];
+                       
+                       var x:Number;
+                       
+                       if (w == null) {
+                               w = new Vector.<Number>(n);
+       
+                               for(i = 0; i < leftWindowStart; i++) {
+                                       w[i] = 0;
+                               }
+       
+                               for (i = 0; i < leftN; i++) {
+                                       x = (i + .5) / leftN * Math.PI / 2.;
+                                       x = Math.sin(x);
+                                       x *= x;
+                                       x *= Math.PI / 2.;
+                                       x = Math.sin(x);
+                                       w[i + leftWindowStart] = x;
+                               }
+       
+                               for (i = leftWindowEnd; i < rightWindowStart; i++) {
+                                       w[i] = 1;
+                               }
+       
+                               for (i = 0; i < rightN; i++) {
+                                       x = (rightN - i - .5) / rightN * Math.PI / 2.;
+                                       x = Math.sin(x);
+                                       x *= x;
+                                       x *= Math.PI / 2.;
+                                       x = Math.sin(x);
+                                       w[i + rightWindowStart] = x;
+                               }
+       
+                               for(i = rightN + rightWindowStart; i < n; i++) {
+                                       w[i] = 0;
+                               }
+
+                               for(i = 0; i < w.length; i++) {
+                                       w[i] *= 0.5;
+                               }
+       
+                               vorbis.windows[ix] = w;
+                       }
+                       
+                       return w;
+               }       
+               
+               
+               public function readPcm(previousPacket:AudioPacket, target: ByteArray): int {
+               
+                       var j:int;
+                       var j2:int;
+                       var ppcm0:Vector.<Number> = previousPacket.pcm0;
+                       var ppcm1:Vector.<Number> = previousPacket.pcm1;
+                       
+                       j2 = previousPacket.rightWindowStart;
+                       
+                       for(j = leftWindowStart; j < leftWindowEnd; j++) {
+                               target.writeFloat(pcm0[j] + ppcm0[j2]);
+                               target.writeFloat(pcm1[j] + ppcm1[j2++]);
+                       }
+
+                       for (j = leftWindowEnd; j < rightWindowStart; j++) {
+                               target.writeFloat(pcm0[j]);
+                               target.writeFloat(pcm1[j]);
+                       }
+
+                       return numberOfSamples;
+
+               }
+
+               public function get numberOfSamples():int {
+                       return rightWindowStart - leftWindowStart;
+               }
+
+               public function get lastPacket(): Boolean {
+                       return lastPacket;
+               }
+               
+               public function get lastGranulePosition(): int {
+                       return lastGranulePosition;
+               }
+       
+       }
+
+
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/CodeBook.as b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/CodeBook.as
new file mode 100644 (file)
index 0000000..ed84041
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+       import flash.errors.IllegalOperationError;
+       import org.omtk.util.*;
+
+       public class CodeBook {
+
+               private var entries:uint;
+               private var entryLengths:Vector.<int>;
+               private var valueVector:Vector.<Vector.<Number>>;
+
+               private var codeBookLookupType:int = -1;
+
+               public var huffmanRoot:HuffmanNode;
+               public var dimensions:uint;
+
+               public function CodeBook( source: BitByteArray ) {
+
+                       var i:int;
+                       var j:int;
+               
+                       var syncPattern:uint = source.readUnsignedBitwiseInt(24);
+                       if(syncPattern !=0x564342) {
+                               throw new IllegalOperationError("Illegal codebook sync pattern: "+syncPattern);
+                       }
+               
+                       dimensions = source.readUnsignedBitwiseInt(16);
+                       entries = source.readUnsignedBitwiseInt(24);
+                       
+                       entryLengths = new Vector.<int>(entries);
+                       
+                       var ordered:Boolean = source.readBit();
+                       
+                       if(ordered) {
+                               var cl:int = source.readUnsignedBitwiseInt(5)+1;
+                               for(i=0; i<entryLengths.length; ) {
+                                       var num:int = source.readUnsignedBitwiseInt(Util.ilog(entryLengths.length-i));
+                                       if(i+num>entryLengths.length) {
+                                               throw new Error("The codebook entry length list is longer than the actual number of entry lengths.");
+                                       }
+                                       for(j=i; j<i+num; j++) {
+                                               entryLengths[j] = cl;
+                                       }
+                                       //Arrays.fill(entryLengths, i, i+num, cl);
+                                       cl++;
+                                       i+=num;
+                               }
+                       }
+                       else {
+                               // !ordered
+                               var sparse:Boolean = source.readBit();
+                               
+                               if(sparse) {
+                                       for(i=0; i<entryLengths.length; i++) {
+                                               if(source.readBit()) {
+                                                       entryLengths[i]=source.readUnsignedBitwiseInt(5)+1;
+                                               }
+                                               else {
+                                                       entryLengths[i]=-1;
+                                               }
+                                       }
+                               }
+                               else {
+                                       // !sparse
+                                       //Alert.show("entryLengths.length: "+entryLengths.length, "CodeBook");
+                                       for(i=0; i<entryLengths.length; i++) {
+                                               entryLengths[i]=source.readUnsignedBitwiseInt(5)+1;
+                                       }
+                               }
+                       
+                       }
+                       
+                       if (!createHuffmanTree(entryLengths)) {
+                               throw new Error("An exception was thrown when building the codebook Huffman tree.");
+                       }       
+
+                       codeBookLookupType = source.readUnsignedBitwiseInt(4);
+
+                       switch(codeBookLookupType) {
+                       case 0:
+                               // codebook has no scalar vectors to be calculated
+                               break;
+                       case 1:
+                       case 2:
+                               var codeBookMinimumValue:Number = Util.float32unpack(source.readUnsignedBitwiseInt(32));
+                               var codeBookDeltaValue:Number = Util.float32unpack(source.readUnsignedBitwiseInt(32));
+
+                               var codeBookValueBits:uint = source.readUnsignedBitwiseInt(4)+1;
+                               var codeBookSequenceP:Boolean = source.readBit();
+
+                               var codeBookLookupValues:uint = 0;
+
+                               if(codeBookLookupType==1) {
+                                       codeBookLookupValues=Util.lookup1Values(entries, dimensions);
+                               }
+                               else {
+                                       codeBookLookupValues=entries*dimensions;
+                               }
+
+                               var codeBookMultiplicands:Vector.<int> = new Vector.<int>(codeBookLookupValues);
+
+                               for(i=0; i < codeBookMultiplicands.length; i++) {
+                                       codeBookMultiplicands[i]=source.readUnsignedBitwiseInt(codeBookValueBits);
+                               }
+
+                               valueVector = new Vector.<Vector.<Number>>(entries);
+
+                               if(codeBookLookupType==1) {
+                                       for(i=0; i<entries; i++) {
+                                               valueVector[i] = new Vector.<Number>(dimensions);
+                                               var last:Number = 0.0;
+                                               var indexDivisor:uint = 1;
+                                               for(j=0; j<dimensions; j++) {
+                                                       var multiplicandOffset:int = (i/indexDivisor)%codeBookLookupValues;
+                                                       valueVector[i][j]=
+                                                               codeBookMultiplicands[multiplicandOffset]*codeBookDeltaValue+codeBookMinimumValue+last;
+                                                       if(codeBookSequenceP) {
+                                                               last = valueVector[i][j];
+                                                       }
+                                                       indexDivisor*=codeBookLookupValues;
+                                               }
+                                       }
+                               }
+                               else {
+                                       throw new Error("Unsupported codebook lookup type: "+codeBookLookupType);
+                                       /** @todo implement */
+                               }
+                               break;
+                       default:
+                               throw new Error("Unsupported codebook lookup type: "+codeBookLookupType);
+                       }
+               }
+       
+               private function createHuffmanTree(entryLengths:Vector.<int>):Boolean {
+               
+                       var i:int;
+               
+                       huffmanRoot = new HuffmanNode();
+                       for(i=0; i<entryLengths.length; i++) {
+                               var el:int = entryLengths[i];
+                               if(el>0) {
+                                       if(!huffmanRoot.setNewValue(el, i)) {
+                                               return false;
+                                       }
+                               }
+                       }
+                       return true;
+               }
+
+
+               public function readVvAdd(a0:Vector.<Number>, a1:Vector.<Number>, left:Boolean, right:Boolean, source:BitByteArray, offset:int, length:int):void {
+       
+                       var i:int;
+                       var j:int;
+       
+                       if (!left && !right) {
+                               return;
+                       }
+
+                       // 1 or 2 channels      
+                       var ch:int = 
+                               left && right ? 2 : 1;
+
+                       var lim:int;
+                       var ix:int;
+                       var ve:Vector.<Number>;
+                       
+                       if(left && right) {
+                               lim = (offset + length) / 2;
+                               var chptr:int = 0;
+                               for (i = offset / 2; i < lim;) {
+                                       ix = source.readUnsignedHuffmanInt(huffmanRoot);
+                                       ve = valueVector[ix];
+                                       for (j = 0; j < dimensions; j++) {
+                                               if(chptr == 0) {
+                                                       a0[i] += ve[j];
+                                               }
+                                               else {
+                                                       a1[i] += ve[j];
+                                               }
+                                               chptr++;
+                                               if(chptr == 2) {
+                                                       chptr = 0;
+                                                       i++;
+                                               }
+                                       }
+                               }
+                       }
+                       else {
+                               var a : Vector.<Number> = left ? a0 : a1;
+                               lim = offset + length;
+                               for (i = offset; i < lim;) {
+                                       ve = valueVector[source.readUnsignedHuffmanInt(huffmanRoot)];
+                                       for (j = 0; j < dimensions; j++) {
+                                               a[i] += ve[j];
+                                               i++;
+                                       }
+                               }
+                       }
+
+               }
+               
+       }
+       
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/CommentHeader.as b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/CommentHeader.as
new file mode 100644 (file)
index 0000000..6cf3bfd
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+       import flash.utils.ByteArray;
+       import flash.utils.Endian;
+       import flash.utils.Dictionary;
+       import org.omtk.ogg.*;
+
+       public class CommentHeader {
+       
+               private var _vendor:String;
+               private var _comments:Dictionary = new Dictionary();
+       
+               public function CommentHeader(source:ByteArray)
+               {
+                       init( source );
+               }
+               
+               private function init( source: ByteArray ): void
+               {
+                       source.readByte();
+                       source.readByte();
+                       source.readByte();
+                       source.readByte();
+                       source.readByte();
+                       source.readByte();
+
+                       _vendor = readUtf8String(source);
+                       
+                       var ucLength:int = source.readUnsignedInt();
+                       
+                       for(var i:int = 0; i < ucLength; i++) {
+                               var comment:String = readUtf8String(source);
+                               var ix:int = comment.indexOf('=');
+                               var key:String = comment.substring(0, ix);
+                               var value:String = comment.substring(ix+1);
+                               _comments[key.toUpperCase()]=value;
+                       }
+               }       
+       
+               private function readUtf8String(source:ByteArray):String {
+                       var length:uint = source.readUnsignedInt();
+                       return source.readUTFBytes(length);
+               }
+       
+               public function get vendor():String {
+                       return _vendor;
+               }
+               
+               public function get comments():Dictionary {
+                       return _comments;
+               }
+       
+               public function get artist():String {
+                       return _comments["ARTIST"];
+               }
+               
+               public function get title():String {
+                       return _comments["TITLE"];
+               }
+       
+       }
+
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/Floor.as b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/Floor.as
new file mode 100644 (file)
index 0000000..f8eac3b
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+       import flash.errors.IllegalOperationError;
+       import org.omtk.util.BitByteArray;
+       
+       public class Floor {
+       
+               public static const DB_STATIC_TABLE:Vector.<Number> = Vector.<Number>([
+                       1.0649863e-07, 1.1341951e-07, 1.2079015e-07, 1.2863978e-07,
+                       1.3699951e-07, 1.4590251e-07, 1.5538408e-07, 1.6548181e-07,
+                       1.7623575e-07, 1.8768855e-07, 1.9988561e-07, 2.128753e-07,
+                       2.2670913e-07, 2.4144197e-07, 2.5713223e-07, 2.7384213e-07,
+                       2.9163793e-07, 3.1059021e-07, 3.3077411e-07, 3.5226968e-07,
+                       3.7516214e-07, 3.9954229e-07, 4.2550680e-07, 4.5315863e-07,
+                       4.8260743e-07, 5.1396998e-07, 5.4737065e-07, 5.8294187e-07,
+                       6.2082472e-07, 6.6116941e-07, 7.0413592e-07, 7.4989464e-07,
+                       7.9862701e-07, 8.5052630e-07, 9.0579828e-07, 9.6466216e-07,
+                       1.0273513e-06, 1.0941144e-06, 1.1652161e-06, 1.2409384e-06,
+                       1.3215816e-06, 1.4074654e-06, 1.4989305e-06, 1.5963394e-06,
+                       1.7000785e-06, 1.8105592e-06, 1.9282195e-06, 2.0535261e-06,
+                       2.1869758e-06, 2.3290978e-06, 2.4804557e-06, 2.6416497e-06,
+                       2.8133190e-06, 2.9961443e-06, 3.1908506e-06, 3.3982101e-06,
+                       3.6190449e-06, 3.8542308e-06, 4.1047004e-06, 4.3714470e-06,
+                       4.6555282e-06, 4.9580707e-06, 5.2802740e-06, 5.6234160e-06,
+                       5.9888572e-06, 6.3780469e-06, 6.7925283e-06, 7.2339451e-06,
+                       7.7040476e-06, 8.2047000e-06, 8.7378876e-06, 9.3057248e-06,
+                       9.9104632e-06, 1.0554501e-05, 1.1240392e-05, 1.1970856e-05,
+                       1.2748789e-05, 1.3577278e-05, 1.4459606e-05, 1.5399272e-05,
+                       1.6400004e-05, 1.7465768e-05, 1.8600792e-05, 1.9809576e-05,
+                       2.1096914e-05, 2.2467911e-05, 2.3928002e-05, 2.5482978e-05,
+                       2.7139006e-05, 2.8902651e-05, 3.0780908e-05, 3.2781225e-05,
+                       3.4911534e-05, 3.7180282e-05, 3.9596466e-05, 4.2169667e-05,
+                       4.4910090e-05, 4.7828601e-05, 5.0936773e-05, 5.4246931e-05,
+                       5.7772202e-05, 6.1526565e-05, 6.5524908e-05, 6.9783085e-05,
+                       7.4317983e-05, 7.9147585e-05, 8.4291040e-05, 8.9768747e-05,
+                       9.5602426e-05, 0.00010181521, 0.00010843174, 0.00011547824,
+                       0.00012298267, 0.00013097477, 0.00013948625, 0.00014855085,
+                       0.00015820453, 0.00016848555, 0.00017943469, 0.00019109536,
+                       0.00020351382, 0.00021673929, 0.00023082423, 0.00024582449,
+                       0.00026179955, 0.00027881276, 0.00029693158, 0.00031622787,
+                       0.00033677814, 0.00035866388, 0.00038197188, 0.00040679456,
+                       0.00043323036, 0.00046138411, 0.00049136745, 0.00052329927,
+                       0.00055730621, 0.00059352311, 0.00063209358, 0.00067317058,
+                       0.00071691700, 0.00076350630, 0.00081312324, 0.00086596457,
+                       0.00092223983, 0.00098217216, 0.0010459992, 0.0011139742,
+                       0.0011863665, 0.0012634633, 0.0013455702, 0.0014330129,
+                       0.0015261382, 0.0016253153, 0.0017309374, 0.0018434235,
+                       0.0019632195, 0.0020908006, 0.0022266726, 0.0023713743,
+                       0.0025254795, 0.0026895994, 0.0028643847, 0.0030505286,
+                       0.0032487691, 0.0034598925, 0.0036847358, 0.0039241906,
+                       0.0041792066, 0.0044507950, 0.0047400328, 0.0050480668,
+                       0.0053761186, 0.0057254891, 0.0060975636, 0.0064938176,
+                       0.0069158225, 0.0073652516, 0.0078438871, 0.0083536271,
+                       0.0088964928, 0.009474637, 0.010090352, 0.010746080,
+                       0.011444421, 0.012188144, 0.012980198, 0.013823725,
+                       0.014722068, 0.015678791, 0.016697687, 0.017782797,
+                       0.018938423, 0.020169149, 0.021479854, 0.022875735,
+                       0.024362330, 0.025945531, 0.027631618, 0.029427276,
+                       0.031339626, 0.033376252, 0.035545228, 0.037855157,
+                       0.040315199, 0.042935108, 0.045725273, 0.048696758,
+                       0.051861348, 0.055231591, 0.058820850, 0.062643361,
+                       0.066714279, 0.071049749, 0.075666962, 0.080584227,
+                       0.085821044, 0.091398179, 0.097337747, 0.10366330,
+                       0.11039993, 0.11757434, 0.12521498, 0.13335215,
+                       0.14201813, 0.15124727, 0.16107617, 0.17154380,
+                       0.18269168, 0.19456402, 0.20720788, 0.22067342,
+                       0.23501402, 0.25028656, 0.26655159, 0.28387361,
+                       0.30232132, 0.32196786, 0.34289114, 0.36517414,
+                       0.38890521, 0.41417847, 0.44109412, 0.46975890,
+                       0.50028648, 0.53279791, 0.56742212, 0.60429640,
+                       0.64356699, 0.68538959, 0.72993007, 0.77736504,
+                       0.82788260, 0.88168307, 0.9389798, 1.0]);
+       
+               public static function createInstance(source:BitByteArray, header:SetupHeader):Floor {
+       
+                       var type:int = source.readUnsignedBitwiseInt(16);
+       
+                       switch (type) {
+                       case 0:
+                               return new Floor0(source, header);
+                       case 1:
+                               return new Floor1(source, header);
+                       default:
+                               throw new Error("Floor type " + type + " is not supported.");
+                       }
+               }
+
+               public function get type():int {
+                       throw new IllegalOperationError("operation not implemented");
+               }
+               
+               public function decodeFloor(vorbis:VorbisStream, source:BitByteArray):Floor1 {
+                       throw new IllegalOperationError("operation not implemented");
+               }
+       
+               public function computeFloor(vector:Vector.<Number>):void {
+                       throw new IllegalOperationError("operation not implemented");
+               }
+               
+
+       }
+
+       
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/Floor0.as b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/Floor0.as
new file mode 100644 (file)
index 0000000..3f38dc8
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+       import flash.errors.IllegalOperationError;
+       import org.omtk.util.BitByteArray;
+       
+       public class Floor0 extends Floor {
+
+               private var order:int;
+               private var rate:int;
+               private var barkMapSize:int;
+               private var amplitudeBits:int;
+               private var amplitudeOffset:int;
+               
+               private var bookList:Vector.<int>;
+               
+               public function Floor0(source:BitByteArray, header:SetupHeader) {
+
+                       order = source.readUnsignedBitwiseInt(8);
+                       rate = source.readUnsignedBitwiseInt(16);
+                       barkMapSize = source.readUnsignedBitwiseInt(16);
+                       amplitudeBits = source.readUnsignedBitwiseInt(6);
+                       amplitudeOffset = source.readUnsignedBitwiseInt(8);
+       
+                       var bookCount:uint = source.readUnsignedBitwiseInt(4) + 1;
+                       bookList = new Vector.<int>(bookCount);
+       
+                       var i:int;
+       
+                       for (i = 0; i < bookList.length; i++) {
+                               bookList[i] = source.readUnsignedBitwiseInt(8);
+                               if (bookList[i] > header.codeBooks.length) {
+                                       throw new Error("A floor0_book_list entry is higher than the code book count.");
+                               }
+                       }
+               }
+
+       }
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/Floor1.as b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/Floor1.as
new file mode 100644 (file)
index 0000000..70621d0
--- /dev/null
@@ -0,0 +1,278 @@
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+       import flash.errors.IllegalOperationError;
+       import org.omtk.util.*;
+       
+       public class Floor1 extends Floor {
+
+               private var partitionClassList:Vector.<int>;
+               private var maximumClass:int;
+               private var multiplier:int;
+               private var rangeBits:int;
+               private var classDimensions:Vector.<int>;
+               private var classSubclasses:Vector.<int>;
+               private var classMasterbooks:Vector.<int>;
+               private var subclassBooks:Vector.<Vector.<int>>;
+               private var xList:Vector.<int>;
+               private var yList:Vector.<int>;
+               private var lowNeighbours:Vector.<int>;
+               private var highNeighbours:Vector.<int>;
+               private static var RANGES:Vector.<int> = Vector.<int>([256, 128, 86, 64]);
+
+               private var xList2:Vector.<int>;
+               private var step2Flags:Vector.<Boolean>;
+               
+               public function Floor1(source:BitByteArray = null, header:SetupHeader = null) {
+
+                       if(source==null && header==null) {
+                               return;
+                       }
+               
+                       var i:int;
+                       var j:int;
+                       
+                       maximumClass = -1;
+                       var partitions:int = source.readUnsignedBitwiseInt(5);
+                       partitionClassList = new Vector.<int>(partitions);
+       
+                       for (i = 0; i < partitionClassList.length; i++) {
+                               partitionClassList[i] = source.readUnsignedBitwiseInt(4);
+                               if (partitionClassList[i] > maximumClass) {
+                                       maximumClass = partitionClassList[i];
+                               }
+                       }
+       
+                       classDimensions = new Vector.<int>(maximumClass + 1);
+                       classSubclasses = new Vector.<int>(maximumClass + 1);
+                       classMasterbooks = new Vector.<int>(maximumClass + 1);
+                       subclassBooks = new Vector.<Vector.<int>>(maximumClass + 1);
+       
+                       var xListLength:int = 2;
+       
+                       for (i = 0; i <= maximumClass; i++) {
+                               classDimensions[i] = source.readUnsignedBitwiseInt(3) + 1;
+                               xListLength += classDimensions[i];
+                               classSubclasses[i] = source.readUnsignedBitwiseInt(2);
+       
+                               if (classDimensions[i] > header.codeBooks.length || classSubclasses[i] > header.codeBooks.length) {
+                                       throw new Error("There is a class dimension or class subclasses entry higher than the number of codebooks in the setup header.");
+                               }
+                               if (classSubclasses[i] != 0) {
+                                       classMasterbooks[i] = source.readUnsignedBitwiseInt(8);
+                               }
+                               subclassBooks[i] = new Vector.<int>(1 << classSubclasses[i]);
+                               for (j = 0; j < subclassBooks[i].length; j++) {
+                                       subclassBooks[i][j] = source.readUnsignedBitwiseInt(8) - 1;
+                               }
+                       }
+       
+                       multiplier = source.readUnsignedBitwiseInt(2) + 1;
+                       rangeBits = source.readUnsignedBitwiseInt(4);
+       
+                       var floorValues:int = 0;
+       
+                       xList = Vector.<int>([0, 1<<rangeBits]);
+                       
+                       for (i = 0; i < partitions; i++) {
+                               for (j = 0; j < classDimensions[partitionClassList[i]]; j++) {
+                                       xList.push(source.readUnsignedBitwiseInt(rangeBits));
+                               }
+                       }
+       
+                       lowNeighbours = new Vector.<int>(xList.length);
+                       highNeighbours = new Vector.<int>(xList.length);
+       
+                       for (i = 0; i < xList.length; i++) {
+                               lowNeighbours[i] = Util.lowNeighbour(xList, i);
+                               highNeighbours[i] = Util.highNeighbour(xList, i);
+                       }
+                       
+                       xList2 = new Vector.<int>(xList.length, true);
+                       step2Flags = new Vector.<Boolean>(xList.length, true);
+               }
+
+               public override function get type():int {
+                       return 1;
+               }
+
+               public override function decodeFloor(vorbis:VorbisStream, source:BitByteArray):Floor1 {
+
+                       var i:int;
+                       var j:int;
+                       var offset:int;
+
+                       if (!source.readBit()) {
+                               return null;
+                       }
+       
+                       var clone:Floor1 = clone();
+       
+                       clone.yList = new Vector.<int>(xList.length);
+       
+                       var range:int = RANGES[multiplier - 1];
+       
+                       clone.yList[0] = source.readUnsignedBitwiseInt(Util.ilog(range - 1));
+                       clone.yList[1] = source.readUnsignedBitwiseInt(Util.ilog(range - 1));
+       
+                       offset = 2;
+       
+                       for (i = 0; i < partitionClassList.length; i++) {
+                               var cls:int = partitionClassList[i];
+                               var cdim:int = classDimensions[cls];
+                               var cbits:int = classSubclasses[cls];
+                               var csub:int = (1 << cbits) - 1;
+                               var cval:int = 0;
+                               if (cbits > 0) {
+                                       cval = source.readUnsignedHuffmanInt(vorbis.setupHeader.codeBooks[classMasterbooks[cls]].huffmanRoot);
+                               }
+
+                               for (j = 0; j < cdim; j++) {
+                                       var book:int = subclassBooks[cls][cval & csub];
+                                       cval >>>= cbits;
+                                       if (book >= 0) {
+                                               clone.yList[j + offset] = source.readUnsignedHuffmanInt(vorbis.setupHeader.codeBooks[book].huffmanRoot);
+                                       } else {
+                                               clone.yList[j + offset] = 0;
+                                       }
+                               }
+                               offset += cdim;
+                       }
+               
+                       return clone;
+               }
+       
+               public override function computeFloor(vector:Vector.<Number>):void {
+
+                       var i:int;
+                       var j:int;
+
+                       var n:int = vector.length;
+                       var values:int = xList.length;
+                       //var step2Flags:Vector.<Boolean> = new Vector.<Boolean>(values);
+
+                       var range:int = RANGES[multiplier - 1];
+       
+                       for (i = 2; i < values; i++) {
+
+                               var lowNeighbourOffset:int = lowNeighbours[i];
+                               var highNeighbourOffset:int = highNeighbours[i];
+                               
+                               var predicted:int = Util.renderPoint(
+                                       xList[lowNeighbourOffset], xList[highNeighbourOffset], 
+                                       yList[lowNeighbourOffset], yList[highNeighbourOffset], xList[i]);
+                               
+                               var val:int = yList[i];
+                               var highRoom:int = range - predicted;
+                               var lowRoom:int = predicted;
+                               var room:int = highRoom < lowRoom ? highRoom * 2 : lowRoom * 2;
+                               
+                               if (val != 0) {
+                                       step2Flags[lowNeighbourOffset] = true;
+                                       step2Flags[highNeighbourOffset] = true;
+                                       step2Flags[i] = true;
+                                       if (val >= room) {
+                                               yList[i] = highRoom > lowRoom ? val - lowRoom + predicted
+                                                               : -val + highRoom + predicted - 1;
+                                       } else {
+                                               yList[i] = (val & 1) == 1 ? predicted - ((val + 1) >> 1)
+                                                               : predicted + (val >> 1);
+                                       }
+                               } else {
+                                       step2Flags[i] = false;
+                                       yList[i] = predicted;
+                               }
+                       }
+       
+                       for(i=0; i<xList.length; i++) {
+                               xList2[i] = xList[i];
+                       }
+
+                       sort(xList2, yList, step2Flags);
+       
+                       var hx:int = 0;
+                       var hy:int = 0;
+                       var lx:int = 0;
+                       var ly:int = yList[0] * multiplier;
+       
+                       for (i = 1; i < values; i++) {
+                               if (step2Flags[i]) {
+                                       hy = yList[i] * multiplier;
+                                       hx = xList2[i];
+                                       Util.renderLine(lx, ly, hx, hy, vector);
+                                       lx = hx;
+                                       ly = hy;
+                               }
+                       }
+       
+                       var r:Number = DB_STATIC_TABLE[hy];
+
+                       while(hx < n/2) {
+                               vector[hx++] = r;
+                       }
+
+               }
+
+               public function clone():Floor1 {
+                       var clone:Floor1 = new Floor1();
+                       clone.classDimensions = classDimensions;
+                       clone.classMasterbooks = classMasterbooks;
+                       clone.classSubclasses = classSubclasses;
+                       clone.maximumClass = maximumClass;
+                       clone.multiplier = multiplier;
+                       clone.partitionClassList = partitionClassList;
+                       clone.rangeBits = rangeBits;
+                       clone.subclassBooks = subclassBooks;
+                       clone.xList = xList;
+                       clone.yList = yList;
+                       clone.lowNeighbours = lowNeighbours;
+                       clone.highNeighbours = highNeighbours;
+                       clone.xList2 = xList2;
+                       clone.step2Flags = step2Flags;
+                       return clone;
+               }
+               
+               private function sort(x:Vector.<int>, y:Vector.<int>, b:Vector.<Boolean>):void {
+                       var off:int = 0;
+                       var len:int = x.length;
+                       var lim:int = len + off;
+                       var itmp:int;
+                       var btmp:Boolean;
+                       var i:int;
+                       var j:int;
+                       // Insertion sort on smallest arrays
+                       for (i = off; i < lim; i++) {
+                               for (j = i; j > off && x[j - 1] > x[j]; j--) {
+                                       itmp = x[j];
+                                       x[j] = x[j - 1];
+                                       x[j - 1] = itmp;
+                                       itmp = y[j];
+                                       y[j] = y[j - 1];
+                                       y[j - 1] = itmp;
+                                       btmp = b[j];
+                                       b[j] = b[j - 1];
+                                       b[j - 1] = btmp;
+                               }
+                       }
+               }
+
+       }
+       
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/IdentificationHeader.as b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/IdentificationHeader.as
new file mode 100644 (file)
index 0000000..c334a11
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+       import flash.utils.ByteArray;
+       
+       public class IdentificationHeader {
+       
+               private var _version:uint;
+               private var _channels:uint;
+               private var _sampleRate:uint;
+               private var _bitrateMaximum:int;
+               private var _bitrateMinimum:int;
+               private var _bitrateNominal:int;
+               private var _blockSize0:uint;
+               private var _blockSize1:uint;
+       
+               private var _mdct:Vector.<Mdct>;
+
+               public function IdentificationHeader(source:ByteArray) {
+
+                       source.readByte();
+                       source.readByte();
+                       source.readByte();
+                       source.readByte();
+                       source.readByte();
+                       source.readByte();
+       
+                       _version = source.readUnsignedInt();
+                       _channels = source.readUnsignedByte();
+                       _sampleRate = source.readUnsignedInt();
+                       _bitrateMaximum = source.readUnsignedInt();
+                       _bitrateNominal = source.readUnsignedInt();
+                       _bitrateMinimum = source.readUnsignedInt();
+                       var bs:int = source.readUnsignedByte();
+                       _blockSize0 = 1<<(bs&0xf);
+                       _blockSize1 = 1<<(bs>>4);
+               
+                       _mdct = new Vector.<Mdct>(2, false);
+                       _mdct[0] = new Mdct(_blockSize0);
+                       _mdct[1] = new Mdct(_blockSize1);
+               }
+               
+               public function get channels():uint {
+                       return _channels;
+               }
+               
+               public function get sampleRate():uint {
+                       return _sampleRate;
+               }
+               
+               public function get blockSize0():uint {
+                       return _blockSize0;
+               }
+               
+               public function get blockSize1():uint {
+                       return _blockSize1;
+               }
+               
+               public function get mdct0():Mdct {
+                       return _mdct[0];
+               }
+       
+               public function get mdct1():Mdct {
+                       return _mdct[1];
+               }
+
+       }
+
+
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/Look.as b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/Look.as
new file mode 100644 (file)
index 0000000..a174a7b
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+       import org.omtk.util.BitByteArray;
+       
+       public class Look {
+       
+               private var _map:int;
+               private var _parts:int;
+               private var _stages:int;
+               private var _fullbooks:Vector.<CodeBook>;
+               private var _phrasebook:CodeBook;
+               private var _partbooks:Vector.<Vector.<int>>;
+               private var _partvals:int;
+               private var _decodemap:Vector.<Vector.<int>>;
+               private var _postbits:int;
+               private var _phrasebits:int;
+               private var _frames:int;
+
+               public function Look(source:VorbisStream, residue:Residue, mode:Mode) {
+               
+                       var i:int;
+                       var j:int;
+                       var k:int;
+                       
+                       var dim:int = 0;
+                       var acc:int = 0;
+                       var maxstage:int = 0;
+
+                       _map = mode.mapping;
+                       
+                       _parts = residue.classifications;
+                       _fullbooks = source.setupHeader.codeBooks;
+                       _phrasebook = _fullbooks[residue.classBook];
+                       dim = _phrasebook.dimensions;
+
+                       _partbooks = new Vector.<Vector.<int>>(_parts);
+
+                       for (j = 0; j < _parts; j++) {
+                               var s:int = Util.ilog(residue.cascade[j]);
+                               if (s != 0) {
+                                       if (s > maxstage) {
+                                               maxstage = s;
+                                       }
+                                       _partbooks[j] = new Vector.<int>(s);
+                                       for (k = 0; k < s; k++) {
+                                               if ((residue.cascade[j] & (1 << k)) != 0) {
+                                                       _partbooks[j][k] = residue.books[j][k];
+                                               }
+                                       }
+                               }
+                       }
+
+                       _partvals = Math.round(Math.pow(_parts, dim));
+                       _stages = maxstage;
+
+                       _decodemap = new Vector.<Vector.<int>>(_partvals, true);
+
+                       for (j = 0; j < _partvals; j++) {
+                               var val:int = j;
+                               var mult:int = _partvals / _parts;
+                               _decodemap[j] = new Vector.<int>(dim);
+
+                               for (k = 0; k < dim; k++) {
+                                       var deco:int = val / mult;
+                                       val -= deco * mult;
+                                       mult /= _parts;
+                                       _decodemap[j][k] = deco;
+                               }
+                       }
+               }
+
+               public function get map():int {
+                       return _map;
+               }
+               
+               public function get parts():int {
+                       return _parts;
+               }
+               
+               public function get stages():int {
+                       return _stages;
+               }
+               
+               public function get fullbooks():Vector.<CodeBook> {
+                       return _fullbooks;
+               }
+               
+               public function get phrasebook():CodeBook {
+                       return _phrasebook;
+               }
+               
+               public function get partbooks():Vector.<Vector.<int>> {
+                       return _partbooks;
+               }
+               
+               public function get partvals():int {
+                       return _partvals;
+               }
+               
+               public function get decodemap():Vector.<Vector.<int>> {
+                       return _decodemap;
+               }
+               
+               public function get postbits():int {
+                       return _postbits;
+               }
+                       
+               public function get phrasebits():int {
+                       return _phrasebits;
+               }
+               
+               public function get frames():int {
+                       return _frames;
+               }
+                       
+       }
+       
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/Mapping.as b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/Mapping.as
new file mode 100644 (file)
index 0000000..982bec7
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+       import flash.errors.IllegalOperationError;
+       import org.omtk.util.BitByteArray;
+
+       public class Mapping {
+       
+               public static function createInstance(stream:VorbisStream, source:BitByteArray, header:SetupHeader):Mapping {
+               
+                       var type:int = source.readUnsignedBitwiseInt(16);
+                       switch (type) {
+                       case 0:
+                               return new Mapping0(stream, source, header);
+                       default:
+                               throw new Error("Mapping type " + type + " is not supported.");
+                       }
+               
+               }
+       
+               public function get type():int {
+                       throw new IllegalOperationError("not implemented");
+               }
+       
+               public function get couplingSteps():int {
+                       throw new IllegalOperationError("not implemented");
+               }
+
+               public function get submaps():int {
+                       throw new IllegalOperationError("not implemented");
+               }
+
+               public function get angles():Vector.<int> {
+                       throw new IllegalOperationError("not implemented");
+               }
+
+               public function get magnitudes():Vector.<int> {
+                       throw new IllegalOperationError("not implemented");
+               }
+
+               public function get mux():Vector.<int> {
+                       throw new IllegalOperationError("not implemented");
+               }
+
+               public function get submapFloors():Vector.<int> {
+                       throw new IllegalOperationError("not implemented");
+               }
+
+               public function get submapResidues():Vector.<int> {
+                       throw new IllegalOperationError("not implemented");
+               }
+
+       
+       }
+
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/Mapping0.as b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/Mapping0.as
new file mode 100644 (file)
index 0000000..547b533
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+       import flash.errors.IllegalOperationError;
+       import org.omtk.util.BitByteArray;
+
+       public class Mapping0 extends Mapping {
+       
+               private var _magnitudes:Vector.<int>;
+               private var _angles:Vector.<int>;
+               private var _mux:Vector.<int>;
+               private var _submapFloors:Vector.<int>;
+               private var _submapResidues:Vector.<int>;
+       
+               public function Mapping0(stream:VorbisStream, source:BitByteArray, header:SetupHeader) {
+
+                       var i:int;
+                       var j:int;
+               
+                       var submaps:int = 1;
+       
+                       if (source.readBit()) {
+                               submaps = source.readUnsignedBitwiseInt(4) + 1;
+                       }
+       
+                       var channels:int = stream.identificationHeader.channels;
+                       var ilogChannels:int = Util.ilog(channels - 1);
+       
+                       if (source.readBit()) {
+                               var couplingSteps:int = source.readUnsignedBitwiseInt(8) + 1;
+                               _magnitudes = new Vector.<int>(couplingSteps);
+                               _angles = new Vector.<int>(couplingSteps);
+       
+                               for (i = 0; i < couplingSteps; i++) {
+                                       magnitudes[i] = source.readUnsignedBitwiseInt(ilogChannels);
+                                       angles[i] = source.readUnsignedBitwiseInt(ilogChannels);
+                                       if (magnitudes[i] == angles[i] || magnitudes[i] >= channels
+                                                       || angles[i] >= channels) {
+                                               throw new Error("The channel magnitude and/or angle mismatch.");
+                                       }
+                               }
+                       } else {
+                               _magnitudes = Vector.<int>([]);
+                               _angles = Vector.<int>([]);
+                       }
+       
+                       if (source.readUnsignedBitwiseInt(2) != 0) {
+                               throw new Error("A reserved mapping field has an invalid value.");
+                       }
+       
+                       _mux = new Vector.<int>(channels);
+                       if (submaps > 1) {
+                               for (i = 0; i < channels; i++) {
+                                       _mux[i] = source.readUnsignedBitwiseInt(4);
+                                       if (_mux[i] > submaps) {
+                                               throw new Error("A mapping mux value is higher than the number of submaps");
+                                       }
+                               }
+                       } else {
+                               for (i = 0; i < channels; i++) {
+                                       _mux[i] = 0;
+                               }
+                       }
+       
+                       _submapFloors = new Vector.<int>(submaps);
+                       _submapResidues = new Vector.<int>(submaps);
+       
+                       var floorCount:int = header.floors.length;
+                       var residueCount:int = header.residues.length;
+       
+                       for (i = 0; i < submaps; i++) {
+                               source.readUnsignedBitwiseInt(8); // discard time placeholder
+                               _submapFloors[i] = source.readUnsignedBitwiseInt(8);
+                               _submapResidues[i] = source.readUnsignedBitwiseInt(8);
+       
+                               if (_submapFloors[i] > floorCount) {
+                                       throw new Error("A mapping floor value is higher than the number of floors.");
+                               }
+       
+                               if (_submapResidues[i] > residueCount) {
+                                       throw new Error("A mapping residue value is higher than the number of residues.");
+                               }
+                       }
+               }
+       
+               public override function get type():int {
+                       return 0;
+               }
+       
+               public override function get couplingSteps():int {
+                       return _angles.length;
+               }
+
+               public override function get submaps():int {
+                       return _submapFloors.length;
+               }
+
+               public override function get angles():Vector.<int> {
+                       return _angles;
+               }
+
+               public override function get magnitudes():Vector.<int> {
+                       return _magnitudes;
+               }
+
+               public override function get mux():Vector.<int> {
+                       return _mux;
+               }
+
+               public override function get submapFloors():Vector.<int> {
+                       return _submapFloors;
+               }
+
+               public override function get submapResidues():Vector.<int> {
+                       return _submapResidues;
+               }       
+       }
+
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/Mdct.as b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/Mdct.as
new file mode 100644 (file)
index 0000000..886deea
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+       import flash.events.*;
+       import flash.system.*;
+       import flash.display.*;
+       import flash.net.*;
+       import flash.utils.getTimer;
+       
+       /*
+        * Wrapper for the haXe compiled class org.omtk.vorbis.MdctHX
+        */
+       public class Mdct {
+       
+               public static var initialized : Boolean = false;
+               private static var hxClass : Class;
+               
+               public static function initialize() : void {
+                       var ldr:Loader = new Loader();
+                       var swfUrl:String = "hxmdct.swf";
+                       var req:URLRequest = new URLRequest(swfUrl);
+                       var ldrContext:LoaderContext = 
+                       new LoaderContext(false, ApplicationDomain.currentDomain);
+                       ldr.load(req, ldrContext);
+                       ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, swfLoaded);
+                       
+                       function swfLoaded(e:Event):void {
+                               hxClass = ApplicationDomain.currentDomain.getDefinition("org.omtk.vorbis.MdctHX") as Class;
+                               initialized = true;
+                       }               
+               }
+
+               private var delegate : Object;
+               
+               public function Mdct(n:int) { 
+                       delegate = new hxClass(n);
+               }
+               
+               public function imdct(frq:Vector.<Number>, window:Vector.<Number>, pcm:Vector.<Number>):void {
+                       delegate.imdct(frq, window, pcm);
+               }
+
+       }
+               
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/Mode.as b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/Mode.as
new file mode 100644 (file)
index 0000000..cf27af2
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+       import flash.errors.IllegalOperationError;
+       import flash.utils.Dictionary;
+       import org.omtk.util.BitByteArray;
+       
+       public class Mode
+       {
+               private var _blockFlag:Boolean;
+               private var _windowType:uint;
+               private var _transformType:uint;
+               private var _mapping:uint;
+               
+               public function Mode(source:BitByteArray, header:SetupHeader) {
+
+                       _blockFlag=source.readBit();
+                       _windowType=source.readUnsignedBitwiseInt(16);
+                       _transformType=source.readUnsignedBitwiseInt(16);
+                       _mapping=source.readUnsignedBitwiseInt(8);
+                       
+                       if(_windowType!=0) {
+                               throw new Error("Window type = "+windowType+", != 0");
+                       }
+                       
+                       if(_transformType!=0) {
+                               throw new Error("Transform type = "+transformType+", != 0");
+                       }
+                       
+                       if(_mapping > header.mappings.length) {
+                               throw new Error("Mode mapping number is higher than total number of mappings.");
+                       }
+               }
+       
+               public function get blockFlag():Boolean {
+                       return _blockFlag;
+               }
+               
+               public function get windowType():uint {
+                       return _windowType;
+               }
+               
+               public function get transformType():uint {
+                       return _transformType;
+               }
+               
+               public function get mapping():uint {
+                       return _mapping;
+               }
+       
+       }
+       
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/Residue.as b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/Residue.as
new file mode 100644 (file)
index 0000000..de9924f
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+       import flash.errors.IllegalOperationError;
+       import flash.utils.Dictionary;
+       import org.omtk.util.BitByteArray;
+       
+       public class Residue {
+
+               private var _begin:int;
+               private var _end:int;
+               private var _partitionSize:int;
+               private var _classifications:int;
+               private var _classBook:int;
+               private var _cascade:Vector.<int>;
+               private var _books:Vector.<Vector.<int>>;
+               
+               private var _looks:Dictionary;
+
+       
+               public function Residue(source:BitByteArray, header:SetupHeader) {
+
+                       _begin = source.readUnsignedBitwiseInt(24);
+                       _end = source.readUnsignedBitwiseInt(24);
+                       _partitionSize = source.readUnsignedBitwiseInt(24) + 1;
+                       _classifications = source.readUnsignedBitwiseInt(6) + 1;
+                       _classBook = source.readUnsignedBitwiseInt(8);
+       
+                       _cascade = new Vector.<int>(classifications);
+       
+                       var acc:int = 0;
+                       var i:int;
+                       var j:int;
+                       
+                       for (i = 0; i < classifications; i++) {
+                               var highBits:int = 0;
+                               var lowBits:int = 0;
+                               
+                               lowBits = source.readUnsignedBitwiseInt(3);
+                               if (source.readBit()) {
+                                       highBits = source.readUnsignedBitwiseInt(5);
+                               }
+                               _cascade[i] = (highBits << 3) | lowBits;
+                               acc += Util.icount(cascade[i]);
+                       }
+       
+                       _books = new Vector.<Vector.<int>>(classifications);
+       
+                       for (i = 0; i < classifications; i++) {
+                               books[i] = new Vector.<int>(8);
+                               for (j = 0; j < 8; j++) {
+                                       if ((cascade[i] & (1 << j)) != 0) {
+                                               books[i][j] = source.readUnsignedBitwiseInt(8);
+                                               if (books[i][j] > header.codeBooks.length) {
+                                                       throw new Error(
+                                                                       "Reference to invalid codebook entry in residue header.");
+                                               }
+                                       }
+                               }
+                       }
+                       
+                       _looks = new Dictionary();
+               }
+       
+               public static function createInstance(source:BitByteArray, header:SetupHeader):Residue {
+       
+                       var type:int = source.readUnsignedBitwiseInt(16);
+                       switch (type) {
+                       case 2:
+                               return new Residue2(source, header);
+                       default:
+                               throw new Error("Residue type " + type + " is not supported.");
+                       }
+               }
+               
+               public function decodeResidue(
+                       vorbis:VorbisStream, source:BitByteArray, 
+                       mode:Mode, ch:int,
+                       doNotDecodeFlags:Vector.<Boolean>, vectors0:Vector.<Number>, vectors1:Vector.<Number>):void {
+                               
+                       throw new IllegalOperationError("not implemented");
+               }
+               
+               
+               public function getLook(stream:VorbisStream, key:Mode):Look {
+                       var look:Look = _looks[key];
+                       if (look == null) {
+                               look = new Look(stream, this, key);
+                               _looks[key] = look;
+                       }
+                       return new Look(stream, this, key);//look;
+               }
+       
+       
+               public function get begin():int {
+                       return _begin;
+               }
+               
+               public function get end():int {
+                       return _end;
+               }
+               
+               public function get partitionSize():int {
+                       return _partitionSize;
+               }
+               
+               public function get classifications():int {
+                       return _classifications;
+               }
+               
+               public function get classBook():int {
+                       return _classBook;
+               }
+               
+               public function get cascade():Vector.<int> {
+                       return _cascade;
+               }
+               
+               public function get books():Vector.<Vector.<int>> {
+                       return _books;
+               }
+                       
+       }
+       
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/Residue2.as b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/Residue2.as
new file mode 100644 (file)
index 0000000..1fdc453
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+       import flash.errors.IllegalOperationError;
+       import flash.utils.Dictionary;
+       import org.omtk.util.BitByteArray;
+
+       public class Residue2 extends Residue {
+       
+               public function Residue2(source:BitByteArray, header:SetupHeader) {
+                       super(source, header);
+               }
+
+               public override function decodeResidue(
+                       vorbis:VorbisStream, source:BitByteArray, 
+                       mode:Mode, ch:int,
+                       doNotDecodeFlags:Vector.<Boolean>, vectors0:Vector.<Number>, vectors1:Vector.<Number>):void {
+
+                       var i:int;
+                       var j:int;
+                       var k:int;
+                       var l:int;
+                       var s:int;
+                       var slim:int;
+
+                       var look:Look = getLook(vorbis, mode);
+       
+                       var codeBook:CodeBook = vorbis.setupHeader.codeBooks[classBook];
+       
+                       var classvalsPerCodeword:int = codeBook.dimensions;
+                       var nToRead:int = end - begin;
+                       var partitionsToRead:int = nToRead / partitionSize; // partvals
+       
+                       var samplesPerPartition:int = partitionSize;
+                       var partitionsPerWord:int = look.phrasebook.dimensions;
+       
+                       var partWords:int = (partitionsToRead + partitionsPerWord - 1) / partitionsPerWord;
+       
+                       var offset:int;
+                       
+                       var left:Boolean = false;
+                       var right:Boolean = false;
+                       
+                       for (i = 0; i < doNotDecodeFlags.length; i++) {
+                               if (!doNotDecodeFlags[i]) {
+                                       if(i==0) {
+                                               left = true;
+                                       }
+                                       else if (i==1) {
+                                               right = true;
+                                       }
+                               }
+                       }
+       
+                       var partword:Array = new Array(partWords);
+                       
+                       var pb:int = source.position;
+                       
+                       slim = look.stages;
+                       for (s = 0; s < slim; s++) {
+                               
+                               for (i = 0, l = 0; i < partitionsToRead; l++) {
+                               
+                                       if (s == 0) {
+                                               var temp:int = source.readUnsignedHuffmanInt(look.phrasebook.huffmanRoot);
+                                               if (temp == -1) {
+                                                       throw new Error("Foo??");
+                                               }
+                                               partword[l] = look.decodemap[temp];
+                                               if (partword[l] == null) {
+                                                       throw new Error("Foo??");
+                                               }
+                                       }
+       
+                                       for (k = 0; k < partitionsPerWord && i < partitionsToRead; k++, i++) {
+                                               offset = begin + i * samplesPerPartition;
+
+                                               if ((cascade[partword[l][k]] & (1 << s)) != 0) {
+                                                       var stagebook:CodeBook = 
+                                                               vorbis.setupHeader.codeBooks[look.partbooks[partword[l][k]][s]];
+                                                       if (stagebook != null) {
+                                                               stagebook.readVvAdd(vectors0, vectors1, left, right, source, offset, samplesPerPartition);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               
+               }
+               
+       }
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/SetupHeader.as b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/SetupHeader.as
new file mode 100644 (file)
index 0000000..1d1350f
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+       import org.omtk.util.BitByteArray;
+
+       public class SetupHeader {
+       
+               private var _codeBooks:Vector.<CodeBook>;
+               private var _floors:Vector.<Floor>;
+               private var _residues:Vector.<Residue>;
+               private var _mappings:Vector.<Mapping>;
+               private var _modes:Vector.<Mode>;
+               
+               public function SetupHeader(stream:VorbisStream, source:BitByteArray) {
+
+                       var i:int;
+               
+                       source.readByte();
+                       source.readByte();
+                       source.readByte();
+                       source.readByte();
+                       source.readByte();
+                       source.readByte();
+       
+                       var codeBookCount:uint = source.readUnsignedBitwiseInt(8)+1;
+                       _codeBooks = new Vector.<CodeBook>(codeBookCount);
+                       
+                       for(i = 0; i < codeBookCount; i++) {
+                               _codeBooks[i] = new CodeBook(source);
+                       }
+                       
+                       // read the time domain transformations,
+                       // these should all be 0
+       
+                       var timeCount:int = source.readUnsignedBitwiseInt(6) + 1;
+                       for (i = 0; i < timeCount; i++) {
+                               if (source.readUnsignedBitwiseInt(16) != 0) {
+                                       throw new Error(
+                                                       "Time domain transformation != 0");
+                               }
+                       }
+                       
+                       // read floor entries
+       
+                       var floorCount:int = source.readUnsignedBitwiseInt(6) + 1;
+                       _floors = new Vector.<Floor>(floorCount);
+       
+                       for (i = 0; i < floorCount; i++) {
+                               _floors[i] = Floor.createInstance(source, this);
+                       }
+
+                       var residueCount:int = source.readUnsignedBitwiseInt(6) + 1;
+                       _residues = new Vector.<Residue>(residueCount);
+
+                       for (i = 0; i < residueCount; i++) {
+                               _residues[i] = Residue.createInstance(source, this);
+                       }
+                       
+                       var mappingCount:int = source.readUnsignedBitwiseInt(6) + 1;
+                       _mappings = new Vector.<Mapping>(mappingCount);
+       
+                       for (i = 0; i < mappingCount; i++) {
+                               _mappings[i] = Mapping.createInstance(stream, source, this);
+                       }
+                       
+                       var modeCount:int = source.readUnsignedBitwiseInt(6) + 1;
+                       _modes = new Vector.<Mode>(modeCount);
+       
+                       for (i = 0; i < modeCount; i++) {
+                               _modes[i] = new Mode(source, this);
+                       }
+       
+                       if (!source.readBit()) {
+                               throw new Error("The setup header framing bit is incorrect.");
+                       }
+               }
+       
+               public function get codeBooks():Vector.<CodeBook> {
+                       return _codeBooks;
+               }
+       
+               public function get floors():Vector.<Floor> {
+                       return _floors;
+               }
+
+               public function get mappings():Vector.<Mapping> {
+                       return _mappings;
+               }
+       
+               public function get residues():Vector.<Residue> {
+                       return _residues;
+               }
+
+               public function get modes():Vector.<Mode> {
+                       return _modes;
+               }
+               
+       }
+
+
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/Util.as b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/Util.as
new file mode 100644 (file)
index 0000000..f6e7ed1
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+       public class Util {
+
+               public static function ilog(x:uint):uint {
+                       var res:int = 0;
+                       for(; x>0; x>>=1, res++);
+                       return res;
+               }       
+               
+               public static function float32unpack(x:uint):Number {
+                       var mantissa:Number = x&0x1fffff;
+                       var e:Number = (x&0x7fe00000)>>21;
+                       if((x&0x80000000)!=0) {
+                               mantissa=-mantissa;
+                       }
+                       return mantissa*Math.pow(2.0, e-788.0);
+               }
+
+               public static function lookup1Values(a:int, b:int):uint {
+                       var res:uint = Math.pow(Math.E, Math.log(a)/b);
+                       return intPow(res+1, b)<=a?res+1:res;
+               }
+
+               public static function intPow(base:uint, e:uint):uint {
+                       var res:uint = 1;
+                       for(; e>0; e--, res*=base);
+                       return res;
+               }
+
+               public static function isBitSet(value:uint, bit:uint):Boolean {
+                       return (value&(1<<bit))!=0;
+               }
+               
+               public static function icount(value:uint):uint {
+                       var res:uint = 0;
+                       while (value > 0) {
+                               res += value & 1;
+                               value >>= 1;
+                       }
+                       return res;
+               }
+
+               public static function lowNeighbour(v:Vector.<int>, x:int):int {
+
+                       var max:int = -1;
+                       var n:int = 0;
+                       var i:int;
+                       
+                       for (i = 0; i < v.length && i < x; i++) {
+                               if (v[i] > max && v[i] < v[x]) {
+                                       max = v[i];
+                                       n = i;
+                               }
+                       }
+                       return n;
+               }
+
+               public static function highNeighbour(v:Vector.<int>, x:int):int {
+                       
+                       var min:int = int.MAX_VALUE;
+                       var n:int = 0;
+                       var i:int;
+                       
+                       for (i = 0; i < v.length && i < x; i++) {
+                               if (v[i] < min && v[i] > v[x]) {
+                                       min = v[i];
+                                       n = i;
+                               }
+                       }
+                       return n;
+               }
+
+               public static function renderPoint(x0:int, x1:int, y0:int, y1:int, x:int):int {
+                       return y0 + int(((y1-y0) * (x - x0)) / (x1 - x0));
+               }
+
+               public static function renderLine(x0:int, y0:int, x1:int, y1:int, v:Vector.<Number>):void {
+               
+                       var dy:int = y1 - y0;
+                       var adx:int = x1 - x0;
+                       var b:int = dy / adx;
+                       var sy:int = dy < 0 ? b - 1 : b + 1;
+                       var x:int = x0;
+                       var y:int = y0;
+                       var err:int = 0;
+                       var ady:int = (dy < 0 ? -dy : dy) - (b > 0 ? b * adx : -b * adx);
+       
+                       v[x] *= Floor.DB_STATIC_TABLE[y];
+                       for (x = x0 + 1; x < x1; x++) {
+                               err += ady;
+                               if (err >= adx) {
+                                       err -= adx;
+                                       v[x] *= Floor.DB_STATIC_TABLE[y += sy];
+                               } else {
+                                       v[x] *= Floor.DB_STATIC_TABLE[y += b];
+                               }
+                       }
+
+               }
+
+       }
+       
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/VorbisSound.as b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/VorbisSound.as
new file mode 100644 (file)
index 0000000..c82bb72
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+       import flash.net.URLRequest;
+       import flash.net.URLStream;
+       import flash.utils.ByteArray;
+       import flash.utils.Endian;
+       import flash.events.Event;
+       import flash.events.ProgressEvent;
+       import flash.events.SampleDataEvent;
+       
+       import flash.external.ExternalInterface;
+
+       import flash.media.Sound;
+       
+       import org.omtk.ogg.UncachedUrlStream;
+       import org.omtk.ogg.EndOfOggStreamError;
+       import flash.utils.setTimeout;
+       
+       public class VorbisSound extends Sound {
+       
+               public static var METADATA_UPDATE: String = "metadata_update";
+       
+               private var urlStream: URLStream;
+               
+               private var oggStream:UncachedUrlStream;
+               private var vorbisStream:VorbisStream;
+
+               private var bytesAvailable:int;
+
+               private var initialized:Boolean = false;
+               private var playing:Boolean = false;
+               
+               private var fill1:Boolean = true;
+               private var fill2:Boolean = true;
+               
+               private var stopped: Boolean = false;
+               private var completeEventDispatched: Boolean = false;
+               
+               public function VorbisSound(url: URLRequest ) {
+                       urlStream = new URLStream();
+                       urlStream.endian = Endian.LITTLE_ENDIAN;
+                       urlStream.load(url);
+
+                       Mdct.initialize();
+
+                       oggStream = new UncachedUrlStream(urlStream);
+                       oggStream.addEventListener('progress', progress);
+                       bytesAvailable = oggStream.bytesAvailable;
+                       addEventListener("sampleData", sampleGenerator);
+               }
+               
+               private function initialize():void {
+                       vorbisStream = new VorbisStream(oggStream.getLogicalOggStream());
+                       setTimeout(dispatchEvent, 100, new Event(METADATA_UPDATE));
+                       initialized = true;
+               }
+               
+               private var samplesPlayed: int = 0;
+               
+               private function sampleGenerator(event:SampleDataEvent):void {
+                       
+                       if(stopped) {
+                               return;
+                       }
+                       
+                       if(Mdct.initialized && !initialized && bytesAvailable > 64*1024) {
+                               initialize();
+                       }
+                       
+                       if(initialized && bytesAvailable > 16*1024 && !vorbisStream.finished) {
+                               var cnt: int;
+                               cnt = vorbisStream.readPcm(event.data);
+                               samplesPlayed += cnt;
+                               if(cnt < 2048 && oggStream.bytesAvailable > 0) {
+                                       vorbisStream = new VorbisStream(oggStream.getLogicalOggStream());
+                                       setTimeout(dispatchEvent, 100, new Event(METADATA_UPDATE));
+                                       samplesPlayed += vorbisStream.readPcm(event.data);
+                               }
+                       }
+                       else if(vorbisStream == null || !vorbisStream.finished) {
+                           for(var c:int=0; c<2048; c++) {
+                               event.data.writeFloat(0);
+                               event.data.writeFloat(0);
+                           }
+                       }
+                       
+                       if(initialized && vorbisStream.finished && oggStream.bytesAvailable == 0 && !completeEventDispatched) {
+                               dispatchEvent(new Event(Event.COMPLETE));
+                               completeEventDispatched = true;
+                       }
+                       
+                       //trace("samples played: " + samplesPlayed + "/" + oggStream.bytesAvailable);
+                       
+               }
+
+               public function stop(): void {
+                       stopped = true;
+               }
+
+               public function progress(event:ProgressEvent):void {
+                       bytesAvailable = oggStream.bytesAvailable;
+               }
+
+               public function get position(): int {
+                       return samplesPlayed * 1000 / 44100;
+               }
+
+               public function getMetaData(key: String):String {
+                       if(vorbisStream != null) {
+                               return vorbisStream.commentHeader.comments[key];
+                       }
+                       else {
+                               return null;
+                       }
+               }
+       }
+       
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/VorbisStream.as b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/as/org/omtk/vorbis/VorbisStream.as
new file mode 100644 (file)
index 0000000..0c37fa1
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+       import flash.events.SampleDataEvent;
+       import flash.utils.ByteArray;
+       import flash.utils.Endian;
+       import org.omtk.util.*;
+       import org.omtk.ogg.*;
+       
+       public class VorbisStream {
+       
+               private const IDENTIFICATION_HEADER:int = 1;
+               private const COMMENT_HEADER:int = 3;
+               private const SETUP_HEADER:int = 5;
+               
+               private var source:LogicalOggStream;
+       
+               private var _identificationHeader:IdentificationHeader;
+               private var _commentHeader:CommentHeader;
+               private var _setupHeader:SetupHeader;
+               
+               private var _lastAudioPacket:AudioPacket;
+               
+               private var _currentGranulePosition:int=0;
+               private var packetCounter:int;
+               
+               private var _finished: Boolean = false;
+               
+               public var windows:Vector.<Vector.<Number>> = new Vector.<Vector.<Number>>(8);
+
+               public function VorbisStream(source:LogicalOggStream) {
+
+                       this.source = source;
+
+                       for (var i:int = 0; i < 3; i++) {
+
+                               var data:BitByteArray = source.getNextOggPacket().data;
+                               var headerType:int = data.readUnsignedByte();
+
+                               switch(headerType) {
+                               case IDENTIFICATION_HEADER:
+                                       _identificationHeader = new IdentificationHeader(data);
+                                       break;
+                               case COMMENT_HEADER:
+                                       _commentHeader = new CommentHeader(data);
+                                       break;
+                               case SETUP_HEADER:
+                                       _setupHeader = new SetupHeader(this, data);
+                                       break;
+                               }
+                       }
+                       
+               }
+       
+               public function get identificationHeader():IdentificationHeader {
+                       return _identificationHeader;
+               }
+               
+               public function get commentHeader():CommentHeader {
+                       return _commentHeader;
+               }
+               
+               public function get setupHeader():SetupHeader {
+                       return _setupHeader;
+               }
+       
+               public function readPcm(data:ByteArray): int {
+               
+                       var total:int;
+                       var i:int;
+                       
+                       if(_lastAudioPacket == null) {
+                               _lastAudioPacket = getNextAudioPacket();
+                       }
+
+                       total = 0;
+                       
+                       while(total < 2048 && !_finished) {
+                               try {
+                                       var ap:AudioPacket = getNextAudioPacket();
+                                       total += ap.readPcm(_lastAudioPacket, data);
+                                       _lastAudioPacket = ap;
+                               }
+                               catch(e: EndOfOggStreamError) {
+                                       // ok, stream finished
+                                       _finished = true;
+                               }
+                       }
+                                               
+                       return total;
+               }
+
+               private function getNextAudioPacket():AudioPacket {
+                       packetCounter++;
+                       var packet:OggPacket = source.getNextOggPacket();
+                       var res:AudioPacket = new AudioPacket(this, packet, _currentGranulePosition);
+                       if(_lastAudioPacket != null) {
+                               // don't count the first packet, since it doesn't contain any "real" samples
+                               _currentGranulePosition += res.numberOfSamples;
+                       }
+                       return res;
+               }       
+               
+               public function get finished() : Boolean {
+                       return _finished;
+               }
+               
+               public function get currentGranulePosition(): int {
+                       return _currentGranulePosition;
+               }
+       }
+       
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/haXe/build.hxml b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/haXe/build.hxml
new file mode 100644 (file)
index 0000000..be51ca9
--- /dev/null
@@ -0,0 +1,3 @@
+-main org.omtk.vorbis.MdctHX
+-swf-version 10
+-swf hxmdct.swf
diff --git a/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/haXe/org/omtk/vorbis/MdctHX.hx b/js2/mwEmbed/libEmbedVideo/binPlayers/omtk-fx/src/haXe/org/omtk/vorbis/MdctHX.hx
new file mode 100644 (file)
index 0000000..4461c32
--- /dev/null
@@ -0,0 +1,337 @@
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+
+package org.omtk.vorbis;
+
+import flash.Vector;
+
+class MdctHX {
+
+       private static var cPI1_8:Float = 0.92387953251128675613;
+       private static var cPI2_8:Float = 0.70710678118654752441;
+       private static var cPI3_8:Float = 0.38268343236508977175;
+       
+       private var n:Int;
+       private var log2n:Int;
+       private var trig:Vector<Float>;
+       private var bitrev:Vector<Int>;
+       
+       private var dtmp1:Float;
+       private var dtmp2:Float;
+       private var dtmp3:Float;
+       private var dtmp4:Float;
+
+       private var x:Vector<Float>;
+       private var w:Vector<Float>;
+
+       public function new(n:Int) { 
+               this.n = n;
+       
+               var i:Int;
+               var j:Int;
+               
+               bitrev = new Vector<Int>();
+               trig = new Vector<Float>(Std.int(n+n/4), true);
+
+               for(i in 0...Std.int(n+n/4)) {
+                       trig[i] = 0;
+               }
+
+               x = new Vector<Float>(Std.int(n/2), true);
+               w = new Vector<Float>(Std.int(n/2), true);
+
+               for(i in 0...Std.int(n/2)) {
+                       x[i] = 0;
+                       w[i] = 0;
+               }
+               
+               var n2:Int = n >>> 1;
+               log2n = Math.round(Math.log(n) / Math.log(2));
+
+               var AE:Int = 0;
+               var AO:Int = 1;
+               var BE:Int = Std.int(AE + n / 2);
+               var BO:Int = BE + 1;
+               var CE:Int = Std.int(BE + n / 2);
+               var CO:Int = CE + 1;
+               
+               for (i in 0...Std.int(n/4)) {
+                       trig[AE + i * 2] = Math.cos((Math.PI / n) * (4 * i));
+                       trig[AO + i * 2] = -Math.sin((Math.PI / n) * (4 * i));
+                       trig[BE + i * 2] = Math.cos((Math.PI / (2 * n)) * (2 * i + 1));
+                       trig[BO + i * 2] = Math.sin((Math.PI / (2 * n)) * (2 * i + 1));
+               }
+
+               for (i in 0...Std.int(n/8)) {
+                       trig[CE + i * 2] = Math.cos((Math.PI / n) * (4 * i + 2));
+                       trig[CO + i * 2] = -Math.sin((Math.PI / n) * (4 * i + 2));
+               }
+               
+               var mask:Int = (1 << (log2n - 1)) - 1;
+               var msb:Int = 1 << (log2n - 2);
+               
+               for (i in 0...Std.int(n/8)) {
+                       var acc:Int = 0;
+                       j = 0;
+                       while(msb>>>j!=0) {
+                               if (((msb >>> j) & i) != 0) {
+                                       acc |= 1 << j;
+                               }
+                               j++;
+                       }
+                       bitrev[i * 2] = ((~acc) & mask);
+                       bitrev[i * 2 + 1] = acc;
+               }
+               
+       } 
+
+       public function imdct(frq:Vector<Float>, window:Vector<Float>, pcm:Vector<Float>):Void {
+       
+               var i:Int;
+
+               var n2:Int;
+               var n4:Int;
+               var n8:Int;
+
+               var inO:Int;
+               var xO:Int;
+               var A:Int;
+
+               var temp1:Float;
+               var temp2:Float;
+
+               var B:Int;
+               var o1:Int;
+               var o2:Int;
+               var o3:Int;
+               var o4:Int;
+
+               var xx:Int;
+               var xxx:Vector<Float>;
+               
+               n2 = n >> 1;
+               n4 = n >> 2;
+               n8 = n >> 3;
+
+               inO = -1;
+               xO = 0;
+               A = n2;
+               
+               temp1 = 0.0;
+               temp2 = 0.0;
+               
+               for (i in 0...n8) {
+                       dtmp1 = frq[inO += 2];
+                       dtmp2 = frq[inO += 2];
+                       dtmp3 = trig[--A];
+                       dtmp4 = trig[--A];
+                       x[xO++] = -dtmp2 * dtmp3 - dtmp1 * dtmp4;
+                       x[xO++] = dtmp1 * dtmp3 - dtmp2 * dtmp4;
+               }
+
+               inO = n2;
+
+               for(i in 0...n8) {
+                       dtmp1 = frq[inO -= 2];
+                       dtmp2 = frq[inO -= 2];
+                       dtmp3 = trig[--A];
+                       dtmp4 = trig[--A];
+                       x[xO++] = dtmp2 * dtmp3 + dtmp1 * dtmp4;
+                       x[xO++] = dtmp2 * dtmp4 - dtmp1 * dtmp3;
+               }
+
+               xxx = kernel(x, w, n, n2, n4, n8);
+               xx = 0;
+               
+               B = n2;
+               o1 = n4;
+               o2 = o1 - 1;
+               o3 = n4 + n2;
+               o4 = o3 - 1;
+
+               for (i in 0...n4) {
+                       dtmp1 = xxx[xx++];
+                       dtmp2 = xxx[xx++];
+                       dtmp3 = trig[B++];
+                       dtmp4 = trig[B++];
+
+                       temp1 = (dtmp1 * dtmp4 - dtmp2 * dtmp3);
+                       temp2 = -(dtmp1 * dtmp3 + dtmp2 * dtmp4);
+
+                       pcm[o1] = -temp1 * window[o1];
+                       pcm[o2] = temp1 * window[o2];
+                       pcm[o3] = temp2 * window[o3];
+                       pcm[o4] = temp2 * window[o4];
+
+                       o1++;
+                       o2--;
+                       o3++;
+                       o4--;
+               }
+               
+       }
+
+       private inline function kernel(x:Vector<Float>, w:Vector<Float>, n:Int, n2:Int, n4:Int, n8:Int):Vector<Float> {
+
+               var i:Int;
+               var r:Int;
+               var s:Int;
+               var rlim:Int;
+               var slim:Int;
+               
+               var xA:Int = n4;
+               var xB:Int = 0;
+               var w1:Int = 0;
+               var w2:Int = n4;
+               var A:Int = n2;
+
+               var x0:Float;
+               var x1:Float;
+               var wA:Float;
+               var wB:Float;
+               var wC:Float;
+               var wD:Float;
+               var k0:Int;
+               var k1:Int;
+               var t1:Int;
+               var t2:Int;
+               
+               var wbase:Int;
+               var temp:Vector<Float>;
+               
+               var wACE:Float;
+               var wBCE:Float;
+               var wACO:Float;
+               var wBCO:Float;
+                       
+               var AEv:Float;
+               var AOv:Float;
+                       
+               i=0;
+               while(i < n4) {
+                       x0 = x[xA] - x[xB];
+                       
+                       w[w2 + i] = x[xA++] + x[xB++];
+
+                       x1 = x[xA] - x[xB];
+                       A -= 4;
+
+                       w[i++] = x0 * trig[A] + x1 * trig[A + 1];
+                       w[i] = x1 * trig[A] - x0 * trig[A + 1];
+
+                       w[w2 + i] = x[xA++] + x[xB++];
+                       i++;
+               }
+
+               for (i in 0...log2n-3) {
+                       k0 = n >>> (i + 2);
+                       k1 = 1 << (i + 3);
+                       wbase = n2 - 2;
+
+                       A = 0;
+
+                       rlim = k0 >>> 2;
+                       for (r in 0...rlim) {
+                       
+                               w1 = wbase;
+                               w2 = w1 - (k0 >> 1);
+                               AEv = trig[A];
+                               AOv = trig[A + 1];
+                               wbase -= 2;
+
+                               k0++;
+                               
+                               slim = 2 << i;
+                               for (s in 0...slim) {
+                                       dtmp1 = w[w1];
+                                       dtmp2 = w[w2];
+                                       wB = dtmp1 - dtmp2;
+                                       x[w1] = dtmp1 + dtmp2;
+                                       dtmp1 = w[++w1];
+                                       dtmp2 = w[++w2];
+                                       wA = dtmp1 - dtmp2;
+                                       x[w1] = dtmp1 + dtmp2;
+                                       x[w2] = wA * AEv - wB * AOv;
+                                       x[w2-1] = wB * AEv + wA * AOv;
+                                       w1 -= k0;
+                                       w2 -= k0;
+                               }
+                               k0--;
+                               A += k1;
+                       }
+
+                       temp = w;
+                       w = x;
+                       x = temp;
+               }
+               
+
+               var C:Int = n;
+               var bit:Int = 0;
+               var xx1:Int = 0;
+               var xx2:Int = n2 - 1;
+               
+               var wt1: Float;
+               var wt2: Float;
+               var wt12: Float;
+               var wt21: Float;
+               var trigV: Float;
+
+               for (i in 0...n8) {
+                       t1 = bitrev[bit++];
+                       t2 = bitrev[bit++];
+                       
+                       wt1 = w[t1];
+                       wt2 = w[t2];
+                       wt12 = w[t1-1];
+                       wt21 = w[t2+1];
+
+                       wA = wt1 - wt21;
+                       wB = wt12 + wt2;
+                       wC = wt1 + wt21;
+                       wD = wt12 - wt2;
+                       
+                       trigV = trig[C];
+
+                       wACE = wA * trigV;
+                       wBCE = wB * trigV;
+                       
+                       trigV = trig[++C];
+                       
+                       wACO = wA * trigV;
+                       wBCO = wB * trigV;
+                       
+                       ++C;
+
+                       x[xx1++] = (wC + wACO + wBCE);
+                       x[xx2--] = (-wD + wBCO - wACE);
+                       x[xx1++] = (wD + wBCO - wACE);
+                       x[xx2--] = (wC - wACO - wBCE);
+               }
+
+               return x;
+       }       
+
+       /*
+        * Dummy function required for the haXe compiler to build this to
+        * a .SWF file.
+        */
+       public static function main() : Void {  
+       }
+       
+}
diff --git a/js2/mwEmbed/libEmbedVideo/embedVideo.js b/js2/mwEmbed/libEmbedVideo/embedVideo.js
new file mode 100644 (file)
index 0000000..c025f17
--- /dev/null
@@ -0,0 +1,2711 @@
+/*  the base video control JSON object with default attributes
+*      for supported attribute details see README
+*/
+
+loadGM( {
+       "mwe-loading_plugin" : "loading plugin ...",
+       "mwe-select_playback" : "Set playback preference",
+       "mwe-link_back" : "Link back",
+       "mwe-error_swap_vid" : "Error: mv_embed was unable to swap the video tag for the mv_embed interface",
+       "mwe-add_to_end_of_sequence" : "Add to end of sequence",
+       "mwe-missing_video_stream" : "The video file for this stream is missing",
+       "mwe-play_clip" : "Play clip",
+       "mwe-pause_clip" : "Pause clip",
+       "mwe-volume_control" : "Volume control",
+       "mwe-player_options" : "Player options",
+       "mwe-closed_captions" : "Closed captions",
+       "mwe-player_fullscreen" : "Fullscreen",
+       "mwe-next_clip_msg" : "Play next clip",
+       "mwe-prev_clip_msg" : "Play previous clip",
+       "mwe-current_clip_msg" : "Continue playing this clip",
+       "mwe-seek_to" : "Seek $1",
+       "mwe-paused" : "paused",
+       "mwe-download_segment" : "Download selection:",
+       "mwe-download_full" : "Download full video file:",
+       "mwe-download_right_click" : "To download, right click and select <i>Save link as...<\/i>",
+       "mwe-download_clip" : "Download video",
+       "mwe-download_text" : "Download text (<a style=\"color:white\" title=\"cmml\" href=\"http:\/\/wiki.xiph.org\/index.php\/CMML\">CMML<\/a> xml):",
+       "mwe-download" : "Download",
+       "mwe-share" : "Share",
+       "mwe-credits" : "Credits",
+       "mwe-clip_linkback" : "Clip source page",
+       "mwe-chose_player" : "Choose video player",
+       "mwe-share_this_video" : "Share this video",
+       "mwe-video_credits" : "Video credits",
+       "mwe-menu_btn" : "Menu",
+       "mwe-close_btn" : "Close",
+       "mwe-ogg-player-vlc-player" : "VLC player",
+       "mwe-ogg-player-videoElement" : "Native Ogg video",
+       "mwe-ogg-player-oggPlugin" : "Generic Ogg plugin",
+       "mwe-ogg-player-quicktime-mozilla" : "QuickTime plugin",
+       "mwe-ogg-player-quicktime-activex" : "QuickTime ActiveX",
+       "mwe-ogg-player-cortado" : "Java Cortado",
+       "mwe-ogg-player-flowplayer" : "Flowplayer",
+       "mwe-ogg-player-kplayer" : "Kaltura player",
+       "mwe-ogg-player-selected" : "(selected)",
+       "mwe-ogg-player-omtkplayer" : "OMTK Flash Vorbis",
+       "mwe-generic_missing_plugin" : "You browser does not appear to support the following playback type: <b>$1<\/b><br \/>Visit the <a href=\"http:\/\/commons.wikimedia.org\/wiki\/Commons:Media_help\">Playback Methods<\/a> page to download a player.<br \/>",
+       "mwe-for_best_experience" : "For a better video playback experience we recommend:<br \/><b><a href=\"http:\/\/www.mozilla.com\/en-US\/firefox\/upgrade.html?from=mwEmbed\">Firefox 3.5<\/a>.<\/b>",
+       "mwe-do_not_warn_again" : "Dismiss for now.",
+       "mwe-playerselect" : "Players",
+       "mwe-read_before_embed" : "<a href=\"http:\/\/mediawiki.org\/wiki\/Security_Notes_on_Remote_Embedding\" target=\"_new\">Read this<\/a> before embedding.",
+       "mwe-embed_site_or_blog" : "Embed on a page",
+       "mwe-related_videos" : "Related videos",
+       "mwe-seeking" : "seeking",
+       "mwe-copy-code" : "Copy code",  
+       "mwe-video-h264" : "H.264 video",
+       "mwe-video-flv" : "Flash video",
+       "mwe-video-ogg" : "Ogg video",
+       "mwe-video-audio" : "Ogg audio"
+} );
+
+var default_video_attributes = {
+       "id" : null,
+       "class" : null,
+       "style" : null,
+       "name" : null,
+       "innerHTML" : null,
+       "width" : "320",
+       "height" : "240",
+
+       // video attributes:
+       "src" : null,
+       "autoplay" : false,
+       "start" : 0,
+       "end" : null,
+       "controls" : true,
+       "muted" : false,
+       "wikiTitleKey" : null,
+       
+       // roe url (for xml based metadata)
+       "roe" : null,
+       
+       // If roe includes metadata tracks we can expose a link to metadata
+       "show_meta_link" : true,
+
+       // default state attributes per html5 spec:
+       // http://www.whatwg.org/specs/web-apps/current-work/#video)
+       "paused" : true,
+       "readyState" : 0,  // http://www.whatwg.org/specs/web-apps/current-work/#readystate
+       "currentTime"  :0, // current playback position (should be updated by plugin)
+       "duration"  :null,   // media duration (read from file or the temporal url)
+       "networkState" : 0,
+
+       "startOffset" : null, // if serving an ogg_chop segment use this to offset the presentation time 
+
+       // custom attributes for mv_embed:
+       "play_button" : true,
+       "thumbnail" : null,
+       "linkback" : null,
+       "embed_link" : true,
+       "download_link" : true,
+       "type" :null     // the content type of the media 
+};
+/*
+ * the base source attribute checks
+ */
+var mv_default_source_attr = new Array(
+       'id',
+       'src',
+       'apisrc',
+       'titleKey',
+       'title',
+       'URLTimeEncoding', // boolean if we support temporal url requests on the source media
+       'startOffset',
+       
+       'durationHint',
+       'start',
+       'end',
+       
+       'default',
+       'lang'
+);
+// set the dismissNativeWarn flag: 
+_global['dismissNativeWarn'] = false;
+/*
+* Converts all occurrences of <video> tag into video object
+*/
+function mv_video_embed( swap_done_callback, force_id ) {
+       // check call stack
+       mvEmbed.init( swap_done_callback, force_id );
+}
+mvEmbed = {
+       // flist stores the set of functions to run after the video has been swapped in. 
+       flist:new Array(),
+       init:function( swap_callback, force_id ) {
+               var _this = this;
+               
+               if ( swap_callback )
+                       mvEmbed.flist.push( swap_callback );
+               // Get mv_embed location if it has not been set
+               js_log( 'mvEmbed:init: ' + mw.version );
+               
+               var loadPlaylistLib = false;
+               
+               // Setup the selector (should be a configuration option) 
+               if ( force_id == null && force_id != '' ) {
+                       var j_selector = 'video,audio,playlist';
+               } else {
+                       var j_selector = '#' + force_id;
+               }
+               js_log( 'EmbedVideo:: rewrite j_selector:: ' + j_selector );
+               // Process selected elements: 
+               // ie8 does not play well with the jQuery video,audio,playlist selector use native:                     
+               if ( $j.browser.msie && $j.browser.version >= 8 ) {
+                       jtags = j_selector.split( ',' );
+                       for ( var i = 0; i < jtags.length; i++ ) {
+                               if (    jtags[i].indexOf( '#' ) === 1 ) {
+                                       _this.doElementSwap( $j( j_selector ).get( 0 ) );
+                               } else {
+                                       $j( document.getElementsByTagName( jtags[i] ) ).each( function() {
+                                               _this.doElementSwap( this );
+                                       } );
+                               }
+                       }
+               } else {
+                       $j( j_selector ).each( function() {
+                               _this.doElementSwap( this );
+                       } );
+               }
+               // Check clips ready to call swap_callback now in ( mvEmbed.flist )
+               this.checkClipsReady();
+       },
+       doElementSwap: function( element ) {
+               if ( $j( element ).attr( "id" ) == '' ) {
+                       $j( element ).attr( "id", 'v' + mw.player_list.length );
+               }
+               js_log( "mvEmbed::rewrite:: " + $j( element ).attr( "id" ) + ' tag: ' + element.tagName.toLowerCase() );
+               
+               // Store a global reference to the id   
+               mw.player_list.push( $j( element ).attr( "id" ) );
+                       
+               switch( element.tagName.toLowerCase() ) {
+                       case 'video':
+                       case 'audio':
+                               var videoInterface = new embedVideo( element );
+                               mvEmbed.swapEmbedVideoElement( element, videoInterface );
+                       break;
+                       case 'playlist':
+                               // Make sure we have the necessary play-list libs loaded:
+                               mvJsLoader.doLoad( [
+                                       'mvPlayList',
+                                       '$j.ui',        // Include dialog for pop-ing up things
+                                       '$j.ui.dialog'
+                               ], function() {
+                                       var plObj = new mvPlayList( element );
+                                       mvEmbed.swapEmbedVideoElement( element, plObj );
+                                       var added_height = plObj.pl_layout.title_bar_height + plObj.pl_layout.control_height;
+                                       // Wrap a blocking display container with height + controls + title height: 
+                                       $j( '#' + plObj.id ).wrap( '<div style="display:block;height:' + ( plObj.height + added_height ) + 'px;"></div>' );
+                               } );
+                       break;
+          }
+       },
+       /*
+       * swapEmbedVideoElement
+       * takes a video element as input and swaps it out with
+       * an embed video interface based on the video_elements attributes
+       * @param {Element} video_element
+       * @param {Object}  
+       */
+       swapEmbedVideoElement:function( video_element, videoInterface ) {
+               js_log( 'do swap ' + videoInterface.id + ' for ' + video_element );
+               embed_video = document.createElement( 'div' );
+               // make sure our div has a hight/width set:
+
+               $j( embed_video ).css( {
+                       'width' : videoInterface.width,
+                       'height' : videoInterface.height
+               } ).html( mv_get_loading_img() );
+               // inherit the video interface
+               for ( var method in videoInterface ) { // for in loop oky in Element context    
+                       if ( method != 'readyState' ) { // readyState crashes IE
+                               if ( method == 'style' ) {
+                                               embed_video.setAttribute( 'style', videoInterface[method] );
+                               } else if ( method == 'class' ) {
+                                       if ( $j.browser.msie )
+                                               embed_video.setAttribute( "className", videoInterface['class'] );
+                                       else
+                                               embed_video.setAttribute( "class", videoInterface['class'] );
+                               } else {
+                                       // normal inherit:
+                                       embed_video[method] = videoInterface[method];
+                               }
+                       }
+                       // string -> boolean:
+                       if ( embed_video[method] == "false" )
+                               embed_video[method] = false;
+                               
+                       if ( embed_video[method] == "true" )
+                               embed_video[method] = true;
+               }
+                                 
+               // Now swap out the video element for the embed_video obj:        
+               $j( video_element ).after( embed_video ).remove();
+               $j( '#' + embed_video.id ).get( 0 ).on_dom_swap();
+                         
+               // Now that "embed_video" is stable, do more initialization (if we are ready)
+               if ( $j( '#' + embed_video.id ).get( 0 ).loading_external_data == false
+                        && $j( '#' + embed_video.id ).get( 0 ).init_with_sources_loadedDone == false ) {
+                       // load and set ready state since source are available: 
+                       $j( '#' + embed_video.id ).get( 0 ).init_with_sources_loaded();
+               }
+               js_log( 'done with child: ' + embed_video.id + ' len:' + mw.player_list.length );
+               return true;
+       },
+       /**
+       * Check if Clips in the player_list are ready and runs 
+       * any associated queued functions 
+       */
+       checkClipsReady : function() {
+               // js_log('checkClipsReady');
+               var is_ready = true;
+               for ( var i = 0; i < mw.player_list.length; i++ ) {
+                         if ( $j( '#' + mw.player_list[i] ).length != 0 ) {
+                               var cur_vid =  $j( '#' + mw.player_list[i] ).get( 0 );
+                               
+                               is_ready = ( cur_vid.ready_to_play ) ? is_ready : false;
+                               
+                               if ( !is_ready && cur_vid.load_error ) {
+                                       is_ready = true;
+                                       // Update the video with its load error:
+                                       $j( cur_vid ).html( cur_vid.load_error );
+                               }
+                       }
+               }
+               if ( is_ready ) {
+                       mvEmbed.allClipsReady = true;
+                       // run queued functions 
+                       // js_log('run queded functions:' + mvEmbed.flist[0]);
+                       mvEmbed.runFlist();
+               } else {
+                        setTimeout( 'mvEmbed.checkClipsReady()', 25 );
+                }
+       },
+       runFlist:function() {
+               while ( this.flist.length ) {
+                       this.flist.shift()();
+               }
+       }
+}
+
+/**
+  * mediaSource class represents a source for a media element.
+  * @param {Element} element: MIME type of the source.
+  * @constructor
+  */
+function mediaSource( element ) {
+       this.init( element );
+}
+
+mediaSource.prototype = {
+       /** MIME type of the source. */
+       mime_type:null,
+       /** URI of the source. */
+       uri:null,
+       /** Title of the source. */
+       title:null,
+       /** True if the source has been marked as the default. */
+       marked_default:false,
+       /** True if the source supports url specification of offset and duration */
+       URLTimeEncoding:false,
+       /** Start offset of the requested segment */
+       start_offset:null,
+       /** Duration of the requested segment (0 if not known) */
+       duration:0,
+       is_playable:null,
+       upddate_interval:null,
+
+       id:null,
+       start_ntp:null,
+       end_ntp:null,
+       /**
+       * MediaSource constructor:
+       */
+       init : function( element ) {
+               // js_log('adding mediaSource: ' + element);                            
+               this.src = $j( element ).attr( 'src' );
+               this.marked_default = false;
+               if ( element.tagName.toLowerCase() == 'video' )
+                       this.marked_default = true;
+               
+               // Set default URLTimeEncoding if we have a time  url:
+               // not ideal way to discover if content is on an oggz_chop server. 
+               // should check some other way. 
+               var pUrl = mw.parseUri ( this.src );
+               if ( typeof pUrl['queryKey']['t'] != 'undefined' ) {
+                       this['URLTimeEncoding'] = true;
+               }
+               for ( var i = 0; i < mv_default_source_attr.length; i++ ) { // array loop:
+                       var attr = mv_default_source_attr[ i ];
+                       if ( $j( element ).attr( attr ) ) {
+                               this[ attr ] =  $j( element ).attr( attr );
+                       }
+               }
+                                       
+                       
+               if ( $j( element ).attr( 'type' ) )
+                       this.mime_type = $j( element ).attr( 'type' );
+               else if ( $j( element ).attr( 'content-type' ) )
+                       this.mime_type = $j( element ).attr( 'content-type' );
+               else
+                       this.mime_type = this.detectType( this.src );                           
+
+               this.parseURLDuration();
+       },
+       /**
+       * Update Source title via Element
+       * @param Element:       
+       */
+       updateSource:function( element ) {
+               // for now just update the title: 
+               if ( $j( element ).attr( "title" ) )
+                       this.title = $j( element ).attr( "title" );
+       },
+       /** 
+        * Updates the src time and start & end
+        * @param {String} start_time: in NTP format
+        * @param {String} end_time: in NTP format
+        */
+       updateSrcTime:function ( start_ntp, end_ntp ) {
+               // js_log("f:updateSrcTime: "+ start_ntp+'/'+ end_ntp + ' from org: ' + this.start_ntp+ '/'+this.end_ntp);
+               // js_log("pre uri:" + this.src);
+               // if we have time we can use:
+               if ( this.URLTimeEncoding ) {
+                       // make sure its a valid start time / end time (else set default) 
+                       if ( !npt2seconds( start_ntp ) )
+                               start_ntp = this.start_ntp;
+                               
+                       if ( !npt2seconds( end_ntp ) )
+                               end_ntp = this.end_ntp;
+                                                                                 
+                       this.src = getURLParamReplace( this.src, { 
+                               't': start_ntp + '/' + end_ntp 
+                       });
+                       
+                       // update the duration
+                       this.parseURLDuration();
+               }
+       },
+       /**
+       * Sets the duration and sets the end time if unset 
+       * @param {Float} duration: in seconds
+       */
+       setDuration:function ( duration ) {
+               this.duration = duration;
+               if ( !this.end_ntp ) {
+                       this.end_ntp = seconds2npt( this.start_offset + duration );
+               }
+       },
+       /** 
+       * MIME type accessor function.
+       * @return {String} the MIME type of the source.
+       */
+       getMIMEType : function() {
+               return this.mime_type;
+       },
+       /** URI function.
+       * @param {Number} seek_time_sec  Int: Used to adjust the URI for url based seeks) 
+       * @return {String} the URI of the source.
+       */
+       getURI : function( seek_time_sec ) {
+               if ( !seek_time_sec || !this.URLTimeEncoding ) {
+                       return this.src;
+               }
+               if ( !this.end_ntp ) {
+                       var endvar = '';
+               } else {
+                       var endvar = '/' + this.end_ntp;
+               }
+               return getURLParamReplace( this.src,
+                       {
+                               't': seconds2npt( seek_time_sec ) + endvar
+                       }
+               );
+       },
+       /** Title accessor function.
+               @return the title of the source.
+               @type String
+       */
+       getTitle : function() { 
+               if( this.title )
+                       return this.title;
+                       
+               // Return a title based on mime type: 
+               switch( this.mime_type ){
+                       case 'video/h264' :
+                               return gM( 'mwe-video-h264' );
+                       break;
+                       case 'video/x-flv' :
+                               return gM( 'mwe-video-flv' );
+                       break;
+                       case 'video/ogg' :
+                               return gM( 'mwe-video-ogg' );
+                       break;
+                       case 'audio/ogg' :
+                               return gM( 'mwe-video-audio' );
+                       break;
+               } 
+               // Return the mime type string if not known type.
+               return this.mime_type;
+       },
+       /** Index accessor function.
+               @return the source's index within the enclosing mediaElement container.
+               @type Integer
+       */
+       getIndex : function() {
+               return this.index;
+       },
+       /*
+        * function parseURLDuration 
+        * getDuration in milliseconds
+        * special case derive duration from request url
+        * supports media_url?t=ntp_start/ntp_end url request format
+        */
+       parseURLDuration : function() {
+               // check if we have a URLTimeEncoding: 
+               if ( this.URLTimeEncoding ) {
+                       var annoURL = mw.parseUri( this.src );
+                       if ( annoURL.queryKey['t'] ) {
+                               var times = annoURL.queryKey['t'].split( '/' );
+                               this.start_ntp = times[0];
+                               this.end_ntp = times[1];
+                               this.start_offset = npt2seconds( this.start_ntp );
+                               this.duration = npt2seconds( this.end_ntp ) - this.start_offset;
+                       } else {
+                               // look for this info as attributes
+                               if ( this.startOffset ) {
+                                       this.start_offset = this.startOffset;
+                                       this.start_ntp = seconds2npt( this.startOffset );
+                               }
+                               if ( this.duration ) {
+                                       this.end_ntp = seconds2npt( parseInt( this.duration ) + parseInt( this.start_offset ) );
+                               }
+                       }
+               }
+       },
+       /** Attempts to detect the type of a media file based on the URI.
+       *       @param {String} uri URI of the media file.
+       *       @returns {String} The guessed MIME type of the file.
+       *       @type String
+       */
+       detectType:function( uri ) {
+               // @@todo if media is on the same server as the javascript
+               // we can issue a HEAD request and read the mime type of the media...
+               // (this will detect media mime type independently of the url name)
+               // http://www.jibbering.com/2002/4/httprequest.html (this should be done by extending jquery's ajax objects)
+               var end_inx =  ( uri.indexOf( '?' ) != -1 ) ? uri.indexOf( '?' ) : uri.length;
+               var no_param_uri = uri.substr( 0, end_inx );
+               switch( no_param_uri.substr( no_param_uri.lastIndexOf( '.' ), 4 ).toLowerCase() ) {
+                       case '.mp4':
+                               return 'video/h264';
+                       break;
+                       case '.flv':
+                               return 'video/x-flv';
+                       break;
+                       case '.ogg':
+                       case '.ogv':
+                               return 'video/ogg';
+                       break;
+                       case '.oga':
+                               return 'audio/ogg';
+                       break;
+                       case '.anx':
+                               return 'video/ogg';
+                       break;
+               }
+       }
+};
+
+/** 
+* A media element corresponding to a <video> element.
+*
+* It is implemented as a collection of mediaSource objects.  The media sources
+*      will be initialized from the <video> element, its child <source> elements,
+*      and/or the ROE file referenced by the <video> element.
+*      @param {element} video_element <video> element used for initialization.
+*      @constructor
+*/
+function mediaElement( element )
+{
+       this.init( element );
+};
+
+mediaElement.prototype = {
+       /** The array of mediaSource elements. */
+       sources:null,
+       addedROEData:false,
+       /** Selected mediaSource element. */
+       selected_source:null,
+       thumbnail:null,
+       linkback:null,
+
+       /** @private */
+       init:function( video_element )
+       {
+               var _this = this;
+               js_log( 'Initializing mediaElement...' );
+               this.sources = new Array();
+               this.thumbnail = mv_default_thumb_url;
+               
+               if ( $j( video_element ).attr( 'thumbnail' ) )
+                       this.thumbnail = $j( video_element ).attr( 'thumbnail' );
+                       
+               if ( $j( video_element ).attr( 'poster' ) )
+                       this.thumbnail = $j( video_element ).attr( 'poster' );
+               
+               if ( $j( video_element ).attr( 'wikiTitleKey' ) )
+                       this.wikiTitleKey = $j( video_element ).attr( 'wikiTitleKey' );
+               
+               if ( $j( video_element ).attr( 'durationHint' ) ) {
+                       this.durationHint = $j( video_element ).attr( 'durationHint' );
+                       // convert duration hint if needed:
+                       this.duration = npt2seconds(  this.durationHint );
+               }
+               
+               // Process the video_element as a source element:
+               if ( $j( video_element ).attr( "src" ) )
+                       this.tryAddSource( video_element );
+               
+               // Process all inner <source> elements  
+               $j( video_element ).find( 'source,text,itext' ).each( function( inx, inner_source ) {
+                       _this.tryAddSource( inner_source );
+               } );
+       },
+       /** 
+       * Updates the time request for all sources that have a standard time request argument (ie &t=start_time/end_time)
+       */
+       updateSourceTimes:function( start_ntp, end_ntp ) {
+               var _this = this;
+               $j.each( this.sources, function( inx, mediaSource ) {
+                       mediaSource.updateSrcTime( start_ntp, end_ntp );
+               } );
+       },
+       /*timed Text check*/
+       timedTextSources:function() {
+               for ( var i = 0; i < this.sources.length; i++ ) {
+                       if (    this.sources[i].mime_type == 'text/cmml' ||
+                               this.sources[i].mime_type == 'text/x-srt' )
+                                       return true;
+               };
+               return false;
+       },
+       /** Returns the array of mediaSources of this element.
+       *       @return {Array} of mediaSource elements.
+       */
+       getSources:function( mime_filter )
+       {
+               if ( !mime_filter )
+                       return this.sources;
+               // apply mime filter: 
+                  var source_set = new Array();
+               for ( var i = 0; i < this.sources.length ; i++ ) {
+                       if ( this.sources[i].mime_type.indexOf( mime_filter ) != -1 )
+                               source_set.push( this.sources[i] );
+               }
+               return source_set;
+       },
+       getSourceById:function( source_id ) {
+               for ( var i = 0; i < this.sources.length ; i++ ) {
+                       if ( this.sources[i].id ==  source_id )
+                               return this.sources[i];
+               }
+               return null;
+       },
+       /** Selects a particular source for playback.
+       */
+       selectSource:function( index )
+       {
+               js_log( 'f:selectSource:' + index );
+               var playable_sources = this.getPlayableSources();
+               for ( var i = 0; i < playable_sources.length; i++ ) {
+                       if ( i == index ) {
+                               this.selected_source = playable_sources[i];
+                               // Update the user selected format: 
+                               embedTypes.players.userSelectFormat( playable_sources[i].mime_type );
+                               break;
+                       }
+               }
+       },
+       /** 
+       * Selects the default source via cookie preference, default marked, or by id order
+       */
+       autoSelectSource:function() {
+               js_log( 'f:autoSelectSource:' );
+               // Select the default source
+               var playable_sources = this.getPlayableSources();
+               var flash_flag = ogg_flag = false;
+               // debugger;
+               for ( var source = 0; source < playable_sources.length; source++ ) {
+                       var mime_type = playable_sources[source].mime_type;
+                       if ( playable_sources[source].marked_default ) {
+                               js_log( 'set via marked default: ' + playable_sources[source].marked_default );
+                               this.selected_source = playable_sources[source];
+                               return true;
+                       }
+                       // Set via user-preference
+                       if ( embedTypes.players.preference['format_prefrence'] == mime_type ) {
+                                js_log( 'set via preference: ' + playable_sources[source].mime_type );
+                                this.selected_source = playable_sources[source];
+                                return true;
+                       }
+               }
+               // Set Ogg via player support           
+               for ( var source = 0; source < playable_sources.length; source++ ) {
+                       js_log( 'f:autoSelectSource:' + playable_sources[source].mime_type );
+                       var mime_type = playable_sources[source].mime_type;
+                          // set source via player                              
+                       if ( mime_type == 'video/ogg' || mime_type == 'ogg/video' || mime_type == 'video/annodex' || mime_type == 'application/ogg' ) {
+                               for ( var i = 0; i < embedTypes.players.players.length; i++ ) { // for in loop on object oky
+                                       var player = embedTypes.players.players[i];
+                                       if ( player.library == 'vlc' || player.library == 'native' ) {
+                                               js_log( 'set via ogg via order' );
+                                               this.selected_source = playable_sources[source];
+                                               return true;
+                                       }
+                               }
+                       }
+               }
+               // Set basic flash
+               for ( var source = 0; source < playable_sources.length; source++ ) {
+                       var mime_type = playable_sources[source].mime_type;
+                       if ( mime_type == 'video/x-flv' ) {
+                               js_log( 'set via by player preference normal flash' )
+                               this.selected_source = playable_sources[source];
+                               return true;
+                       }
+               }
+               // Set h264 flash 
+               for ( var source = 0; source < playable_sources.length; source++ ) {
+                       var mime_type = playable_sources[source].mime_type;
+                       if ( mime_type == 'video/h264' ) {
+                               js_log( 'set via playable_sources preference h264 flash' )
+                               this.selected_source = playable_sources[source];
+                               return true;
+                       }
+               }
+               // Select first source          
+               if ( !this.selected_source )
+               {
+                       js_log( 'set via first source:' + playable_sources[0] );
+                       this.selected_source = playable_sources[0];
+                       return true;
+               }
+       },
+       /** 
+       * Returns the thumbnail URL for the media element.
+       * @returns {String} thumbnail URL
+       */
+       getThumbnailURL:function()
+       {
+               return this.thumbnail;
+       },
+       /** 
+       * Checks whether there is a stream of a specified MIME type.
+       * @param {String} mime_type MIME type to check.
+       * @return {Boolean} true if sources include MIME false if not.
+       */
+       hasStreamOfMIMEType:function( mime_type )
+       {
+               for ( source in this.sources )
+               {
+                       if ( this.sources[source].getMIMEType() == mime_type )
+                               return true;
+               }
+               return false;
+       },
+       isPlayableType:function( mime_type )
+       {
+               if ( embedTypes.players.defaultPlayer( mime_type ) ) {
+                       return true;
+               } else {
+                       return false;
+               }
+       },
+       /** 
+       * Adds a single mediaSource using the provided element if
+       *       the element has a 'src' attribute.              
+       *       @param {Element} element <video>, <source> or <mediaSource> <text> element.
+       */
+       tryAddSource:function( element )
+       {
+               js_log( 'f:tryAddSource:' + $j( element ).attr( "src" ) );
+               if ( $j( element ).attr( "src" ) ) {
+                       var new_src = $j( element ).attr( 'src' );
+                       // make sure an existing element with the same src does not already exist:               
+                       for ( var i = 0; i < this.sources.length; i++ ) {
+                               if ( this.sources[i].src == new_src ) {
+                                       // js_log('checking existing: '+this.sources[i].getURI() + ' != '+ new_src);     
+                                       // can't add it all but try to update any additional attr: 
+                                       this.sources[i].updateSource( element );
+                               }
+                       }
+               }
+               var source = new mediaSource( element );
+               // Inherit some properties from the parent <video> element if unset: 
+               if ( !source.duration && this.duration )
+                       source.duration = this.duration;
+                       
+               if ( !source.startOffset && this.startOffset )
+                       source.startOffset = this.startOffset;
+               
+                               
+               this.sources.push( source );
+               js_log( 'pushed source to stack' + source + 'sl:' + this.sources.length );
+       },
+       getPlayableSources: function() {
+                var playable_sources = new Array();
+                for ( var i = 0; i < this.sources.length; i++ ) {
+                        if ( this.isPlayableType( this.sources[i].mime_type ) ) {
+                                playable_sources.push( this.sources[i] );
+                        } else {
+                                js_log( "type " + this.sources[i].mime_type + 'is not playable' );
+                        }
+                };
+                return playable_sources;
+       },
+       /* Imports media sources from ROE data.
+        *   @param roe_data ROE data.
+       */
+       addROE:function( roe_data ) {
+               js_log( 'f:addROE' );
+               this.addedROEData = true;
+               var _this = this;
+               if ( typeof roe_data == 'string' )
+               {
+                       var parser = new DOMParser();
+                       js_log( 'ROE data:' + roe_data );
+                       roe_data = parser.parseFromString( roe_data, "text/xml" );
+               }
+               if ( roe_data ) {
+                       $j.each( roe_data.getElementsByTagName( 'mediaSource' ), function( inx, source ) {
+                               _this.tryAddSource( source );
+                       } );
+                       // set the thumbnail:
+                       $j.each( roe_data.getElementsByTagName( 'img' ), function( inx, n ) {
+                               if ( $j( n ).attr( "id" ) == "stream_thumb" ) {
+                                       js_log( 'roe:set thumb to ' + $j( n ).attr( "src" ) );
+                                       _this['thumbnail'] = $j( n ).attr( "src" );
+                               }
+                       } );
+                       // set the linkback:
+                       $j.each( roe_data.getElementsByTagName( 'link' ), function( inx, n ) {
+                               if ( $j( n ).attr( 'id' ) == 'html_linkback' ) {
+                                       js_log( 'roe:set linkback to ' + $j( n ).attr( "href" ) );
+                                       _this['linkback'] = $j( n ).attr( 'href' );
+                               }
+                       } );
+               } else {
+                       js_log( 'ROE data empty.' );
+               }
+       }
+};
+
+
+/** base embedVideo object
+       @param element <video> tag used for initialization.
+       @constructor
+*/
+var embedVideo = function( element ) {
+       return this.init( element );
+};
+
+embedVideo.prototype = {
+       /** The mediaElement object containing all mediaSource objects */
+       media_element:null,
+       preview_mode:false,
+       ready_to_play:false, // should use html5 ready state
+       load_error:false, // used to set error in case of error
+       loading_external_data:false,
+       thumbnail_updating:false,
+       thumbnail_disp:true,
+       init_with_sources_loadedDone:false,
+       inDOM:false,
+       // for onClip done stuff: 
+       anno_data_cache:null,
+       seek_time_sec:0,
+       base_seeker_slider_offset:null,
+       onClipDone_disp:false,
+       supports: { },
+       // for seek thumb updates:
+       cur_thumb_seek_time:0,
+       thumb_seek_interval:null,
+       // set the default tag type to video:   
+       seeking:false,
+       // set the buffered percent:    
+       bufferedPercent:0,
+       // utility functions for property values:
+       hx : function ( s ) {
+               if ( typeof s != 'String' ) {
+                       s = s.toString();
+               }
+               return s.replace( /&/g, '&amp;' )
+                       . replace( /</g, '&lt;' )
+                       . replace( />/g, '&gt;' );
+       },
+       hq : function ( s ) {
+               return '"' + this.hx( s ) + '"';
+       },
+       playerPixelWidth : function()
+       {
+               var player = $j( '#mv_embedded_player_' + this.id ).get( 0 );
+               if ( typeof player != 'undefined' && player['offsetWidth'] )
+                       return player.offsetWidth;
+               else
+                       return parseInt( this.width );
+       },
+       playerPixelHeight : function()
+       {
+               var player = $j( '#mv_embedded_player_' + this.id ).get( 0 );
+               if ( typeof player != 'undefined' && player['offsetHeight'] )
+                       return player.offsetHeight;
+               else
+                       return parseInt( this.height );
+       },
+       init: function( element ) {
+               // Inherit all the default video_attributes             
+               for ( var attr in default_video_attributes ) { // for in loop oky on user object
+                       if ( element.getAttribute( attr ) ) {
+                               this[ attr ] = element.getAttribute( attr );
+                       } else {
+                               this[attr] = default_video_attributes[attr];
+                       }
+               }
+               
+               // Set the skin name from the class  
+               var     sn = $j(element).attr( 'class' );
+               if ( sn && sn != '' ) {
+                       for ( var n = 0; n < mw.valid_skins.length; n++ ) {
+                               if ( sn.indexOf( mw.valid_skins[n] ) !== -1 ) {
+                                       this.skin_name = mw.valid_skins[ n ];
+                               }
+                       }
+               }
+               // Set the default if unset: 
+               if ( !this.skin_name )
+                       this.skin_name = mw.conf.skin_name;
+               
+               // Make sure startOffset is cast as an int                 
+               if ( this.startOffset && this.startOffset.split( ':' ).length >= 2 )
+                       this.startOffset = npt2seconds( this.startOffset );
+               // Make sure offset is in float: 
+               this.startOffset = parseFloat( this.startOffset );
+                
+               if ( this.duration && this.duration.split( ':' ).length >= 2 )
+                       this.duration = npt2seconds( this.duration );
+               // Make sure duration is in float:  
+               this.duration = parseFloat( this.duration );
+               js_log( "duration is: " +  this.duration );
+               
+                                               
+               this.setDimSize( element, 'width' );
+               this.setDimSize( element, 'height' );                                                           
+               
+               // Set the plugin id
+               this.pid = 'pid_' + this.id;
+
+               // Grab any innerHTML and set it to missing_plugin_html
+               // @@todo we should strip source tags instead of checking and skipping
+               if ( element.innerHTML != '' && element.getElementsByTagName( 'source' ).length == 0 ) {
+                       js_log( 'innerHTML: ' + element.innerHTML );
+                       this.user_missing_plugin_html = element.innerHTML;
+               }
+               // Load all of the specified sources
+               this.media_element = new mediaElement( element );
+               
+               // If we are displaying controls setup the ctrlBuilder  
+               if ( this.controls ) {
+                       // set-up the local ctrlBuilder instance: 
+                       this.ctrlBuilder = new ctrlBuilder( this );
+                       // load the css for the current player
+
+               }
+               // Load skin:
+               loadExternalCss(  mv_embed_path +  'skins/' + this.skin_name + '/playerSkin.css' );
+       },
+       // Function for set width height from attributes or by default value
+       setDimSize:function( element, dim ){                            
+               var dcss = parseInt( $j(element).css( dim ).replace( 'px' , '' ) );
+               var dattr = parseInt( $j(element).attr( dim ) );
+               this[ dim ] = ( dcss )? dcss : dattr;           
+               if( !this[ dim ] ){
+                       //special height default for audio tag:  
+                       if( element.tagName.toLowerCase() == 'audio' &&  dim == 'height' )
+                               return this[ dim ] = 0;
+                       // Grab width/height from default value (for video) 
+                       var dwh = mw.conf['video_size'].split( 'x' );
+                       this[ dim ] = ( dim == 'width' )? dwh[0] : dwh[1];
+                }
+       },
+       on_dom_swap: function() {
+               js_log( 'f:on_dom_swap' );
+               // Process the provided ROE file... if we don't yet have sources
+               if ( this.roe && this.media_element.sources.length == 0 ) {
+                       js_log( 'loading external data' );
+                       this.loading_external_data = true;
+                       var _this = this;                                               
+                       do_request( this.roe, function( data ){                         
+                               // Continue                                        
+                               _this.media_element.addROE( data );
+                               js_log( 'added_roe::' + _this.media_element.sources.length );
+                                                                                                          
+                               js_log( 'set loading_external_data=false' );
+                               _this.loading_external_data = false;
+                               
+                               _this.init_with_sources_loaded();
+                       } );
+               }
+       },
+       init_with_sources_loaded : function()
+       {
+               js_log( 'f:init_with_sources_loaded' );
+               // Set flag that we have run this function:
+               this.init_with_sources_loadedDone = true;
+               // Autoseletct the source
+               this.media_element.autoSelectSource();
+               // Auto select player based on default order
+               if ( !this.media_element.selected_source )
+               {
+                       // check for parent clip: 
+                       if ( typeof this.pc != 'undefined' ) {
+                               js_log( 'no sources, type:' + this.type + ' check for html' );
+                               // debugger;                    
+                               // do load player if just displaying innerHTML: 
+                               if ( this.pc.type == 'text/html' ) {
+                                       this.selected_player = embedTypes.players.defaultPlayer( 'text/html' );
+                                       js_log( 'set selected player:' + this.selected_player.mime_type );
+                               }
+                       }
+               } else {
+                       this.selected_player = embedTypes.players.defaultPlayer( this.media_element.selected_source.mime_type );
+               }
+               if ( this.selected_player ) {
+                       js_log( "Playback type: " + this.selected_player.library );
+                       this.thumbnail_disp = true;
+                       this.inheritEmbedObj();
+               } else {
+                       // No source's playable
+                       var missing_type = '';
+                       var or = '';
+                       for ( var i = 0; i < this.media_element.sources.length; i++ ) {
+                               missing_type += or + this.media_element.sources[i].mime_type;
+                               or = ' or ';
+                       }
+                       // Get from parent playlist if set:             
+                       if ( this.pc )
+                               var missing_type = this.pc.type;
+                                                                                                               
+                       js_log( 'No player found for given source type ' + missing_type );
+                       this.load_error = this.getPluginMissingHTML( missing_type );
+               }
+       },
+       inheritEmbedObj:function() {
+               js_log( "inheritEmbedObj:duration is: " +  this.getDuration() );
+               // @@note: tricky cuz direct overwrite is not so ideal.. since the extended object is already tied to the dom
+               // clear out any non-base embedObj stuff:
+               if ( this.instanceOf ) {
+                       eval( 'tmpObj = ' + this.instanceOf );
+                       for ( var i in tmpObj ) { // for in loop oky for object  
+                               if ( this['parent_' + i] ) {
+                                       this[i] = this['parent_' + i];
+                               } else {
+                                       this[i] = null;
+                               }
+                       }
+               }
+               // set up the new embedObj
+               js_log( 'f: inheritEmbedObj: embedding with ' + this.selected_player.library );
+               var _this = this;
+               this.selected_player.load( function() {
+                       // js_log('inheriting '+_this.selected_player.library +'Embed to ' + _this.id + ' ' + $j('#'+_this.id).length);
+                       eval( 'embedObj = ' + _this.selected_player.library + 'Embed;' );
+                       for ( var method in embedObj ) { // for in loop oky for object  
+                               // parent method preservation for local overwritten methods
+                               if ( _this[method] )
+                                       _this['parent_' + method] = _this[method];
+                               _this[method] = embedObj[method];
+                       }
+                       if ( _this.inheritEmbedOverride ) {
+                               _this.inheritEmbedOverride();
+                       }
+                       // Update controls if possible
+                       if ( !_this.loading_external_data )
+                               _this.refreshControlsHTML();
+                                       
+                       _this.ready_to_play = true;
+                       _this.getDuration();
+                       _this.getHTML();
+               } );
+       },
+       selectPlayer:function( player )
+       {
+               var _this = this;
+               if ( this.selected_player.id != player.id ) {
+                       this.selected_player = player;
+                       this.inheritEmbedObj();
+               }
+       },
+       doNativeWarningCheck:function() {
+               if ( $j.cookie( 'dismissNativeWarn' ) && $j.cookie( 'dismissNativeWarn' ) === true ) {
+                       return false;
+               }
+               
+               // See if we have native support for ogg: 
+               var supporting_players = embedTypes.players.getMIMETypePlayers( 'video/ogg' );
+               for ( var i = 0; i < supporting_players.length; i++ ) {
+                       if ( supporting_players[i].id == 'videoElement' ) {
+                               return false;
+                       }
+               }
+               // See if we are using mv_embed without a ogg source in which case no point in promoting firefox :P                     
+               if ( this.media_element && this.media_element.sources ) {
+                       var foundOgg = false;
+                       var playable_sources = this.media_element.getPlayableSources();
+                       for ( var sInx = 0; sInx < playable_sources.length; sInx++ ) {
+                               var mime_type = playable_sources[sInx].mime_type;
+                               if ( mime_type == 'video/ogg' ) {
+                                       foundOgg = true;
+                               }
+                       }
+                       // no ogg src... no point in download firefox link
+                       if ( !foundOgg )
+                               return false;
+                                                                       
+               }
+               return true;
+       },
+       getTimeReq:function() {
+               var et = ( this.ctrlBuilder.long_time_disp ) ? '/' + seconds2npt( this.getDuration() ) : '';
+               var default_time_req = '0:00:00' + et;
+               if ( !this.media_element )
+                       return default_time_req;
+               if ( !this.media_element.selected_source )
+                       return default_time_req;
+               if ( !this.media_element.selected_source.end_ntp )
+                       return default_time_req;
+               var et = ( this.ctrlBuilder.long_time_disp ) ? '/' + this.media_element.selected_source.end_ntp : '';
+               return this.media_element.selected_source.start_ntp + et;
+       },
+       getDuration:function() {
+               // Update some local pointers for the selected source:  
+               if ( this.media_element && this.media_element.selected_source && this.media_element.selected_source.duration ) {
+                       this.duration = this.media_element.selected_source.duration;
+                       this.start_offset = this.media_element.selected_source.start_offset;
+                       this.start_ntp = this.media_element.selected_source.start_ntp;
+                       this.end_ntp = this.media_element.selected_source.end_ntp;
+               }
+               // Update start end_ntp if duration !=0 (set from plugin) 
+               if ( !this.start_ntp )
+                       this.start_ntp = '0:0:0';
+               if ( !this.end_ntp && this.duration )
+                       this.end_ntp = seconds2npt( this.duration );
+               // Return the duration
+               return this.duration;
+       },
+       /*
+        * wrapEmebedContainer
+        * wraps the embed code into a container to better support playlist function
+        *  (where embed element is swapped for next clip
+        *  (where plugin method does not support playlist) 
+        */
+       wrapEmebedContainer:function( embed_code ) {
+               // Check if parent clip is set( ie we are in a playlist so name the embed container by playlistID)
+               var id = ( this.pc != null ) ? this.pc.pp.id:this.id;
+               return '<div id="mv_ebct_' + id + '" style="width:' + this.width + 'px;height:' + this.height + 'px;">' +
+                                       embed_code +
+                               '</div>';
+       },
+       getEmbedHTML : function() {
+               // Return this.wrapEmebedContainer( this.getEmbedObj() );
+               return 'Error: function getEmbedHTML should be overwritten by embedLib ';
+       },
+       // Do seek function (should be overwritten by implementing embedLibs)
+       // to check if seek can be done on locally downloaded content. 
+       doSeek : function( perc ) {
+               var _this = this;
+               if ( this.supportsURLTimeEncoding() ) {
+                       // make sure this.seek_time_sec is up-to-date:
+                       this.seek_time_sec = npt2seconds( this.start_ntp ) + parseFloat( perc * this.getDuration() );
+                       js_log( 'updated seek_time_sec: ' + seconds2npt ( this.seek_time_sec ) );
+                       this.stop();
+                       this.didSeekJump = true;
+                       // update the slider
+                       this.setSliderValue( perc );
+               }
+               // do play in 100ms (give things time to clear) 
+               setTimeout( function(){
+                       _this.play()
+               }, 100 );
+       },
+       /*
+        * seeks to the requested time and issues a callback when ready 
+        * (should be overwritten by client that supports frame serving)
+        */
+       setCurrentTime:function( time, callback ) {
+               js_log( 'Error: base embed setCurrentTime can not frame serve (override via plugin)' );
+       },
+       addPresTimeOffset:function() {
+          // add in the offset:                
+          if ( this.seek_time_sec && this.seek_time_sec != 0 ) {
+                       this.currentTime += this.seek_time_sec;
+          } else if ( this.start_offset && this.start_offset != 0 ) {
+                  this.currentTime = parseFloat( this.currentTime ) + parseFloat( this.start_offset );
+          }
+       },
+       doEmbedHTML:function() {
+               js_log( 'f:doEmbedHTML' );
+               js_log( 'thum disp:' + this.thumbnail_disp );
+               var _this = this;
+               this.closeDisplayedHTML();
+               
+               // Set "loading" here
+               $j( '#mv_embedded_player_' + _this.id ).html( '' +
+                       '<div style="color:black;width:' + this.width + 'px;height:' + this.height + 'px;">' +
+                               gM( 'mwe-loading_plugin' ) +
+                       '</div>'
+               );
+               // Schedule embedding after player library is loaded:
+               this.selected_player.load( function() {
+                       js_log( 'performing embed for ' + _this.id );
+                       var embed_code = _this.getEmbedHTML();
+                       // js_log('shopuld embed:' + embed_code);
+                       $j( '#mv_embedded_player_' + _this.id ).html( embed_code );
+               } );
+       },
+       relatedTitleKeySearch:function() {
+               var _this = this;
+               var reqObj = {
+                       'action' : 'query',
+                       //normalize the File NS (ie sometimes its present in wikiTitleKey other times not
+                       'titles' : 'File:' + this.wikiTitleKey.replace(/File:|Image:/,''),
+                   'generator' : 'categories'
+               };
+               var req_categories = new Array();
+           do_api_req( {
+               'url'   : mw.commons_api_url,
+                       'data'  : reqObj                        
+           },  function( data ) {
+                       req_categories = Array();
+                       if ( data.query && data.query.pages ) {
+                               for ( var pageid in  data.query.pages ) {
+                                       if ( data.query.pages[pageid].title )
+                                               req_categories.push( data.query.pages[pageid].title );
+                               }
+                               _this.getRelatedFromCat( req_categories );
+                       } else {
+                               _this.doThumbnailHTML();
+                       }
+               } );
+       },
+       getRelatedFromCat:function( catAry ) {
+               js_log( 'getRelatedFromCat' );
+               var _this = this;
+               for ( var i = 0 ; i <= catAry.length ; i++ ) {
+                       if ( !catAry[i] )
+                               continue;
+                       var reqObj = {
+                               'action'        : 'query',
+                               'generator'     : 'categorymembers'  ,
+                               'gcmtitle'      : catAry[i],
+                               'prop'          : 'imageinfo',
+                               'iiprop'        : 'url',
+                               'iiurlwidth': '80'
+                       };
+                       do_api_req( {
+                               'data':reqObj,
+                               'url': mw.commons_api_url
+                       },  function( data ) {
+                   // empty the videos:                            
+                   $j( '#dc_' + _this.id + ' .related_vids ul' ).html( ' ' );
+                                                          
+                               for ( var j in data.query.pages ) {
+                                       // Setup poster default:                                        
+                                       var local_poster = "http://upload.wikimedia.org/wikipedia/commons/7/79/Wiki-commons.png";
+                                       // Make sure it exists: 
+                                       var page = data.query.pages[j];
+                                       if ( j > 0 && page && page['imageinfo'] ) {
+                                               if (    page['imageinfo'][0].thumburl ) {
+                                                       local_poster = page['imageinfo'][0].thumburl;
+                                               }
+                                               var descriptionurl = page['imageinfo'][0].descriptionurl;
+                                               var title_str = page.title.replace( /File:|.ogv$|.oga$|.ogg$/gi, "" );
+                                               // only link to other videos:                                                           
+                                               if ( descriptionurl.match( /\.ogg$|\.ogv$|\.oga$/gi ) != null) {
+                                                       var liout = '<li>' +
+                                                               '<a href="' + descriptionurl + '" >' +
+                                                                       '<img src="' + local_poster + '">' +
+                                                               '</a>' +
+                                                                       ' <a title="' + title_str + '" target="_blank" ' +
+                                                                               'href="' + descriptionurl + '">' + title_str + '</a>' +
+                                                       '</li>';
+                                                       $j( '#dc_' + _this.id + ' .related_vids ul' ).append( liout ) ;
+                                               }
+                                        }
+                               };
+                       } ); // end do_api_req
+               };
+       },
+       onClipDone:function() {
+               js_log( 'base:onClipDone' );
+               // stop the clip (load the thumbnail etc) 
+               this.stop();
+               this.seek_time_sec = 0;
+               this.setSliderValue( 0 );
+               var _this = this;
+               
+               if ( this.width < 300 ) {
+                       return ;
+               }
+               this.onClipDone_disp = true;
+               this.thumbnail_disp = true;
+               
+               // make sure we are not in preview mode( no end clip actions in preview mode) 
+               if ( this.preview_mode )
+                       return ;
+                       
+               $j( '#img_thumb_' + this.id ).css( 'zindex', 1 );
+               $j( '#' + this.id + ' .play-btn-large' ).hide();
+
+               // add black background
+               $j( '#dc_' + this.id ).append( '<div id="black_back_' + this.id + '" ' +
+                                       'style="z-index:-2;position:absolute;background:#000;' +
+                                       'top:0px;left:0px;width:' + parseInt( this.width ) + 'px;' +
+                                       'height:' + parseInt( this.height ) + 'px;">' +
+                               '</div>' );
+
+               if ( this.wikiTitleKey ) {
+                       $j( '#dc_' + this.id ).append(
+                       '<div class="related_vids" >' +
+                          '<h1>' + gM( 'mwe-related_videos' ) + '</h1>' +
+                               '<ul>' +
+                               '</ul>' +
+                       '</div>' );
+                       $j( '#img_thumb_' + this.id ).fadeOut( "fast" );
+                       $j( '#dc_' + _this.id + ' .related_vids ul' ).html( gM( 'mwe-loading_txt' ) );
+                       this.relatedTitleKeySearch();
+               } else {
+                       this.onClipDoneDisp();
+               }
+       },
+       onClipDoneDisp:function() {
+               var _this = this;
+               // add the liks_info_div black back 
+               $j( '#dc_' + this.id ).append( '<div id="liks_info_' + this.id + '" ' +
+                               'style="width:' + parseInt( parseInt( this.width ) / 2 ) + 'px;' +
+                               'height:' + parseInt( parseInt( this.height ) ) + 'px;' +
+                               'position:absolute;top:10px;overflow:auto' +
+                               'width: ' + parseInt( ( ( parseInt( this.width ) / 2 ) -15 ) ) + 'px;' +
+                               'left:' + parseInt( ( ( parseInt( this.width ) / 2 ) + 15 ) ) + 'px;">' +
+                       '</div>'
+          );
+          // start animation (make thumb small in upper left add in div for "loading"                  
+               $j( '#img_thumb_' + this.id ).animate( {
+                               width : parseInt( parseInt( _this.width ) / 2 ),
+                               height : parseInt( parseInt( _this.height ) / 2 ),
+                               top:20,
+                               left:10
+                       },
+                       1000,
+                       function() {
+                               // animation done.. add "loading" to div if empty               
+                               if ( $j( '#liks_info_' + _this.id ).html() == '' ) {
+                                       $j( '#liks_info_' + _this.id ).html( gM( 'mwe-loading_txt' ) );
+                               }
+                       }
+               )
+               // now load roe if run the showNextPrevLinks
+               if ( this.roe && this.media_element.addedROEData == false ) {
+                       do_request( this.roe, function( data )
+                       {
+                               _this.media_element.addROE( data );
+                               _this.getNextPrevLinks();
+                       } );
+               } else {
+                       this.getNextPrevLinks();
+               }
+       },
+       // @@todo we should merge getNextPrevLinks with textInterface .. there is repeated code between them. 
+       getNextPrevLinks:function() {
+               js_log( 'f:getNextPrevLinks' );
+               var anno_track_url = null;
+               var _this = this;
+               // check for annoative track
+               $j.each( this.media_element.sources, function( inx, n ) {
+                       if ( n.mime_type == 'text/cmml' ) {
+                               if ( n.id == 'Anno_en' ) {
+                                       anno_track_url = n.src;
+                               }
+                       }
+               } );
+               
+               if ( !anno_track_url ) {
+                       js_log( 'no annotative track url found' );
+                       // $j('#liks_info_'+this.id).html('no metadata found for related links');
+                       _this.doThumbnailHTML();
+                       return ;
+               }
+               
+               js_log( 'we have annotative track:' + anno_track_url );
+               // Zero out seconds (should improve cache hit rate and generally expands metadata search)
+               // @@todo this could be replaced with a regExp
+               var annoURL = mw.parseUri( anno_track_url );
+               var times = annoURL.queryKey['t'].split( '/' );
+               var stime_parts = times[0].split( ':' );
+               var etime_parts = times[1].split( ':' );
+               // zero out the hour:
+               var new_start = stime_parts[0] + ':' + '0:0';
+               // zero out the end sec
+               var new_end   = ( etime_parts[0] == stime_parts[0] ) ? ( etime_parts[0] + 1 ) + ':0:0' :etime_parts[0] + ':0:0';
+                                
+               var etime_parts = times[1].split( ':' );
+               
+               var new_anno_track_url = annoURL.protocol + '://' + annoURL.host + annoURL.path + '?';
+               $j.each( annoURL.queryKey, function( i, val ) {
+                       new_anno_track_url += ( i == 't' ) ? 't=' + new_start + '/' + new_end + '&' :
+                                                                        i + '=' + val + '&';
+               } );
+               var request_key = new_start + '/' + new_end;
+               // check the anno_data cache: 
+               // @@todo search cache see if current is in range.  
+               if ( this.anno_data_cache ) {
+                       js_log( 'anno data found in cache: ' + request_key );
+                       this.showNextPrevLinks();
+               } else {
+                       do_request( new_anno_track_url, function( cmml_data ) {
+                               js_log( 'raw response: ' + cmml_data );
+                               if ( typeof cmml_data == 'string' ) {
+                                       var parser = new DOMParser();
+                                       js_log( 'Parse CMML data:' + cmml_data );
+                                       cmml_data = parser.parseFromString( cmml_data, "text/xml" );
+                               }
+                               // init anno_data_cache
+                               if ( !_this.anno_data_cache )
+                                       _this.anno_data_cache = { };
+                               // grab all metadata and put it into the anno_data_cache:                                        
+                               $j.each( cmml_data.getElementsByTagName( 'clip' ), function( inx, clip ) {
+                                       _this.anno_data_cache[ $j( clip ).attr( "id" ) ] = {
+                                                       'start_time_sec':npt2seconds( $j( clip ).attr( "start" ).replace( 'npt:', '' ) ),
+                                                       'end_time_sec':npt2seconds( $j( clip ).attr( "end" ).replace( 'npt:', '' ) ),
+                                                       'time_req':$j( clip ).attr( "start" ).replace( 'npt:', '' ) + '/' + $j( clip ).attr( "end" ).replace( 'npt:', '' )
+                                               };
+                                       // grab all its meta
+                                       _this.anno_data_cache[ $j( clip ).attr( "id" ) ]['meta'] = { };
+                                       $j.each( clip.getElementsByTagName( 'meta' ), function( imx, meta ) {
+                                               // js_log('adding meta: '+ $j(meta).attr("name")+ ' = '+ $j(meta).attr("content"));
+                                               _this.anno_data_cache[$j( clip ).attr( "id" )]['meta'][$j( meta ).attr( "name" )] = $j( meta ).attr( "content" );
+                                       } );
+                               } );
+                               _this.showNextPrevLinks();
+                       } );
+               }
+               // query current request time +|- 60s to get prev next speech links. 
+       },
+       showNextPrevLinks:function() {
+               // js_log('f:showNextPrevLinks');
+               // int requested links: 
+               var link = {
+                       'prev':'',
+                       'current':'',
+                       'next':''
+               }
+               var curTime = this.getTimeReq().split( '/' );
+               
+               var s_sec = npt2seconds( curTime[0] );
+               var e_sec = npt2seconds( curTime[1] );
+               js_log( 'showNextPrevLinks: req time: ' + s_sec + ' to ' + e_sec );
+               // now we have all the data in anno_data_cache
+               var current_done = false;
+               for ( var clip_id in this.anno_data_cache ) {  // for in loop oky for object
+                        var clip =  this.anno_data_cache[clip_id];
+                        // js_log('on clip:'+ clip_id);
+                        // set prev_link (if cur_link is still empty)
+                       if ( s_sec > clip.end_time_sec ) {
+                               link.prev = clip_id;
+                               js_log( 'showNextPrevLinks: ' + s_sec + ' < ' + clip.end_time_sec + ' set prev' );
+                       }
+                               
+                       if ( e_sec == clip.end_time_sec && s_sec == clip.start_time_sec )
+                               current_done = true;
+                       // current clip is not done:
+                       if (  e_sec < clip.end_time_sec  && link.current == '' && !current_done ) {
+                               link.current = clip_id;
+                               js_log( 'showNextPrevLinks: ' + e_sec + ' < ' + clip.end_time_sec + ' set current' );
+                       }
+                       
+                       // set end clip (first clip where start time is > end_time of req
+                       if ( e_sec <  clip.start_time_sec && link.next == '' ) {
+                               link.next = clip_id;
+                               js_log( 'showNextPrevLinks: ' +  e_sec + ' < ' + clip.start_time_sec + ' && ' + link.next );
+                       }
+               }
+               var html = '';
+               if ( link.prev == '' && link.current == '' && link.next == '' ) {
+                       html = '<p><a href="' + this.media_element.linkbackgetMsg + '">clip page</a>';
+               } else {
+                       for ( var link_type in link ) {
+                               var link_id = link[link_type];
+                               if ( link_id != '' ) {
+                                       var clip = this.anno_data_cache[link_id];
+                                       var title_msg = '';
+                                       for ( var j in clip['meta'] ) {
+                                               title_msg += j.replace( /_/g, ' ' ) + ': ' + clip['meta'][j].replace( /_/g, ' ' ) + " <br>";
+                                       }
+                                       var time_req =   clip.time_req;
+                                       if ( link_type == 'current' ) // if current start from end of current clip play to end of current meta:                          
+                                               time_req = curTime[1] + '/' + seconds2npt( clip.end_time_sec );
+                                       
+                                       // do special linkbacks for metavid content: 
+                                       var regTimeCheck = new RegExp( /[0-9]+:[0-9]+:[0-9]+\/[0-9]+:[0-9]+:[0-9]+/ );
+                                       html += '<p><a  ';
+                                       if ( regTimeCheck.test( this.media_element.linkback ) ) {
+                                               html += ' href="' + this.media_element.linkback.replace( regTimeCheck, time_req ) + '" ';
+                                       } else {
+                                               html += ' href="#" onClick="$j(\'#' + this.id + '\').get(0).playByTimeReq(\'' +
+                                                               time_req + '\'); return false; "';
+                                       }
+                                       html += ' title="' + title_msg + '">' +
+                                                gM( 'mwe-' + link_type + '_clip_msg' ) +
+                                       '</a><br><span style="font-size:small">' + title_msg + '<span></p>';
+                               }
+                       }
+               }
+               // js_og("should set html:"+ html);
+               $j( '#liks_info_' + this.id ).html( html );
+       },
+       playByTimeReq: function( time_req ) {
+               js_log( 'f:playByTimeReq: ' + time_req );
+               this.stop();
+               this.updateVideoTimeReq( time_req );
+               this.play();
+       },
+       doThumbnailHTML:function() {
+               var _this = this;
+               js_log( 'f:doThumbnailHTML' + this.thumbnail_disp );
+               this.closeDisplayedHTML();
+               $j( '#mv_embedded_player_' + this.id ).html( this.getThumbnailHTML() );
+               this.paused = true;
+               this.thumbnail_disp = true;
+               // make sure the ctrlBuilder remain active: 
+               this.ctrlBuilder.addControlHooks();
+       },
+       refreshControlsHTML:function() {
+               if ( $j( '#' + this.id + ' .control-bar' ).length == 0 ) {
+                       js_log( 'refreshControlsHTML::control-bar not present, no refresh' );
+                       return ;
+               }
+               // Do update controls: 
+               $j( '#' + this.id + ' .control-bar' ).html( this.getControlsHTML() );
+               this.ctrlBuilder.addControlHooks();
+                               
+       },
+       getControlsHTML:function() {
+               return this.ctrlBuilder.getControls( this );
+       },
+       getHTML : function () {
+               // @@todo check if we have sources available    
+               js_log( 'embedVideo:getHTML : ' + this.id  + ' resource type: ' + this.type );
+               
+               // set-up the local ctrlBuilder instance: 
+               this.ctrlBuilder = new ctrlBuilder( this );
+                                               
+               var _this = this;
+               var html_code = '';
+               html_code = '<div id="videoPlayer_' + this.id + '" style="width:' + this.width + 'px;position:relative;"' +
+                                               'class="' + this.ctrlBuilder.pClass + '">';
+               html_code += '<div style="width:' + parseInt( this.width ) + 'px;height:' + parseInt( this.height ) + 'px;"  id="mv_embedded_player_' + this.id + '">' +
+                                               this.getThumbnailHTML() +
+                                       '</div>';
+               
+               // js_log("mvEmbed:controls "+ typeof this.controls);                                                                   
+               if ( this.controls ) {
+                       js_log( "f:getHTML:AddControls" );
+                       html_code += '<div class="ui-state-default ui-widget-header ui-helper-clearfix control-bar" >';
+                       html_code += this.getControlsHTML();
+                       html_code += '</div>';
+                       // block out some space by encapulating the top level div 
+                       $j( this ).wrap( '<div style="width:' + parseInt( this.width ) + 'px;height:'
+                                       + ( parseInt( this.height ) + this.ctrlBuilder.height ) + 'px"></div>' );
+               }
+               
+               html_code += '</div>'; // videoPlayer div close         
+
+               // js_log('should set: '+this.id);
+               $j( this ).html( html_code );
+               
+               // Add hooks once Controls are in DOM
+               this.ctrlBuilder.addControlHooks();
+                                                 
+               
+               if ( this.autoplay ) {
+                       js_log( 'getHTML::activating autoplay' );
+                       this.play();
+               }
+       },
+       /**
+       * get missing plugin html (check for user included code)
+       * @param {String} misssing_type missing type mime
+       */
+       getPluginMissingHTML : function( missing_type ) {
+               // keep the box width hight:
+               var out = '<div style="width:' + this.width + 'px;height:' + this.height + 'px">';
+               if ( this.user_missing_plugin_html ) {
+                 out += this.user_missing_plugin_html;
+               } else {
+                 if ( !missing_type )
+                       missing_type = '';
+                 out += gM( 'mwe-generic_missing_plugin', missing_type ) + '<br><a title="' + gM( 'mwe-download_clip' ) + '" href="' + this.src + '">' + gM( 'mwe-download_clip' ) + '</a>';
+               }
+               return out + '</div>';
+       },
+       updateVideoTimeReq:function( time_req ) {
+               js_log( 'f:updateVideoTimeReq' );
+               var time_parts = time_req.split( '/' );
+               this.updateVideoTime( time_parts[0], time_parts[1] );
+       },
+       // update video time
+       updateVideoTime:function( start_ntp, end_ntp ) {
+               // update media
+               this.media_element.updateSourceTimes( start_ntp, end_ntp );
+               // update mv_time
+               this.setStatus( start_ntp + '/' + end_ntp );
+               // reset slider
+               this.setSliderValue( 0 );
+               // reset seek_offset:
+               if ( this.media_element.selected_source.URLTimeEncoding )
+                       this.seek_time_sec = 0;
+               else
+                       this.seek_time_sec = npt2seconds( start_ntp );
+       },
+       // Should overwrite by embed library if we can render frames natively 
+       renderTimelineThumbnail:function( options ) {
+               var my_thumb_src = this.media_element.getThumbnailURL();
+               // check if our thumbnail has a time attribute: 
+               if ( my_thumb_src.indexOf( 't=' ) !== -1 ) {
+                       var time_ntp =  seconds2npt ( options.time + parseInt( this.start_offset ) );
+                       my_thumb_src = getURLParamReplace( my_thumb_src, { 
+                               't':time_ntp, 
+                               'size': options.size 
+                       });
+               }
+               var thumb_class = ( typeof options['thumb_class'] != 'undefined' ) ? options['thumb_class'] : '';
+               return '<div class="ui-corner-all ' + thumb_class + '" src="' + my_thumb_src + '" ' +
+                               'style="height:' + options.height + 'px;' +
+                               'width:' + options.width + 'px" >' +
+                                        '<img src="' + my_thumb_src + '" ' +
+                                               'style="height:' + options.height + 'px;' +
+                                               'width:' + options.width + 'px">' +
+                               '</div>';
+       },
+       updateThumbTimeNTP:function( time ) {
+               this.updateThumbTime( npt2seconds( time ) - parseInt( this.start_offset ) );
+       },
+       updateThumbTime:function( float_sec ) {
+               // js_log('updateThumbTime:'+float_sec);
+               var _this = this;
+               if ( typeof this.org_thum_src == 'undefined' ) {
+                       this.org_thum_src = this.media_element.getThumbnailURL();
+               }
+               if ( this.org_thum_src.indexOf( 't=' ) !== -1 ) {
+                       this.last_thumb_url = getURLParamReplace( this.org_thum_src,
+                               { 
+                                       't' : seconds2npt( float_sec + parseInt( this.start_offset ) ) 
+                               }
+                       );
+                       if ( !this.thumbnail_updating ) {
+                               this.updateThumbnail( this.last_thumb_url , false );
+                               this.last_thumb_url = null;
+                       }
+               }
+       },
+       updateThumbPerc:function( perc ) {
+               return this.updateThumbTime( ( this.getDuration() * perc ) );
+       },
+       // Updates the thumbnail if the thumbnail is being displayed
+       updateThumbnail : function( src, quick_switch ) {
+               // make sure we don't go to the same url if we are not already updating: 
+               if ( !this.thumbnail_updating && $j( '#img_thumb_' + this.id ).attr( 'src' ) == src )
+                       return false;
+               // if we are already updating don't issue a new update: 
+               if ( this.thumbnail_updating && $j( '#new_img_thumb_' + this.id ).attr( 'src' ) == src )
+                       return false;
+               
+               js_log( 'update thumb: ' + src );
+               
+               if ( quick_switch ) {
+                       $j( '#img_thumb_' + this.id ).attr( 'src', src );
+               } else {
+                       var _this = this;
+                       // if still animating remove new_img_thumb_
+                       if ( this.thumbnail_updating == true )
+                               $j( '#new_img_thumb_' + this.id ).stop().remove();
+                                       
+                       if ( this.thumbnail_disp ) {
+                               js_log( 'set to thumb:' + src );
+                               this.thumbnail_updating = true;
+                               $j( '#dc_' + this.id ).append( '<img src="' + src + '" ' +
+                                       'style="display:none;position:absolute;zindex:2;top:0px;left:0px;" ' +
+                                       'width="' + this.width + '" height="' + this.height + '" ' +
+                                       'id = "new_img_thumb_' + this.id + '" />' );
+                               // js_log('appended: new_img_thumb_');          
+                               $j( '#new_img_thumb_' + this.id ).fadeIn( "slow", function() {
+                                               // once faded in remove org and rename new:
+                                               $j( '#img_thumb_' + _this.id ).remove();
+                                               $j( '#new_img_thumb_' + _this.id ).attr( 'id', 'img_thumb_' + _this.id );
+                                               $j( '#img_thumb_' + _this.id ).css( 'zindex', '1' );
+                                               _this.thumbnail_updating = false;
+                                               // js_log("done fadding in "+ $j('#img_thumb_'+_this.id).attr("src"));
+
+                                               // if we have a thumb queued update to that
+                                               if ( _this.last_thumb_url ) {
+                                                       var src_url = _this.last_thumb_url;
+                                                       _this.last_thumb_url = null;
+                                                       _this.updateThumbnail( src_url );
+                                               }
+                               } );
+                       }
+               }
+       },
+       /** 
+       * Returns the HTML code for the video when it is in thumbnail mode.
+       * This includes the specified thumbnail as well as buttons for
+       * playing, configuring the player, inline cmml display, HTML linkback,
+       * download, and embed code.
+       */
+       getThumbnailHTML : function () {
+               js_log( 'embedVideo:getThumbnailHTML::' + this.id );
+               var thumb_html = '';
+               var class_atr = '';
+               var style_atr = '';
+               // if(this.class)class_atr = ' class="'+this.class+'"';
+               // if(this.style)style_atr = ' style="'+this.style+'"';
+               //      else style_atr = 'overflow:hidden;height:'+this.height+'px;width:'+this.width+'px;';
+               this.thumbnail = this.media_element.getThumbnailURL();
+
+               // put it all in the div container dc_id
+               thumb_html += '<div id="dc_' + this.id + '" style="position:absolute;' +
+                       ' overflow:hidden; top:0px; left:0px; width:' + this.playerPixelWidth() + 'px; height:' + this.playerPixelHeight() + 'px; z-index:0;">' +
+                       '<img width="' + this.playerPixelWidth() + '" height="' + this.playerPixelHeight() + '" style="position:relative;width:' + this.playerPixelWidth() + ';height:' + this.playerPixelHeight() + '"' +
+                       ' id="img_thumb_' + this.id + '" src="' + this.thumbnail + '">';
+               
+               if ( this.play_button == true && this.controls == true )
+                         thumb_html += this.ctrlBuilder.getComponent( 'play-btn-large' );
+                         
+                  thumb_html += '</div>';
+               return thumb_html;
+       },
+       getEmbeddingHTML:function() {
+               var thumbnail = this.media_element.getThumbnailURL();
+
+               var embed_thumb_html;
+               if ( thumbnail.substring( 0, 1 ) == '/' ) {
+                       eURL = mw.parseUri( mv_embed_path );
+                       embed_thumb_url = eURL.protocol + '://' + eURL.host + thumbnail;
+                       // js_log('set from mv_embed_path:'+embed_thumb_html);
+               } else {
+                       embed_thumb_url = ( thumbnail.indexOf( 'http://' ) != -1 ) ? thumbnail:mv_embed_path + thumbnail;
+               }
+               var embed_code_html = '&lt;script type=&quot;text/javascript&quot; ' +
+                                       'src=&quot;' + mv_embed_path + 'mv_embed.js&quot;&gt;&lt;/script&gt' +
+                                       '&lt;video ';
+               if ( this.roe ) {
+                       embed_code_html += 'roe=&quot;' + escape( this.roe ) + '&quot; ';
+               } else {
+                       embed_code_html += 'src=&quot;' + this.src + '&quot; ' +
+                               'poster=&quot;' + escape( embed_thumb_url ) + '&quot; ';
+               }
+               
+               // Add in the wikiTitle key if provided 
+               // (in the future we should just include the titleKey on remote embeds 
+               // and query a roe like xml/json representaiton thing from mediawiki)
+               if ( this.wikiTitleKey ) {
+                       embed_code_html += 'wikiTitleKey=&quot;' + escape( this.wikiTitleKey ) + '&quot;';
+               }
+               
+               // close the video tag
+               embed_code_html += '&gt;&lt;/video&gt;';
+
+               return embed_code_html;
+       },
+       doOptionsHTML:function() {
+               var sel_id = ( this.pc != null ) ? this.pc.pp.id:this.id;
+               var pos = $j( '#' + sel_id + ' .options-btn' ).offset();
+               pos['top'] = pos['top'] + 24;
+               pos['left'] = pos['left'] -124;
+               // js_log('pos of options button: t:'+pos['top']+' l:'+ pos['left']);
+               $j( '#mv_vid_options_' + sel_id ).css( pos ).toggle();
+               return;
+       },
+       doLinkBack:function() {
+               if ( this.roe && this.media_element.addedROEData == false ) {
+                       var _this = this;
+                       this.displayHTML( gM( 'mwe-loading_txt' ) );
+                       do_request( this.roe, function( data ) {
+                               _this.media_element.addROE( data );
+                               _this.doLinkBack();
+                       } );
+               } else {
+                       if ( this.linkback ) {
+                               window.location = this.linkback;
+                       } else if ( this.media_element.linkback ) {
+                               window.location = this.media_element.linkback;
+                       } else {
+                               this.displayHTML( gM( 'mwe-could_not_find_linkback' ) );
+                       }
+               }
+       },
+       showShare:function( $target ) {
+               var     embed_code = this.getEmbeddingHTML();
+               var o = '';
+               var _this = this;
+        // @todo: hook events to two a's for swapping in and out code for link vs. embed;
+        //       hook events for changing active class of li based on a.
+        var o = '';                                    
+               o += '<h2>' + gM( 'mwe-share_this_video' ) + '</h2>' +
+                       '<ul>' +
+                               '<li><a href="#" class="active">' + gM( 'mwe-embed_site_or_blog' ) + '</a></li>';
+                               if ( this.linkback )
+                                       o += '<li><a href="#" id="k-share-link">' + this.linkback + '</a></li>';
+               o +='</ul>' +
+                       '<div class="source_wrap">'+
+                               '<textarea>' + embed_code + '</textarea>'+
+                       '</div>' +
+                       '<button class="ui-state-default ui-corner-all copycode">' + gM( 'mwe-copy-code' ) + '</button>' +
+                       '<div class="ui-state-highlight ui-corner-all">' + 
+                               gM( 'mwe-read_before_embed' ) + 
+                       '</div>';
+               $target.html( o );
+               $cpBtn = $j( '#' + this.id + ' .copycode' );
+               $cpTxt = $j( '#' + this.id + ' .source_wrap textarea' );
+               
+               $cpTxt.click( function() {
+                       $j( this ).get( 0 ).select();
+               } );
+               
+               // add copy binding: 
+               $cpBtn.click( function() {
+                       $cpTxt.focus().get( 0 ).select();
+                       if ( document.selection ) {
+                               CopiedTxt = document.selection.createRange();
+                               CopiedTxt.execCommand( "Copy" );
+                       }
+               } );
+       },
+       showTextInterface:function() {
+               var _this = this;
+               if( $j( '#metaBox_' + this.id ).is( ':visible' ) ) {
+                       $j( '#metaBox_' + this.id ).fadeOut("fast");
+               }else{
+                       $j( '#metaBox_' + this.id ).fadeIn( "fast" );
+               }
+               // display the text container with loading text: 
+               // @@todo support position config
+               var loc = $j( this ).position();
+               if ( $j( '#metaBox_' + this.id ).length == 0 ) {                        
+                       var theight = ( ( parseInt( this.height ) + this.ctrlBuilder.height ) < 200 ) ? 200 : ( parseInt( this.height ) + this.ctrlBuilder.height );
+                       $j( this ).after( '<div class="ui-widget ui-widget-content ui-corner-all" style="position:absolute;z-index:10;' +
+                               'top:' + ( loc.top ) + 'px;' +
+                               'left:' + ( parseInt( loc.left ) + parseInt( this.width ) + 10) + 'px;' +
+                               'height:' + theight + 'px;width:400px;' +
+                               'display:none;" ' +
+                               'id="metaBox_' + this.id + '">' +
+                                       mv_get_loading_img() +
+                               '</div>' );
+               }               
+               // check if textObj present:
+               if ( typeof this.textInterface == 'undefined' ) {
+                       // load the default text interface:
+                       mvJsLoader.doLoad( [
+                                       'mvTextInterface',
+                                       '$j.fn.hoverIntent'
+                               ], function() {
+                                       _this.textInterface = new mvTextInterface( _this );
+                                       // show interface
+                                       _this.textInterface.show();
+                               }
+                       );
+               } else {
+                       // show interface
+                       this.textInterface.show();
+               }
+       },
+       closeTextInterface:function() {
+               js_log( 'closeTextInterface ' + typeof this.textInterface );
+               if ( typeof this.textInterface !== 'undefined' ) {
+                       this.textInterface.close();
+               }
+       },
+       /** 
+       * Generic function to display custom HTML inside the mv_embed element.
+       * The code should call the closeDisplayedHTML function to close the
+       * display of the custom HTML and restore the regular mv_embed display.          
+       * @param {String} html_code code for the selection list.
+       */
+       displayHTML:function( html_code )
+       {
+               var sel_id = ( this.pc != null ) ? this.pc.pp.id:this.id;
+               
+               if ( !this.supports['overlays'] )
+                       this.stop();
+               
+               // put select list on-top
+               // make sure the parent is relatively positioned:
+               $j( '#' + sel_id ).css( 'position', 'relative' );
+               // set height width (check for playlist container)
+               var width = ( this.pc ) ? this.pc.pp.width:this.playerPixelWidth();
+               var height = ( this.pc ) ? this.pc.pp.height:this.playerPixelHeight();
+               
+               if ( this.pc )
+                       height += ( this.pc.pp.pl_layout.title_bar_height + this.pc.pp.pl_layout.control_height );
+         
+               var fade_in = true;
+               if ( $j( '#blackbg_' + sel_id ).length != 0 )
+               {
+                       fade_in = false;
+                       $j( '#blackbg_' + sel_id ).remove();
+               }
+               // fade in a black bg div ontop of everything
+                var div_code = '<div id="blackbg_' + sel_id + '" class="videoComplete" ' +
+                        'style="height:' + parseInt( height ) + 'px;width:' + parseInt( width ) + 'px;">' +
+                               '<span style="float:right;margin-right:10px">' +
+                               '<a href="#" style="color:white;" onClick="$j(\'#' + sel_id + '\').get(0).closeDisplayedHTML();return false;">close</a>' +
+                       '</span>' +
+                         '<div class="videoOptionsComplete">' +                                        
+                          '</div>'+
+                        '</div>';              
+               $j( '#' + sel_id ).prepend( div_code );
+               if ( fade_in )
+                       $j( '#blackbg_' + sel_id ).fadeIn( "slow" );
+               else
+                       $j( '#blackbg_' + sel_id ).show();
+               return false; // onclick action return false
+       },
+       /** 
+       * Close the custom HTML displayed using displayHTML and restores the
+       * regular mv_embed display.
+       */
+       closeDisplayedHTML:function() {
+                 var sel_id = ( this.pc != null ) ? this.pc.pp.id:this.id;
+                $j( '#blackbg_' + sel_id ).fadeOut( "slow", function() {
+                        $j( '#blackbg_' + sel_id ).remove();
+                } );
+                return false; // onclick action return false
+       },
+       showPlayerselect:function( $target ) {  
+               // Get id (in case where we have a parent container)
+               var this_id = ( this.pc != null ) ? this.pc.pp.id:this.id;
+               var _this = this;
+               var o = '';
+               o += '<h2>' + gM( 'mwe-chose_player' ) + '</h2>';
+               var _this = this;
+               $j.each( this.media_element.getPlayableSources(), function( source_id, source ) {
+                       var playable = embedTypes.players.defaultPlayer( source.getMIMEType() );
+
+                       var is_selected = ( source == _this.media_element.selected_source );
+                       var image_src =  mv_skin_img_path ;
+                       
+                       o += '<h2>' + source.getTitle() + '</h2>';
+                       
+                       if ( playable ) {
+                               o += '<ul>';
+                               // output the player select code:
+                               var supporting_players = embedTypes.players.getMIMETypePlayers( source.getMIMEType() );
+
+                               for ( var i = 0; i < supporting_players.length ; i++ ) {
+                                       if ( _this.selected_player.id == supporting_players[i].id && is_selected ) {
+                                               o += '<li>' +
+                                                       '<a href="#" class="active" rel="sel_source" id="sc_' + source_id + '_' + supporting_players[i].id + '">' +
+                                                               supporting_players[i].getName() +
+                                                       '</li>';
+                                       } else {
+                               o += '<li>' +
+                                                       '<a href="#" rel="sel_source" id="sc_' + source_id + '_' + supporting_players[i].id + '">' +
+                                                               supporting_players[i].getName() +
+                                                       '</a>' +
+                                               '</li>';
+                                       }
+                               }
+                               o += '</ul>';
+                       } else {
+                               o += source.getTitle() + ' - no player available';
+                       }
+               } );
+               $target.html( o );
+
+               // Set up the click bindings:
+               $target.find( "[rel='sel_source']" ).each( function() {
+                       $j( this ).click( function() {
+                               var iparts = $j( this ).attr( 'id' ).replace(/sc_/ , '' ).split( '_' );
+                               var source_id = iparts[0];
+                               var default_player_id = iparts[1];
+                               js_log( 'source id: ' +  source_id + ' player id: ' + default_player_id );
+
+                               $j( '#' + this_id  ).get( 0 ).closeDisplayedHTML();
+                               $j( '#' + _this.id ).get( 0 ).media_element.selectSource( source_id );
+
+                               embedTypes.players.userSelectPlayer( default_player_id,
+                                        _this.media_element.sources[ source_id ].getMIMEType() );
+
+                               // Issue a stop
+                               $j( '#' + this_id  ).get( 0 ).stop();
+
+                               // Don't follow the empty # link:
+                               return false;
+                       } );
+               } );
+       },
+       showDownload:function( $target ) {
+               var _this = this;
+               // Load the roe if available (to populate out download options:
+               function getShowVideoDownload() {
+                               var out = '<div style="color:white">';
+                       var dl_list = '';
+                       var dl_txt_list = '';
+                       $j.each( _this.media_element.getSources(), function( index, source ) {
+                               var dl_line = '<li>' + '<a style="color:white" href="' + source.getURI() + '"> '
+                                       + source.getTitle() + '</a> ' + '</li>' + "\n";
+                               if (     source.getURI().indexOf( '?t=' ) !== -1 ) {
+                                       out += dl_line;
+                               } else if ( this.getMIMEType() == "text/cmml" || this.getMIMEType() == "text/x-srt" ) {
+                                       dl_txt_list += dl_line;
+                               } else {
+                                       dl_list += dl_line;
+                               }
+                       } );
+                       
+                       if ( dl_list != '' )
+                               out += '<h2>' + gM( 'mwe-download_full' ) + '</h2><ul>' + dl_list + '</ul>';
+                       if ( dl_txt_list != '' )
+                               out += '<h2>' +gM( 'mwe-download_text' ) + '</h2><ul>' + dl_txt_list + '</ul>';
+                       out += '</div>';
+                       return out;
+               }
+               // js_log('f:showDownload '+ this.roe + ' ' + this.media_element.addedROEData);
+               if ( this.roe && this.media_element.addedROEData == false ) {
+                       var _this = this;
+                       $target.html( gM( 'loading_txt' ) );
+                       do_request( this.roe, function( data ) {
+                          _this.media_element.addROE( data );
+                          $target.html( getShowVideoDownload() );
+                       } );
+               } else {
+                       $target.html( getShowVideoDownload() );
+               }
+       },
+       /*
+       *  Base embed controls
+       *  The Play Action:
+       */
+       play : function() {
+               var eid = ( this.pc != null ) ? this.pc.pp.id:this.id;
+                                               
+               // check if thumbnail is being displayed and embed html
+               if ( this.thumbnail_disp ) {
+                       if ( !this.selected_player ) {
+                               js_log( 'no selected_player' );
+                               // this.innerHTML = this.getPluginMissingHTML();                                
+                               $j( '#' + this.id ).html( this.getPluginMissingHTML() );
+                       } else {
+                               this.doEmbedHTML();
+                               this.onClipDone_disp = false;
+                               this.paused = false;
+                               this.thumbnail_disp = false;
+                       }
+               } else {
+                       // the plugin is already being displayed                        
+                       this.paused = false; // make sure we are not "paused"
+                       this.seeking = false;
+               }
+               
+                $j( '#' + eid + ' .play-btn span' ).removeClass( 'ui-icon-play' ).addClass( 'ui-icon-pause' );
+                $j( '#' + eid + ' .play-btn' ).unbind().btnBind().click( function() {
+                       $j( '#' + eid ).get( 0 ).pause();
+                } ).attr( 'title', gM( 'mwe-pause_clip' ) );
+                  
+       },
+       load:function() {
+               // should be done by child (no base way to pre-buffer video)
+               js_log( 'baseEmbed:load call' );
+       },
+       getSrc:function() {
+          return this.media_element.selected_source.getURI( this.seek_time_sec );
+       },
+       /*
+        * Base embed pause
+        *      there is no general way to pause the video
+        *  must be overwritten by embed object to support this functionality.
+        */
+       pause: function() {
+               var _this = this;
+               var eid = ( this.pc != null ) ? this.pc.pp.id:this.id;
+               // js_log('mv_embed:do pause');         
+               // (playing) do pause           
+               this.paused = true;
+               var $pt = $j( '#' + eid);
+               // update the ctrl "paused state"                               
+               $pt.find('.play-btn span' ).removeClass( 'ui-icon-pause' ).addClass( 'ui-icon-play' );
+                $pt.find('.play-btn' ).unbind().btnBind().click( function() {
+                               _this.play();
+               } ).attr( 'title', gM( 'mwe-play_clip' ) );
+       },
+       /**
+        * Base embed stop (can be overwritten by the plugin)
+        */
+       stop: function() {
+               var _this = this;
+               js_log( 'mvEmbed:stop:' + this.id );
+               
+               // no longer seeking:
+               this.didSeekJump = false;
+               
+               // first issue pause to update interface        (only call the parent) 
+               if ( this['parent_pause'] ) {
+                       this.parent_pause();
+               } else {
+                       this.pause();
+               }
+               
+               // reset the currentTime: 
+               this.currentTime = 0;
+               // check if thumbnail is being displayed in which case do nothing
+               if ( this.thumbnail_disp ) {
+                       // already in stooped state
+                       js_log( 'already in stopped state' );
+               } else {
+                       // rewrite the html to thumbnail disp
+                       this.doThumbnailHTML();
+                       this.bufferedPercent = 0; // reset buffer state
+                       this.setSliderValue( 0 );
+                       this.setStatus( this.getTimeReq() );
+               }
+               
+               // make sure the big playbutton is has click action: 
+               $j( '#' + _this.id + ' .play-btn-large' ).unbind( 'click' ).click( function() {
+                       $j( '#' + _this.id ).get( 0 ).play();
+               } );
+               
+               if ( this.update_interval )
+               {
+                       clearInterval( this.update_interval );
+                       this.update_interval = null;
+               }
+       },
+       toggleMute:function() {
+               var eid = ( this.pc != null ) ? this.pc.pp.id:this.id;
+               if ( this.muted ) {
+                       this.muted = false;
+                       $j( '#' + eid + ' .volume-slider' ).slider( 'value', 100 );
+                       this.updateVolumen( 1 );
+               } else {
+                       this.muted = true;
+                       $j( '#' + eid + ' .volume-slider' ).slider( 'value', 0 );
+                       this.updateVolumen( 0 );
+               }
+               js_log( 'f:toggleMute::' + this.muted );
+       },
+       updateVolumen:function( perc ) {
+               js_log( 'update volume not supported with current playback type' );
+       },
+       fullscreen:function() {
+               js_log( 'fullscreen not supported with current playback type' );
+       },
+       /**
+       *  returns bool true if playing or paused, false if stooped
+       */
+       isPlaying : function() {
+               if ( this.thumbnail_disp ) {
+                       // in stoped state
+                       return false;
+               } else if ( this.paused ) {
+                       // paused state
+                       return false;
+               } else {
+                       return true;
+               }
+       },
+       isPaused : function() {
+               return this.isPlaying() && this.paused;
+       },
+       isStoped : function() {
+               return this.thumbnail_disp;
+       },
+       playlistSupport:function() {
+               // by default not supported (implemented in js)
+               return false;
+       },
+       postEmbedJS:function() {
+               return '';
+       },
+       /*
+       * Monitor playback and update interface components.
+       * underling plugin objects are responsible for updating currentTime
+       */
+       monitor:function() {
+               //js_log(' ct: ' + this.currentTime + ' dur: ' + ( parseInt( this.duration ) + 1 )  + ' is seek: ' + this.seeking );
+               if ( this.currentTime && this.currentTime > 0 && this.duration ) {
+                       if ( !this.userSlide && !this.seeking ) {
+                               if ( this.start_offset  ) {
+                                       // if start offset include that calculation 
+                                       this.setSliderValue( ( this.currentTime - this.start_offset ) / this.duration );
+                                       var et = ( this.ctrlBuilder.long_time_disp ) ? '/' + seconds2npt( parseFloat( this.start_offset ) + parseFloat( this.duration ) ) : '';
+                                       this.setStatus( seconds2npt( this.currentTime ) + et );
+                               } else {
+                                       this.setSliderValue( this.currentTime / this.duration );
+                                       var et = ( this.ctrlBuilder.long_time_disp ) ? '/' + seconds2npt( this.duration ):'';
+                                       this.setStatus( seconds2npt( this.currentTime ) + et );
+                               }
+                       }
+                       // Check if we are "done"
+                       var end_presentation_time = parseFloat( this.startOffset) + parseFloat( this.duration ) ;
+                       if ( this.currentTime > end_presentation_time ) {
+                               js_log( "should run clip done ct:: " + this.currentTime + ' > ' +  end_presentation_time  );
+                               this.onClipDone();
+                       }
+               } else {
+                       // Media lacks duration just show end time
+                       // js_log(' ct:' + this.currentTime + ' dur: ' + this.duration);
+                       if ( this.isStoped() ) {
+                               this.setStatus( this.getTimeReq() );
+                       } else if ( this.isPaused() ) {
+                               this.setStatus( gM( 'mwe-paused' ) );
+                       } else if ( this.isPlaying() ) {
+                               if ( this.currentTime && ! this.duration )
+                                       this.setStatus( seconds2npt( this.currentTime ) + ' /' );
+                               else
+                                       this.setStatus( " - - - " );
+                       } else {
+                               this.setStatus( this.getTimeReq() );
+                       }
+               }
+               // Could check if time > duration here and stop playback
+
+               // Update buffer information 
+               this.updateBufferStatus();
+               var _this = this;
+               // Update monitorTimerId to call child monitor
+               if ( ! this.monitorTimerId ) {
+                       // Make sure an instance of this.id exists: 
+                       if ( document.getElementById( this.id ) ) {
+                               this.monitorTimerId = setInterval( function() {
+                                       if ( _this.id && $j( '#' + _this.id ).length != 0 ) {
+                                               $j( '#' + _this.id ).get( 0 ).monitor();
+                                       }
+                               }, 250 );
+                       }
+               }
+       },
+       stopMonitor:function() {
+               if ( this.monitorTimerId != 0 )
+               {
+                       clearInterval( this.monitorTimerId );
+                       this.monitorTimerId = 0;
+               }
+       },
+       updateBufferStatus: function() {
+                       
+               // Build the buffer target based for playlist vs clip 
+               var buffer_select = ( this.pc ) ?
+                       '#cl_status_' + this.id + ' .mv_buffer':
+                       '#' + this.id + ' .play_head .mv_buffer';
+                       
+               // Update the buffer progress bar (if available )
+               if ( this.bufferedPercent != 0 ) {
+                       // js_log('bufferedPercent: ' + this.bufferedPercent);                  
+                       if ( this.bufferedPercent > 1 )
+                               this.bufferedPercent = 1;
+                       
+                       $j( buffer_select ).css( "width", ( this.bufferedPercent * 100 ) + '%' );
+               } else {
+                       $j( buffer_select ).css( "width", '0px' );
+               }
+       },
+       relativeCurrentTime: function() {
+               if ( !this.start_offset )
+                       this.start_offset = 0;
+               var rt = this.currentTime - this.start_offset;
+               if ( rt < 0 ) // should not happen but does. 
+                       return 0;
+               return rt;
+       },
+       getPluginEmbed : function() {
+               if ( window.document[this.pid] ) {
+                       return window.document[this.pid];
+               }
+               if ( $j.browser.msie ) {
+                       return document.getElementById( this.pid );
+               } else {
+                        if ( document.embeds && document.embeds[this.pid] )
+                               return  document.embeds[this.pid];
+               }
+               return null;
+       },
+       setSliderValue: function( perc, hide_progress ) {
+               var eid = ( this.pc ) ? this.pc.pp.id:this.id;
+               if ( this.controls && $j( '#' + eid + ' .play_head' ).length != 0 ) {
+                       var val = parseInt( perc * 1000 );
+                       $j( '#' + eid + ' .play_head' ).slider( 'value', val );
+               }
+               // js_log('set#mv_seeker_slider_'+eid + ' perc in: ' + perc + ' * ' + $j('#mv_seeker_'+eid).width() + ' = set to: '+ val + ' - '+ Math.round(this.mv_seeker_width*perc) );
+               // js_log('op:' + offset_perc + ' *('+perc+' * ' + $j('#slider_'+id).width() + ')');
+       },
+       highlightPlaySection:function( options ) {
+               js_log( 'highlightPlaySection' );
+               var eid = ( this.pc ) ? this.pc.pp.id:this.id;
+               var dur = this.getDuration();
+               var hide_progress = true;
+               // set the left percet and update the slider: 
+               rel_start_sec = npt2seconds( options['start'] );
+               // remove the start_offset if relevent: 
+               if ( this.start_offset )
+                       rel_start_sec = rel_start_sec - this.start_offset
+               
+               var slider_perc = 0;
+               if ( rel_start_sec <= 0 ) {
+                       left_perc = 0;
+                       options['start'] = seconds2npt( this.start_offset );
+                       rel_start_sec = 0;
+                       this.setSliderValue( 0 , hide_progress );
+               } else {
+                       left_perc = parseInt( ( rel_start_sec / dur ) * 100 ) ;
+                       slider_perc = ( left_perc / 100 );
+               }
+               
+               js_log( "slider perc:" + slider_perc );
+               if ( ! this.isPlaying() ) {
+                       this.setSliderValue( slider_perc , hide_progress );
+               }
+               
+               width_perc = parseInt( ( ( npt2seconds( options['end'] ) - npt2seconds( options['start'] ) ) / dur ) * 100 ) ;
+               if ( ( width_perc + left_perc ) > 100 ) {
+                       width_perc = 100 - left_perc;
+               }
+               // js_log('should hl: '+rel_start_sec+ '/' + dur + ' re:' + rel_end_sec+' lp:'  + left_perc + ' width: ' + width_perc); 
+               $j( '#mv_seeker_' + eid + ' .mv_highlight' ).css( {
+                       'left' : left_perc + '%',
+                       'width' : width_perc + '%'
+               } ).show();
+               
+               this.jump_time =  options['start'];
+               this.seek_time_sec = npt2seconds( options['start'] );
+               // trim output to 
+               this.setStatus( gM( 'mwe-seek_to', seconds2npt( this.seek_time_sec ) ) );
+               js_log( 'DO update: ' +  this.jump_time );
+               this.updateThumbTime( rel_start_sec );
+       },
+       hideHighlight:function() {
+               var eid = ( this.pc ) ? this.pc.pp.id:this.id;
+               $j( '#mv_seeker_' + eid + ' .mv_highlight' ).hide();
+               this.setStatus( this.getTimeReq() );
+               this.setSliderValue( 0 );
+       },
+       setStatus:function( value ) {
+               var eid = ( this.pc ) ? this.pc.pp.id:this.id;
+               // update status:
+               $j( '#' + eid + ' .time-disp' ).html( value );
+       },
+       /**
+       * Helper Functions for selected source 
+       */
+       /*
+       * returns the selected source url for players to play
+       */
+       getURI : function( seek_time_sec ) {
+               return this.media_element.selected_source.getURI( this.seek_time_sec );
+       },
+       supportsURLTimeEncoding: function() {
+               // do head request if on the same domain
+               return this.media_element.selected_source.URLTimeEncoding;
+       }
+}
+
+
+
+/**
+  * mediaPlayer represents a media player plugin.
+  * @param {String} id id used for the plugin.
+  * @param {Array<String>} supported_types n array of supported MIME types.
+  * @param {String} library external script containing the plugin interface code. (mv_<library>Embed.js)
+  * @constructor
+  */
+function mediaPlayer( id, supported_types, library )
+{
+       this.id = id;
+       this.supported_types = supported_types;
+       this.library = library;
+       this.loaded = false;
+       this.loading_callbacks = new Array();
+       return this;
+}
+mediaPlayer.prototype =
+{
+       id:null,
+       supported_types:null,
+       library:null,
+       loaded:false,
+       loading_callbacks:null,
+       supportsMIMEType : function( type )
+       {
+               for ( var i = 0; i < this.supported_types.length; i++ )
+                       if ( this.supported_types[i] == type )
+                               return true;
+               return false;
+       },
+       getName : function()
+       {
+               return gM( 'mwe-ogg-player-' + this.id );
+       },
+       load : function( callback ) {   
+               mvJsLoader.doLoad( [
+                       this.library + 'Embed'
+               ], function() {                 
+                       js_log("wtf: " + typeof( vlcEmbed ) );
+                       callback();
+               } );
+       }
+}
+/* players and supported mime types 
+@@note ideally we query the plugin to get what mime types it supports in practice not always reliable/avaliable
+*/
+//var flowPlayer = new mediaPlayer( 'flowplayer', ['video/x-flv', 'video/h264'], 'flowplayer' );
+var kplayer = new mediaPlayer('kplayer', ['video/x-flv', 'video/h264'], 'kplayer');
+
+var omtkPlayer = new mediaPlayer( 'omtkplayer', ['audio/ogg'], 'omtk' );
+
+var cortadoPlayer = new mediaPlayer( 'cortado', ['video/ogg', 'audio/ogg'], 'java' );
+var videoElementPlayer = new mediaPlayer( 'videoElement', ['video/ogg', 'audio/ogg'], 'native' );
+
+var vlcMineList = ['video/ogg', 'audio/ogg', 'video/x-flv', 'video/mp4',  'video/h264'];
+var vlcPlayer = new mediaPlayer( 'vlc-player', vlcMineList, 'vlc' );
+
+// add generic
+var oggPluginPlayer = new mediaPlayer( 'oggPlugin', ['video/ogg'], 'generic' );
+
+// depricate quicktime in favor of safari native 
+// var quicktimeMozillaPlayer = new mediaPlayer('quicktime-mozilla',['video/ogg'],'quicktime');
+// var quicktimeActiveXPlayer = new mediaPlayer('quicktime-activex',['video/ogg'],'quicktime');
+
+var htmlPlayer = new mediaPlayer( 'html', ['text/html', 'image/jpeg', 'image/png', 'image/svg'], 'html' );
+
+/**
+  * mediaPlayers is a collection of mediaPlayer objects supported by the client.
+  * It could be merged with embedTypes, since there is one embedTypes per script
+  * and one mediaPlayers per embedTypes.
+  */
+function mediaPlayers()
+{
+       this.init();
+}
+
+mediaPlayers.prototype =
+{
+       players : null,
+       preference : null,
+       default_players : { },
+       init : function() {
+               this.players = new Array();
+               this.loadPreferences();
+               
+               // set up default players order for each library type           
+               this.default_players['video/x-flv'] = ['kplayer', 'vlc'];
+               this.default_players['video/h264'] = ['kplayer', 'vlc'];
+               
+               this.default_players['video/ogg'] = ['native', 'vlc', 'java', 'generic'];
+               this.default_players['application/ogg'] = ['native', 'vlc', 'java', 'generic'];
+               this.default_players['audio/ogg'] = ['native', 'vlc', 'java', 'omtk' ];
+               this.default_players['video/mp4'] = ['vlc'];
+               
+               this.default_players['text/html'] = ['html'];
+               this.default_players['image/jpeg'] = ['html'];
+               this.default_players['image/png'] = ['html'];
+               this.default_players['image/svg'] = ['html'];
+               
+       },
+       addPlayer : function( player, mime_type ) {
+               for ( var i = 0; i < this.players.length; i++ ) {
+                       if ( this.players[i].id == player.id ) {
+                               if ( mime_type != null ) {
+                                       // make sure the mime_type is not already there:
+                                       var add_mime = true;
+                                       for ( var j = 0; j < this.players[i].supported_types.length; j++ ) {
+                                               if ( this.players[i].supported_types[j] == mime_type )
+                                                       add_mime = false;
+                                       }
+                                       if ( add_mime )
+                                               this.players[i].supported_types.push( mime_type );
+                               }
+                               return ;
+                       }
+               }
+               // Player not found: 
+               if ( mime_type != null )
+                       player.supported_types.push( mime_type );
+                                 
+               js_log( 'Adding ' + player.id + ' with mime_type ' + mime_type );
+               this.players.push( player );
+       },
+       getMIMETypePlayers : function( mime_type ) {
+               var mime_players = new Array();
+               var _this = this;
+               var inx = 0;
+               if ( this.default_players[mime_type] ) {
+                       $j.each( this.default_players[mime_type], function( d, lib ) {
+                               var library = _this.default_players[mime_type][d];
+                               for ( var i = 0; i < _this.players.length; i++ ) {
+                                       if ( _this.players[i].library == library && _this.players[i].supportsMIMEType( mime_type ) ) {
+                                               mime_players[ inx ] = _this.players[i];
+                                               inx++;
+                                       }
+                               }
+                       } );
+               }
+               return mime_players;
+       },
+       defaultPlayer : function( mime_type ) {
+               js_log( "get defaultPlayer for " + mime_type );
+               var mime_players = this.getMIMETypePlayers( mime_type );
+               if ( mime_players.length > 0 )
+               {
+                       // Check for prior preference for this mime type
+                       for ( var i = 0; i < mime_players.length; i++ ) {
+                               if ( mime_players[i].id == this.preference[mime_type] )
+                                       return mime_players[i];
+                       }
+                       // Otherwise just return the first compatible player
+                       // (it will be chosen according to the default_players list
+                       return mime_players[0];
+               }
+               js_log( 'No default player found for ' + mime_type );
+               return null;
+       },
+       userSelectFormat : function ( mime_format ) {
+                this.preference['format_prefrence'] = mime_format;
+                this.savePreferences();
+       },
+       userSelectPlayer : function( player_id, mime_type ) {
+               var selected_player = null;
+               for ( var i = 0; i < this.players.length; i++ ) {
+                       if ( this.players[i].id == player_id ) {
+                               selected_player = this.players[i];
+                               js_log( 'choosing ' + player_id + ' for ' + mime_type );
+                               this.preference[mime_type] = player_id;
+                               this.savePreferences();
+                               break;
+                       }
+               }
+               if ( selected_player ) {
+                       for ( var i = 0; i < mw.player_list.length; i++ ) {
+                               var embed = $j( '#' + mw.player_list[i] ).get( 0 );
+                               if ( embed.media_element.selected_source && ( embed.media_element.selected_source.mime_type == mime_type ) )
+                               {
+                                       embed.selectPlayer( selected_player );
+                                       js_log( 'using ' + embed.selected_player.getName() + ' for ' + embed.media_element.selected_source.getTitle() );
+                               }
+                       }
+               }
+       },
+       loadPreferences : function()
+       {
+               this.preference = new Object();
+               // see if we have a cookie set to a clientSupported type:
+               var cookieVal = $j.cookie( 'ogg_player_exp' );
+               if ( cookieVal ) {
+                       var pairs = cookieVal.split( '&' );
+                       for ( var i = 0; i < pairs.length; i++ )
+                       {
+                               var name_value = pairs[i].split( '=' );
+                               this.preference[name_value[0]] = name_value[1];
+                               // js_log('load preference for ' + name_value[0] + ' is ' + name_value[1]);
+                       }
+               }
+       },
+       savePreferences : function() {
+               var cookieVal = '';
+               for ( var i in this.preference )
+                       cookieVal += i + '=' + this.preference[i] + '&';
+                       
+               cookieVal = cookieVal.substr( 0, cookieVal.length -1 );
+               var week = 7 * 86400 * 1000;
+               $j.cookie( 'ogg_player_exp', cookieVal, { 'expires':week } );
+       }
+};
+
+/*
+ * embedTypes object handles setting and getting of supported embed types:
+ * closely mirrors OggHandler so that its easier to share efforts in this area:
+ * http://svn.wikimedia.org/viewvc/mediawiki/trunk/extensions/OggHandler/OggPlayer.js
+ */
+var embedTypes = {
+        // List of players
+        players: null,
+        detect_done:false,
+        init: function() {
+               // detect supported types
+               this.detect();
+               this.detect_done = true;
+       },
+       clientSupports: { 'thumbnail' : true },
+       supportedMimeType: function( mimetype ) {
+               for ( var i = navigator.plugins.length; i-- > 0; ) {
+                       var plugin = navigator.plugins[i];
+                       if ( typeof plugin[mimetype] != "undefined" )
+                         return true;
+               }
+               return false;
+       },
+
+        detect: function() {
+                js_log( "running detect" );
+               this.players = new mediaPlayers();
+               // every browser supports html rendering:
+               this.players.addPlayer( htmlPlayer );
+                // In Mozilla, navigator.javaEnabled() only tells us about preferences, we need to
+                // search navigator.mimeTypes to see if it's installed
+                var javaEnabled = navigator.javaEnabled();
+                // Some browsers filter out duplicate mime types, hiding some plugins
+                var uniqueMimesOnly = $j.browser.opera || $j.browser.safari;
+                // Opera will switch off javaEnabled in preferences if java can't be found.
+                // And it doesn't register an application/x-java-applet mime type like Mozilla does.
+                if ( javaEnabled )
+                        this.players.addPlayer( cortadoPlayer );
+               
+                // ActiveX plugins
+                if ( $j.browser.msie ) {
+                       // check for flash               
+                       if ( this.testActiveX( 'ShockwaveFlash.ShockwaveFlash' ) ) {
+                               // try to get the flash version for omtk include: 
+                               try {
+                                       a = new ActiveXObject( SHOCKWAVE_FLASH_AX + ".7" );
+                                       d = a.GetVariable( "$version" );        // Will crash fp6.0.21/23/29
+                                       if ( d ) {
+                                               d = d.split( " " )[1].split( "," );
+                                               // we need flash version 10 or greater:
+                                               if ( parseInt( d[0] ) >= 10 ) {
+                                                       this.players.addPlayer( omtkPlayer );
+                                               }
+                                       }
+                               } catch ( e ) {
+                                       // failed to check for flash
+                               }
+                               // flowplayer has pretty good compatiablity 
+                               // (but if we wanted to be fancy we would check for version of flash and update the mp4/h.264 support
+
+                               this.players.addPlayer( kplayer );
+                               //this.players.addPlayer( flowPlayer );
+                       }
+                        // VLC
+                        if ( this.testActiveX( 'VideoLAN.VLCPlugin.2' ) )
+                                this.players.addPlayer( vlcPlayer );
+                                
+                        // Java ActiveX
+                        if ( this.testActiveX( 'JavaWebStart.isInstalled' ) )
+                                this.players.addPlayer( cortadoPlayer );
+                        // quicktime (currently off) 
+                        // if ( this.testActiveX( 'QuickTimeCheckObject.QuickTimeCheck.1' ) )
+                        //     this.players.addPlayer(quicktimeActiveXPlayer);                  
+                }
+               // <video> element
+               if ( typeof HTMLVideoElement == 'object' // Firefox, Safari
+                               || typeof HTMLVideoElement == 'function' ) // Opera
+               {
+                       // do another test for safari: 
+                       if ( $j.browser.safari ) {
+                               try {
+                                       var dummyvid = document.createElement( "video" );
+                                       if ( dummyvid.canPlayType && dummyvid.canPlayType( "video/ogg;codecs=\"theora,vorbis\"" ) == "probably" )
+                                       {
+                                               this.players.addPlayer( videoElementPlayer );
+                                       } else if ( this.supportedMimeType( 'video/ogg' ) ) {
+                                               /* older versions of safari do not support canPlayType,
+                                                  but xiph qt registers mimetype via quicktime plugin */
+                                               this.players.addPlayer( videoElementPlayer );
+                                       } else {
+                                               // @@todo add some user nagging to install the xiph qt 
+                                       }
+                               } catch ( e ) {
+                                       js_log( 'could not run canPlayType in safari' );
+                               }
+                       } else {
+                               this.players.addPlayer( videoElementPlayer );
+                       }
+               }
+               
+                // "navigator" plugins
+               if ( navigator.mimeTypes && navigator.mimeTypes.length > 0 ) {
+                       for ( var i = 0; i < navigator.mimeTypes.length; i++ ) {
+                               var type = navigator.mimeTypes[i].type;
+                               var semicolonPos = type.indexOf( ';' );
+                               if ( semicolonPos > -1 ) {
+                                       type = type.substr( 0, semicolonPos );
+                               }
+                               // js_log('on type: '+type);
+                               var pluginName = navigator.mimeTypes[i].enabledPlugin ? navigator.mimeTypes[i].enabledPlugin.name : '';
+                               if ( !pluginName ) {
+                                       // In case it is null or undefined
+                                       pluginName = '';
+                               }
+                               if ( pluginName.toLowerCase() == 'vlc multimedia plugin' || pluginName.toLowerCase() == 'vlc multimedia plug-in' ) {
+                                       this.players.addPlayer( vlcPlayer, type );
+                                       continue;
+                               }
+               
+                               if ( type == 'application/x-java-applet' ) {
+                                       this.players.addPlayer( cortadoPlayer );
+                                       continue;
+                               }
+               
+                               if ( type == 'application/ogg' ) {
+                                       if ( pluginName.toLowerCase() == 'vlc multimedia plugin' ) {
+                                               this.players.addPlayer( vlcMozillaPlayer, type );
+                                       // else if ( pluginName.indexOf( 'QuickTime' ) > -1 )
+                                       //      this.players.addPlayer(quicktimeMozillaPlayer);
+                                       } else {
+                                               this.players.addPlayer( oggPluginPlayer );
+                                       }
+                                       continue;
+                               } else if ( uniqueMimesOnly ) {
+                                       if ( type == 'application/x-vlc-player' ) {
+                                               this.players.addPlayer( vlcMozillaPlayer, type );
+                                               continue;
+                                       } else if ( type == 'video/quicktime' ) {
+                                               // this.players.addPlayer(quicktimeMozillaPlayer);
+                                               continue;
+                                       }
+                               }
+               
+                               /*if ( type == 'video/quicktime' ) {
+                                       this.players.addPlayer(vlcMozillaPlayer, type);
+                                       continue;
+                               }*/
+                               if ( type == 'application/x-shockwave-flash' ) {
+                               
+                                       this.players.addPlayer( kplayer );
+                                       //this.players.addPlayer( flowPlayer );
+                                       
+                                       // check version to add omtk:
+                                       var flashDescription = navigator.plugins["Shockwave Flash"].description;
+                                       var descArray = flashDescription.split( " " );
+                                       var tempArrayMajor = descArray[2].split( "." );
+                                       var versionMajor = tempArrayMajor[0];
+                                       // js_log("version of flash: " + versionMajor);
+                                       if ( versionMajor >= 10 ) {
+                                               this.players.addPlayer( omtkPlayer );
+                                       }
+                                       continue;
+                               }
+                       }
+               }
+               // @@The xiph quicktime component does not work well with annodex streams (temporarly disable)
+               // this.clientSupports['quicktime-mozilla'] = false;
+               // this.clientSupports['quicktime-activex'] = false;
+               // js_log(this.clientSupports);
+       },
+       testActiveX : function ( name ) {
+                var hasObj = true;
+                try {
+                        // No IE, not a class called "name", it's a variable
+                        var obj = new ActiveXObject( '' + name );
+                } catch ( e ) {
+                        hasObj = false;
+                }
+                return hasObj;
+       }
+};
diff --git a/js2/mwEmbed/libEmbedVideo/flowplayerEmbed.js b/js2/mwEmbed/libEmbedVideo/flowplayerEmbed.js
new file mode 100644 (file)
index 0000000..d2cecd0
--- /dev/null
@@ -0,0 +1,1726 @@
+/**
+ * metavid: mv_flashEmbed builds off of flowplayer api (included first in this file)
+ * THIS WILL BE DEPRECIATED SOON
+ */
+
+ /**
+ * flowplayer.js 3.0.0-rc5. The Flowplayer API.
+ *
+ * This file is part of Flowplayer, http://flowplayer.org
+ *
+ * Author: Tero Piirainen, <support@flowplayer.org>
+ * Copyright (c) 2008 Flowplayer Ltd
+ *
+ * Released under the MIT License:
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * Version: 3.0.0-rc5 - Thu Nov 20 2008 22:09:49 GMT-0000 (GMT+00:00)
+ */
+( function() {
+
+/*
+       FEATURES
+       --------
+       - handling multiple instances
+       - Flowplayer programming API
+       - Flowplayer event model
+       - player loading / unloading
+       - $f() function
+       - jQuery support
+*/
+
+/*jslint glovar: true, browser: true */
+/*global flowplayer, $f */
+
+// {{{ private utility methods
+
+       function log( args ) {
+
+               // write into opera console
+               if ( typeof opera == 'object' ) {
+                       opera.postError( "$f.fireEvent: " + args.join( " | " ) );
+
+
+               } else if ( typeof console == 'object' ) {
+                       console.log( "$f.fireEvent", [].slice.call( args ) );
+               }
+       }
+
+       // thanks: http://keithdevens.com/weblog/archive/2007/Jun/07/javascript.clone
+       function clone ( obj ) {
+               if ( !obj || typeof obj != 'object' ) { return obj; }
+               var temp = new obj.constructor();
+               for ( var key in obj ) {
+                       if ( obj.hasOwnProperty( key ) ) {
+                               temp[key] = clone ( obj[key] );
+                       }
+               }
+               return temp;
+       }
+
+       // stripped from jQuery, thanks John Resig
+       function each( obj, fn ) {
+               if ( !obj ) { return; }
+
+               var name, i = 0, length = obj.length;
+
+               // object
+               if ( length === undefined ) {
+                       for ( name in obj ) {
+                               if ( fn.call( obj[name], name, obj[name] ) === false ) { break; }
+                       }
+
+               // array
+               } else {
+                       for ( var value = obj[0];
+                               i < length && fn.call( value, i, value ) !== false; value = obj[++i] ) {
+                       }
+               }
+
+               return obj;
+       }
+
+       // convenience
+       function el( id ) {
+               return document.getElementById( id );
+       }
+
+       // used extensively. a very simple implementation.
+       function extend( to, from, skipFuncs ) {
+               if ( to && from ) {
+                       each( from, function( name, value ) {
+                               if ( !skipFuncs || typeof value != 'function' ) {
+                                       to[name] = value;
+                               }
+                       } );
+               }
+       }
+
+       // var arr = select("elem.className");
+       function select( query ) {
+               var index = query.indexOf( "." );
+               if ( index != - 1 ) {
+                       var tag = query.substring( 0, index ) || "*";
+                       var klass = query.substring( index + 1, query.length );
+                       var els = [];
+                       each( document.getElementsByTagName( tag ), function() {
+                               if ( this.className && this.className.indexOf( klass ) != - 1 ) {
+                                       els.push( this );
+                               }
+                       } );
+                       return els;
+               }
+       }
+
+       // fix event inconsistencies across browsers
+       function stopEvent( e ) {
+               e = e || window.event;
+
+               if ( e.preventDefault ) {
+                       e.stopPropagation();
+                       e.preventDefault();
+
+               } else {
+                       e.returnValue = false;
+                       e.cancelBubble = true;
+               }
+               return false;
+       }
+
+       // push an event listener into existing array of listeners
+       function bind( to, evt, fn ) {
+               to[evt] = to[evt] || [];
+               to[evt].push( fn );
+       }
+
+
+       // generates an unique id
+       function makeId() {
+               return "_" + ( "" + Math.random() ).substring( 2, 10 );
+       }
+
+// }}}
+// {{{ Clip
+       var Clip = function( json, index, player ) {
+               // private variables
+               var self = this;
+               var cuepoints = { };
+               var listeners = { };
+               this.index = index;
+
+               // instance variables
+               if ( typeof json == 'string' ) {
+                       json = { url:json };
+               }
+
+               extend( this, json, true );
+
+               // event handling
+               each( ( "Begin*,Start,Pause*,Resume*,Seek*,Stop*,Finish*,LastSecond,Update,BufferFull,BufferEmpty,BufferStop" ).split( "," ),
+                       function() {
+
+                       var evt = "on" + this;
+
+                       // before event
+                       if ( evt.indexOf( "*" ) != - 1 ) {
+                               evt = evt.substring( 0, evt.length - 1 );
+                               var before = "onBefore" + evt.substring( 2 );
+
+                               self[before] = function( fn ) {
+                                       bind( listeners, before, fn );
+                                       return self;
+                               };
+                       }
+
+                       self[evt] = function( fn ) {
+                               bind( listeners, evt, fn );
+                               return self;
+                       };
+
+                       // set common clip event listeners to player level
+                       if ( index == - 1 ) {
+                               if ( self[before] ) {
+                                       player[before] = self[before];
+                               }
+                               if ( self[evt] )  {
+                                       player[evt] = self[evt];
+                               }
+                       }
+               } );
+
+               extend( this, {
+                       onCuepoint: function( points, fn ) {
+
+                               // embedded cuepoints
+                               if ( arguments.length == 1 ) {
+                                       cuepoints.embedded = [null, points];
+                                       return self;
+                               }
+
+                               if ( typeof points == 'number' ) {
+                                       points = [points];
+                               }
+
+                               var fnId = makeId();
+                               cuepoints[fnId] = [points, fn];
+
+                               if ( player.isLoaded() ) {
+                                       player._api().fp_addCuepoints( points, index, fnId );
+                               }
+
+                               return self;
+                       },
+                       update: function( json ) {
+                               extend( self, json );
+
+                               if ( player.isLoaded() ) {
+                                       player._api().fp_updateClip( json, index );
+                               }
+                               var conf = player.getConfig();
+                               var clip = ( index == - 1 ) ? conf.clip : conf.playlist[index];
+                               extend( clip, json, true );
+                       },
+                       // internal event for performing clip tasks. should be made private someday
+                       _fireEvent: function( evt, arg1, arg2, target ) {
+
+                               if ( evt == 'onLoad' ) {
+                                       each( cuepoints, function( key, val ) {
+                                               player._api().fp_addCuepoints( val[0], index, key );
+                                       } );
+                                       return false;
+                               }
+
+                               // target clip we are working against
+                               if ( index != - 1 ) {
+                                       target = self;
+                               }
+
+                               if ( evt == 'onCuepoint' ) {
+                                       var fn = cuepoints[arg1];
+                                       if ( fn ) {
+                                               return fn[1].call( player, target, arg2 );
+                                       }
+                               }
+
+                               if ( evt == 'onStart' || evt == 'onUpdate' ) {
+
+                                       extend( target, arg1 );
+
+                                       if ( !target.duration ) {
+                                               target.duration = arg1.metaData.duration;
+                                       } else {
+                                               target.fullDuration = arg1.metaData.duration;
+                                       }
+                               }
+
+                               var ret = true;
+                               each( listeners[evt], function() {
+                                       ret = this.call( player, target, arg1 );
+                               } );
+                               return ret;
+                       }
+               } );
+
+               // get cuepoints from config
+               if ( json.onCuepoint ) {
+                       self.onCuepoint.apply( self, json.onCuepoint );
+                       delete json.onCuepoint;
+               }
+
+               // get other events
+               each( json, function( key, val ) {
+                       if ( typeof val == 'function' ) {
+                               bind( listeners, key, val );
+                               delete json[key];
+                       }
+               } );
+
+               // setup common clip event callbacks for Player object too (shortcuts)
+               if ( index == - 1 ) {
+                       player.onCuepoint = this.onCuepoint;
+               }
+       };
+
+// }}}
+// {{{ Plugin
+       var Plugin = function( name, json, player, fn ) {
+               var listeners = { };
+               var self = this;
+               var hasMethods = false;
+
+               if ( fn ) {
+                       extend( listeners, fn );
+               }
+
+               // custom callback functions in configuration
+               each( json, function( key, val ) {
+                       if ( typeof val == 'function' ) {
+                               listeners[key] = val;
+                               delete json[key];
+                       }
+               } );
+
+               // core plugin methods
+               extend( this, {
+                       animate: function( props, speed, fn ) {
+                               if ( !props ) {
+                                       return self;
+                               }
+
+                               if ( typeof speed == 'function' ) {
+                                       fn = speed;
+                                       speed = 500;
+                               }
+
+                               if ( typeof props == 'string' ) {
+                                       var key = props;
+                                       props = { };
+                                       props[key] = speed;
+                                       speed = 500;
+                               }
+
+                               if ( fn ) {
+                                       var fnId = makeId();
+                                       listeners[fnId] = fn;
+                               }
+
+                               if ( speed === undefined ) { speed = 500; }
+                               json = player._api().fp_animate( name, props, speed, fnId );
+                               return self;
+                       },
+                       css: function( props, val ) {
+                               if ( val !== undefined ) {
+                                       var css = { };
+                                       css[props] = val;
+                                       props = css;
+                               }
+                               try {
+                                       json = player._api().fp_css( name, props );
+                                       extend( self, json );
+                                       return self;
+                               } catch ( e ) {
+                                       js_log( 'flow player could not set css: ' + json );
+                               }
+                       },
+                       show: function() {
+                               this.display = 'block';
+                               player._api().fp_showPlugin( name );
+                               return self;
+                       },
+                       hide: function() {
+                               this.display = 'none';
+                               player._api().fp_hidePlugin( name );
+                               return self;
+                       },
+                       toggle: function() {
+                               this.display = player._api().fp_togglePlugin( name );
+                               return self;
+                       },
+                       fadeTo: function( o, speed, fn ) {
+
+                               if ( typeof speed == 'function' ) {
+                                       fn = speed;
+                                       speed = 500;
+                               }
+
+                               if ( fn ) {
+                                       var fnId = makeId();
+                                       listeners[fnId] = fn;
+                               }
+                               this.display = player._api().fp_fadeTo( name, o, speed, fnId );
+                               this.opacity = o;
+                               return self;
+                       },
+                       fadeIn: function( speed, fn ) {
+                               return self.fadeTo( 1, speed, fn );
+                       },
+                       fadeOut: function( speed, fn ) {
+                               return self.fadeTo( 0, speed, fn );
+                       },
+                       getName: function() {
+                               return name;
+                       },
+                       // internal method not meant to be used by clients
+                       _fireEvent: function( evt, arg ) {
+                               // update plugins properties & methods
+                               if ( evt == 'onUpdate' ) {
+                                       var json = arg || player._api().fp_getPlugin( name );
+                                       if ( !json ) { return; }
+
+                                       Extend( self, json );
+                                       delete self.methods;
+       
+                                       if ( !hasMethods ) {
+                                               each( json.methods, function() {
+                                                       var method = "" + this;
+       
+                                                       self[method] = function() {
+                                                               var a = [].slice.call( arguments );
+                                                               var ret = player._api().fp_invoke( name, method, a );
+                                                               return ret == 'undefined' ? self : ret;
+                                                       };
+                                               } );
+                                               hasMethods = true;
+                                       }
+                               }
+
+                               // plugin callbacks
+                               var fn = listeners[evt];
+
+                               if ( fn ) {
+                                       fn.call( self, arg );
+
+                                       // "one-shot" callback
+                                       if ( evt.substring( 0, 1 ) == "_" ) {
+                                               delete listeners[evt];
+                                       }
+                               }
+                       }
+
+               } );
+
+       };
+
+// }}}
+function Player( wrapper, params, conf ) {
+       // private variables (+ arguments)
+       var
+               self = this,
+               api = null,
+               html,
+               commonClip,
+               playlist = [],
+               plugins = { },
+               listeners = { },
+               playerId,
+               apiId,
+               activeIndex,
+               swfHeight,
+               wrapperHeight;
+
+// {{{ public methods
+       extend( self, {
+               id: function() {
+                       return playerId;
+               },
+               isLoaded: function() {
+                       return ( api !== null );
+               },
+               getParent: function() {
+                       return wrapper;
+               },
+               hide: function( all ) {
+                       if ( all ) { wrapper.style.height = "0px"; }
+                       if ( api ) { api.style.height = "0px"; }
+                       return self;
+               },
+               show: function() {
+                       wrapper.style.height = wrapperHeight + "px";
+                       if ( api ) { api.style.height = swfHeight + "px"; }
+                       return self;
+               },
+               isHidden: function() {
+                       return api && parseInt( api.style.height, 10 ) === 0;
+               },
+               load: function( fn ) {
+
+                       if ( !api && self._fireEvent( "onBeforeLoad" ) !== false ) {
+
+                               // unload all instances
+                               each( players, function()  {
+                                       this.unload();
+                               } );
+
+                               html = wrapper.innerHTML;
+                               flashembed( wrapper, params, { config: conf } );
+
+                               // function argument
+                               if ( fn ) {
+                                       fn.cached = true;
+                                       bind( listeners, "onLoad", fn );
+                               }
+                       }
+
+                       return self;
+               },
+               unload: function() {
+                       if ( api && html.replace( /\s/g, '' ) !== '' && !api.fp_isFullscreen() &&
+                         self._fireEvent( "onBeforeUnload" ) !== false ) {
+                               api.fp_close();
+                               wrapper.innerHTML = html;
+                               self._fireEvent( "onUnload" );
+                               api = null;
+                       }
+
+                       return self;
+               },
+               getClip: function( index ) {
+                       if ( index === undefined ) {
+                               index = activeIndex;
+                       }
+                       return playlist[index];
+               },
+               getCommonClip: function() {
+                       return commonClip;
+               },
+               getPlaylist: function() {
+                       return playlist;
+               },
+               getPlugin: function( name ) {
+                 var plugin = plugins[name];
+                       // create plugin if nessessary
+                       if ( !plugin && self.isLoaded() ) {
+                               var json = self._api().fp_getPlugin( name );
+                               if ( json ) {
+                                       plugin = new Plugin( name, json, self );
+                                       plugins[name] = plugin;
+                               }
+                       }
+                       return plugin;
+               },
+               getScreen: function() {
+                       return self.getPlugin( "screen" );
+               },
+               getControls: function() {
+                       return self.getPlugin( "controls" );
+               },
+               getConfig: function() {
+                       return clone ( conf );
+               },
+               getFlashParams: function() {
+                       return params;
+               },
+               loadPlugin: function( name, url, props, fn ) {
+                       // properties not supplied
+                       if ( typeof props == 'function' ) {
+                               fn = props;
+                               props = { };
+                       }
+
+                       // if fn not given, make a fake id so that plugin's onUpdate get's fired
+                       var fnId = fn ? makeId() : "_";
+                       self._api().fp_loadPlugin( name, url, props, fnId );
+
+                       // create new plugin
+                       var arg = { };
+                       arg[fnId] = fn;
+                       var p = new Plugin( name, null, self, arg );
+                       plugins[name] = p;
+                       return p;
+               },
+               getState: function() {
+                       return api ? api.fp_getState() : - 1;
+               },
+               // "lazy" play
+               play: function( clip ) {
+                       function play() {
+                               if ( clip !== undefined ) {
+                                       self._api().fp_play( clip );
+                               } else {
+                                       if ( typeof self._api().fp_play == 'function' )
+                                               self._api().fp_play();
+                               }
+                       }
+
+                       if ( api ) {
+                               play();
+                       } else {
+                               self.load( function() {
+                                       play();
+                               } );
+                       }
+
+                       return self;
+               },
+               getVersion: function() {
+                       var js = "flowplayer.js 3.0.0-rc5";
+                       if ( api ) {
+                               var ver = api.fp_getVersion();
+                               ver.push( js );
+                               return ver;
+                       }
+                       return js;
+               },
+               _api: function() {
+                       if ( !api ) {
+                               throw "Flowplayer " + self.id() + " not loaded. Try moving your call to player's onLoad event";
+                       }
+                       return api;
+               },
+               _dump: function() {
+                       console.log( listeners );
+               }
+       } );
+
+       // event handlers
+       each( ( "Click*,Load*,Unload*,Keypress*,Volume*,Mute*,Unmute*,PlaylistReplace,Fullscreen*,FullscreenExit,Error" ).split( "," ),
+               function() {
+                       var name = "on" + this;
+
+                       // before event
+                       if ( name.indexOf( "*" ) != - 1 ) {
+                               name = name.substring( 0, name.length - 1 );
+                               var name2 = "onBefore" + name.substring( 2 );
+                               self[name2] = function( fn ) {
+                                       bind( listeners, name2, fn );
+                                       return self;
+                               };
+                       }
+
+                       // normal event
+                       self[name] = function( fn ) {
+                               bind( listeners, name, fn );
+                               return self;
+                       };
+               }
+       );
+
+       // core API methods
+       each( ( "pause,resume,mute,unmute,stop,toggle,seek,getStatus,getVolume,setVolume,getTime,isPaused,isPlaying,startBuffering,stopBuffering,isFullscreen,reset" ).split( "," ),
+               function() {
+                       var name = this;
+
+                       self[name] = function( arg ) {
+                               if ( !api ) { return self; }
+                               try {
+                                       var ret = ( arg === undefined ) ? api["fp_" + name]() : api["fp_" + name]( arg );
+                                       return ret == 'undefined' ? self : ret;
+                               } catch ( e ) {
+                                       js_log( 'flowplayer could not access fp_ ' + name );
+                               }
+                       };
+               }
+       );
+
+// }}}
+// {{{ public method: _fireEvent
+       self._fireEvent = function( evt, arg0, arg1, arg2 ) {
+               if ( conf.debug ) {
+                       log( arguments );
+               }
+
+               // internal onLoad
+               if ( evt == 'onLoad' && !api ) {
+                       api = api || el( apiId );
+                       swfHeight = api.clientHeight;
+
+                       each( playlist, function() {
+                               this._fireEvent( "onLoad" );
+                       } );
+
+                       each( plugins, function( name, p ) {
+                               p._fireEvent( "onUpdate" );
+                       } );
+
+                       commonClip._fireEvent( "onLoad" );
+               }
+
+               if ( evt == 'onContextMenu' ) {
+                       each( conf.contextMenu[arg0], function( key, fn )  {
+                               fn.call( self );
+                       } );
+                       return;
+               }
+
+               if ( evt == 'onPluginEvent' ) {
+                       var name = arg0.name || arg0;
+                       var p = plugins[name];
+                       if ( p ) {
+                               if ( arg0.name ) {
+                                       p._fireEvent( "onUpdate", arg0 );
+                               }
+                               p._fireEvent( arg1 );
+                       }
+                       return;
+               }
+
+               // onPlaylistReplace
+               if ( evt == 'onPlaylistReplace' ) {
+                       playlist = [];
+                       var index = 0;
+                       each( arg0, function() {
+                               playlist.push( new Clip( this, index++ ) );
+                       } );
+               }
+
+               var ret = true;
+
+               // clip event
+               if ( arg0 === 0 || ( arg0 && arg0 >= 0 ) ) {
+                       activeIndex = arg0;
+                       var clip = playlist[arg0];
+
+                       if ( clip ) {
+                               ret = clip._fireEvent( evt, arg1, arg2 );
+                       }
+
+                       if ( !clip || ret !== false ) {
+                               // clip argument is given for common clip, because it behaves as the target
+                               ret = commonClip._fireEvent( evt, arg1, arg2, clip );
+                       }
+               }
+
+               // player event
+               var i = 0;
+               each( listeners[evt], function() {
+                       ret = this.call( self, arg0 );
+
+                       // remove cached entry
+                       if ( this.cached ) {
+                               listeners[evt].splice( i, 1 );
+                       }
+
+                       // break loop
+                       if ( ret === false ) { return false;     }
+                       i++;
+
+               } );
+
+               return ret;
+       };
+
+// }}}
+// {{{ init
+       function init() {
+               if ( $f( wrapper ) ) {
+                       return null;
+               }
+
+               wrapperHeight = parseInt( wrapper.style.height ) || wrapper.clientHeight;
+
+               // register this player into global array of instances
+               players.push( self );
+
+
+               // flashembed parameters
+               if ( typeof params == 'string' ) {
+                       params = { src: params };
+               }
+
+               // playerId
+               playerId = wrapper.id || "fp" + makeId();
+               apiId = params.id || playerId + "_api";
+               params.id = apiId;
+               conf.playerId = playerId;
+
+
+               // plain url is given as config
+               if ( typeof conf == 'string' ) {
+                       conf = { clip: { url:conf } };
+               }
+
+               // common clip is always there
+               conf.clip = conf.clip || { };
+               commonClip = new Clip( conf.clip, - 1, self );
+
+
+               // wrapper href as playlist
+               if ( wrapper.getAttribute( "href" ) ) {
+                       conf.playlist = [ { url:wrapper.getAttribute( "href", 2 ) }];
+               }
+
+               // playlist
+               conf.playlist = conf.playlist || [conf.clip];
+
+               var index = 0;
+               each( conf.playlist, function() {
+
+                       var clip = this;
+
+                       // clip is an array, we don't allow that
+                       if ( typeof clip == 'object' && clip.length )  {
+                               clip = "" + clip;
+                       }
+
+                       if ( !clip.url && typeof clip == 'string' ) {
+                               clip = { url: clip };
+                       }
+
+                       // populate common clip properties to each clip
+                       extend( clip, conf.clip, true );
+
+                       // modify configuration playlist
+                       conf.playlist[index] = clip;
+
+                       // populate playlist array
+                       clip = new Clip( clip, index, self );
+                       playlist.push( clip );
+                       index++;
+               } );
+
+
+               // event listeners
+               each( conf, function( key, val ) {
+                       if ( typeof val == 'function' ) {
+                               bind( listeners, key, val );
+                               delete conf[key];
+                       }
+               } );
+
+
+               // plugins
+               each( conf.plugins, function( name, val ) {
+                       if ( val ) {
+                               plugins[name] = new Plugin( name, val, self );
+                       }
+               } );
+
+
+               // setup controlbar plugin if not explicitly defined
+               if ( !conf.plugins || conf.plugins.controls === undefined ) {
+                       plugins.controls = new Plugin( "controls", null, self );
+               }
+
+               // Flowplayer uses black background by default
+               params.bgcolor = params.bgcolor || "#000000";
+
+
+               // setup default settings for express install
+               params.version = params.version || [9, 0];
+               params.expressInstall = 'http://www.flowplayer.org/swf/expressinstall.swf';
+
+
+               // click function
+               function doClick( e ) {
+                       if ( self._fireEvent( "onBeforeClick" ) !== false ) {
+                               self.load();
+                       }
+                       return stopEvent( e );
+               }
+
+               // defer loading upon click
+               html = wrapper.innerHTML;
+               if ( html.replace( /\s/g, '' ) !== '' ) {
+
+                       if ( wrapper.addEventListener ) {
+                               wrapper.addEventListener( "click", doClick, false );
+
+                       } else if ( wrapper.attachEvent ) {
+                               wrapper.attachEvent( "onclick", doClick );
+                       }
+
+               // player is loaded upon page load
+               } else {
+
+                       // prevent default action from wrapper (safari problem) loaded
+                       if ( wrapper.addEventListener ) {
+                               wrapper.addEventListener( "click", stopEvent, false );
+                       }
+
+                       // load player
+                       self.load();
+               }
+
+       }
+
+       // possibly defer initialization until DOM get's loaded
+       if ( typeof wrapper == 'string' ) {
+               flashembed.domReady( function() {
+                       var node = el( wrapper );
+
+                       if ( !node ) {
+                               throw "Flowplayer cannot access element: " + wrapper;
+                       } else {
+                               wrapper = node;
+                               init();
+                       }
+               } );
+
+       // we have a DOM element so page is already loaded
+       } else {
+               init();
+       }
+// }}}
+}
+
+// {{{ flowplayer() & statics
+// container for player instances
+var players = [];
+
+// this object is returned when multiple player's are requested
+function Iterator( arr ) {
+       this.length = arr.length;
+
+       this.each = function( fn )  {
+               each( arr, fn );
+       };
+
+       this.size = function() {
+               return arr.length;
+       };
+}
+
+// these two variables are the only global variables
+window.flowplayer = window.$f = function() {
+       var instance = null;
+       var arg = arguments[0];
+
+       // $f()
+       if ( !arguments.length ) {
+               each( players, function() {
+                       if ( this.isLoaded() )  {
+                               instance = this;
+                               return false;
+                       }
+               } );
+
+               return instance || players[0];
+       }
+
+       if ( arguments.length == 1 ) {
+               // $f(index);
+               if ( typeof arg == 'number' ) {
+                       return players[arg];
+
+               // $f(wrapper || 'containerId' || '*');
+               } else {
+                       // $f("*");
+                       if ( arg == '*' ) {
+                               return new Iterator( players );
+                       }
+
+                       // $f(wrapper || 'containerId');
+                       each( players, function() {
+                               if ( this.id() == arg.id || this.id() == arg || this.getParent() == arg )  {
+                                       instance = this;
+                                       return false;
+                               }
+                       } );
+
+                       return instance;
+               }
+       }
+
+       // instance builder
+       if ( arguments.length > 1 ) {
+               var swf = arguments[1];
+               var conf = ( arguments.length == 3 ) ? arguments[2] : { };
+
+               if ( typeof arg == 'string' ) {
+                       // select arg by classname
+                       if ( arg.indexOf( "." ) != - 1 ) {
+                               var instances = [];
+
+                               each( select( arg ), function() {
+                                       instances.push( new Player( this, clone ( swf ), clone ( conf ) ) );
+                               } );
+
+                               return new Iterator( instances );
+
+                       // select node by id
+                       } else {
+                               var node = el( arg );
+                               return new Player( node !== null ? node : arg, swf, conf );
+                       }
+
+
+               // arg is a DOM element
+               } else if ( arg ) {
+                       return new Player( arg, swf, conf );
+               }
+       }
+
+       return null;
+};
+
+extend( window.$f, {
+       // called by Flash External Interface
+       fireEvent: function( id, evt, a0, a1, a2 ) {
+               var p = $f( id );
+               return p ? p._fireEvent( evt, a0, a1, a2 ) : null;
+       },
+
+       // create plugins by modifying Player's prototype
+       addPlugin: function( name, fn ) {
+               Player.prototype[name] = fn;
+               return $f;
+       },
+
+       // utility methods for plugin developers
+       each: each,
+
+       extend: extend
+} );
+
+// }}}
+// {{{ jQuery support
+
+if ( typeof jQuery == 'function' ) {
+       jQuery.prototype.flowplayer = function( params, conf ) {
+
+               // select instances
+               if ( !arguments.length || typeof arguments[0] == 'number' ) {
+                       var arr = [];
+                       this.each( function()  {
+                               var p = $f( this );
+                               if ( p ) {
+                                       arr.push( p );
+                               }
+                       } );
+                       return arguments.length ? arr[arguments[0]] : new Iterator( arr );
+               }
+
+               // create flowplayer instances
+               return this.each( function() {
+                       $f( this, clone ( params ), conf ? clone ( conf ) : { } );
+               } );
+
+       };
+
+}
+
+// }}}
+
+
+} )();
+/**
+ * flashembed 0.34. Adobe Flash embedding script
+ *
+ * http://flowplayer.org/tools/flash-embed.html
+ *
+ * Copyright (c) 2008 Tero Piirainen (support@flowplayer.org)
+ *
+ * Released under the MIT License:
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * >> Basically you can do anything you want but leave this header as is <<
+ *
+ * first version 0.01 - 03/11/2008
+ * version 0.34 - Tue Nov 11 2008 09:09:52 GMT-0000 (GMT+00:00)
+ */
+( function() {
+
+// {{{ utility functions
+
+var jQ = typeof jQuery == 'function';
+
+
+// from "Pro JavaScript techniques" by John Resig
+function isDomReady() {
+
+       if ( domReady.done )  { return false; }
+
+       var d = document;
+       if ( d && d.getElementsByTagName && d.getElementById && d.body ) {
+               clearInterval( domReady.timer );
+               domReady.timer = null;
+
+               for ( var i = 0; i < domReady.ready.length; i++ ) {
+                       domReady.ready[i].call();
+               }
+
+               domReady.ready = null;
+               domReady.done = true;
+       }
+}
+
+// if jQuery is present, use it's more effective domReady method
+var domReady = jQ ? jQuery : function( f ) {
+
+       if ( domReady.done ) {
+               return f();
+       }
+
+       if ( domReady.timer ) {
+               domReady.ready.push( f );
+
+       } else {
+               domReady.ready = [f];
+               domReady.timer = setInterval( isDomReady, 13 );
+       }
+};
+
+
+// override extend params function
+function extend( to, from ) {
+       if ( from ) {
+               for ( key in from ) {
+                       if ( from.hasOwnProperty( key ) ) {
+                               to[key] = from[key];
+                       }
+               }
+       }
+
+       return to;
+}
+
+
+function concatVars( vars ) {
+       var out = "";
+
+       for ( var key in vars ) {
+               if ( vars[key] ) {
+                       out += [key] + '=' + asString( vars[key] ) + '&';
+               }
+       }
+       return out.substring( 0, out.length - 1 );
+}
+
+
+
+// JSON.asString() function
+function asString( obj ) {
+
+       switch ( typeOf( obj ) ) {
+               case 'string':
+                       obj = obj.replace( new RegExp( '(["\\\\])', 'g' ), '\\$1' );
+
+                       // flash does not handle %- characters well. transforms "50%" to "50pct" (a dirty hack, I admit)
+                       obj = obj.replace( /^\s?(\d+)%/, "$1pct" );
+                       return '"' + obj + '"';
+
+               case 'array':
+                       return '[' + map( obj, function( el ) {
+                               return asString( el );
+                       } ).join( ',' ) + ']';
+
+               case 'function':
+                       return '"function()"';
+
+               case 'object':
+                       var str = [];
+                       for ( var prop in obj ) {
+                               if ( obj.hasOwnProperty( prop ) ) {
+                                       str.push( '"' + prop + '":' + asString( obj[prop] ) );
+                               }
+                       }
+                       return '{' + str.join( ',' ) + '}';
+       }
+
+       // replace ' --> "  and remove spaces
+       return String( obj ).replace( /\s/g, " ").replace( /\'/g, "\"" );
+}
+
+
+// private functions
+function typeOf(obj) {
+       if (obj === null || obj === undefined) { return false; }
+       var type = typeof obj;
+       return (type == 'object' && obj.push) ? 'array' : type;
+}
+
+
+// version 9 bugfix: (http://blog.deconcept.com/2006/07/28/swfobject-143-released/)
+if (window.attachEvent) {
+       window.attachEvent("onbeforeunload", function() {
+               __flash_unloadHandler = function() {};
+               __flash_savedUnloadHandler = function() {};
+       });
+}
+
+function map(arr, func) {
+       var newArr = [];
+       for (var i in arr) {
+               if (arr.hasOwnProperty(i)) {
+                       newArr[i] = func(arr[i]);
+               }
+       }
+       return newArr;
+}
+
+function getEmbedCode(p, c) {
+       var html = ' < embed type = "application/x-shockwave-flash" ';
+
+       if (p.id) { extend(p, {name:p.id}); }
+
+       for (var key in p) {
+               if (p[key] !== null) {
+                       html += key + '="' + p[key] + '"\n\t';
+               }
+       }
+
+       if (c) {
+                html += 'flashvars=\'' + concatVars( c ) + '\'';
+       }
+
+       // thanks Tom Price (07/17/2008)
+       html += '/>';
+
+       return html;
+}
+
+function getObjectCode( p, c, embeddable ) {
+
+       var html = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" ';
+       html += 'width="' + p.width + '" height="' + p.height + '"';
+
+       // force id for IE. otherwise embedded Flash object cannot be returned
+       if ( !p.id && document.all ) {
+               p.id = "_" + ( "" + Math.random() ).substring( 5 );
+       }
+
+       if ( p.id ) {
+               html += ' id="' + p.id + '"';
+       }
+
+       html += '>';
+
+       // sometimes ie fails to load flash if it's on cache
+       if ( document.all ) {
+               p.src += ( ( p.src.indexOf( "?" ) != - 1 ? "&" : "?" ) + Math.random() );
+       }
+
+       html += '\n\t<param name="movie" value="' + p.src + '" />';
+
+       var e = extend( { }, p );
+       e.id = e.width = e.height = e.src = null;
+
+       for ( var k in e ) {
+               if ( e[k] !== null ) {
+                       html += '\n\t<param name="' + k + '" value="' + e[k] + '" />';
+               }
+       }
+
+       if ( c ) {
+               html += '\n\t<param name="flashvars" value=\'' + concatVars( c ) + '\' />';
+       }
+
+       if ( embeddable ) {
+               html += getEmbedCode( p, c );
+       }
+
+       html += "</object>";
+
+       return html;
+}
+
+function getFullHTML( p, c ) {
+       return getObjectCode( p, c, true );
+}
+
+function getHTML( p, c ) {
+       var isNav = navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length;
+       return ( isNav ) ? getEmbedCode( p, c ) : getObjectCode( p, c );
+}
+
+// }}}
+
+
+window.flashembed = function( root, userParams, flashvars ) {
+
+
+// {{{ construction
+
+       // setup params
+       var params = {
+
+               // very common params
+               src: '#',
+               width: '100%',
+               height: '100%',
+
+               // flashembed specific options
+               version:null,
+               onFail:null,
+               expressInstall:null,
+               debug: false,
+
+               // flashembed defaults
+               // bgcolor: 'transparent',
+               allowfullscreen: true,
+               allowscriptaccess: 'always',
+               quality: 'high',
+               type: 'application/x-shockwave-flash',
+               pluginspage: 'http://www.adobe.com/go/getflashplayer'
+       };
+
+
+       if ( typeof userParams == 'string' ) {
+               userParams = { src: userParams };
+       }
+
+       extend( params, userParams );
+
+       var version = flashembed.getVersion();
+       var required = params.version;
+       var express = params.expressInstall;
+       var debug = params.debug;
+
+
+       if ( typeof root == 'string' ) {
+               var el = document.getElementById( root );
+               if ( el ) {
+                       root = el;
+               } else {
+                       domReady( function() {
+                               flashembed( root, userParams, flashvars );
+                       } );
+                       return;
+               }
+       }
+
+       if ( !root ) { return; }
+
+
+       // is supported
+       if ( !required || flashembed.isSupported( required ) ) {
+               params.onFail = params.version = params.expressInstall = params.debug = null;
+
+               // root.innerHTML may cause broplems: http://domscripting.com/blog/display/99
+               // thanks to: Ryan Rud
+               // var tmp = document.createElement("extradiv");
+               // tmp.innerHTML = getHTML();
+               // root.appendChild(tmp);
+
+               root.innerHTML = getHTML( params, flashvars );
+
+               // return our API
+               return root.firstChild;
+
+       // custom fail event
+       } else if ( params.onFail ) {
+               var ret = params.onFail.call( params, flashembed.getVersion(), flashvars );
+               if ( ret === true ) { root.innerHTML = ret; }
+
+
+       // express install
+       } else if ( required && express && flashembed.isSupported( [6, 65] ) ) {
+
+               extend( params, { src: express } );
+
+               flashvars = {
+                       MMredirectURL: location.href,
+                       MMplayerType: 'PlugIn',
+                       MMdoctitle: document.title
+               };
+
+               root.innerHTML = getHTML( params, flashvars );
+
+       // not supported
+       } else {
+
+               // minor bug fixed here 08.04.2008 (thanks JRodman)
+
+               if ( root.innerHTML.replace( /\s/g, '') !== '' ) {
+                       // custom content was supplied
+
+               } else {
+                       root.innerHTML =
+                               "<h2>Flash version " + required + " or greater is required</h2>" +
+                               "<h3>" +
+                                       ( version[0] > 0 ? "Your version is " + version : "You have no flash plugin installed" ) +
+                               "</h3>" +
+                               "<p>Download latest version from <a href='" + params.pluginspage + "'>here</a></p>";
+               }
+       }
+
+       return root;
+
+// }}}
+
+
+};
+
+
+// {{{ static methods
+
+extend( window.flashembed, {
+
+       // returns arr[major, fix]
+       getVersion: function() {
+
+               var version = [0, 0];
+
+               if ( navigator.plugins && typeof navigator.plugins["Shockwave Flash"] == "object" ) {
+                       var _d = navigator.plugins["Shockwave Flash"].description;
+                       if ( typeof _d != "undefined" ) {
+                               _d = _d.replace( /^.*\s+(\S+\s+\S+$ )/, "$1" );
+                               var _m = parseInt( _d.replace( /^(.*)\..*$/, "$1" ), 10 );
+                               var _r = / r / .test( _d ) ? parseInt( _d.replace( /^.*r(.*)$/ , "$1" ), 10 ) : 0;
+                               version = [_m, _r];
+                       }
+
+               } else if ( window.ActiveXObject ) {
+
+                       try { // avoid fp 6 crashes
+                               var _a = new ActiveXObject( "ShockwaveFlash.ShockwaveFlash.7" );
+
+                       } catch ( e ) {
+                               try {
+                                       _a = new ActiveXObject( "ShockwaveFlash.ShockwaveFlash.6" );
+                                       version = [6, 0];
+                                       _a.AllowScriptAccess = "always"; // throws if fp < 6.47
+
+                               } catch ( ee ) {
+                                       if ( version[0] == 6 ) { return; }
+                               }
+                               try {
+                                       _a = new ActiveXObject( "ShockwaveFlash.ShockwaveFlash" );
+                               } catch ( eee ) {
+
+                               }
+
+                       }
+
+                       if ( typeof _a == "object" ) {
+                               _d = _a.GetVariable( "$version" ); // bugs in fp 6.21 / 6.23
+                               if ( typeof _d != "undefined" ) {
+                                       _d = _d.replace( /^\S+\s+(.*)$/, "$1" ).split( "," );
+                                       version = [parseInt( _d[0], 10 ), parseInt( _d[2], 10 )];
+                               }
+                       }
+               }
+
+               return version;
+       },
+
+       isSupported: function( version ) {
+               var now = flashembed.getVersion();
+               var ret = ( now[0] > version[0] ) || ( now[0] == version[0] && now[1] >= version[1] );
+               return ret;
+       },
+
+       domReady: domReady,
+
+       // returns a String representation from JSON object
+       asString: asString,
+
+       getHTML: getHTML,
+
+       getFullHTML: getFullHTML
+
+} );
+
+// }}}
+
+
+// setup jquery support
+if ( jQ ) {
+
+       jQuery.prototype.flashembed = function( params, flashvars ) {
+               return this.each( function() {
+                       flashembed( this, params, flashvars );
+               } );
+       };
+
+}
+
+} )();
+
+/************************************************
+********* mv_embed extension to flowplayer.js ***
+************************************************/
+var flowplayerEmbed = {
+       instanceOf:'flowplayerEmbed',
+       monitorTimerId : 0,
+       old_pid:0,
+       didSeekJump:false,
+       startedTimedPlayback:false,
+       didDateStartTimeRestore:false,
+       supports: {
+               'play_head' : true,
+               'pause' : true,
+               'stop' : true,
+               'time_display' : true,
+               'volume_control' : true
+       },
+       getEmbedHTML: function () {
+               setTimeout( 'document.getElementById(\'' + this.id + '\').postEmbedJS()', 150 );
+               return this.wrapEmebedContainer( this.getEmbedObj() );
+       },
+       getEmbedObj:function() {
+               // give the embed element a unique pid (work around for flowplayer persistence)
+               if ( this.old_pid != 0 ) {
+                       this.pid = this.pid + '_' + this.old_pid;
+               }
+               return '<a  ' +
+                                       'href="' + this.getSrc() + '" ' +
+                                       'style="display:block;width:' + parseInt( this.width ) + 'px;height:' + parseInt( this.height ) + 'px" ' +
+                                       'id="' + this.pid + '">' +
+                               '</a>';
+       },
+       postEmbedJS: function()
+       {
+               var _this = this;
+               js_log( 'embedFlow: uri:' + this.getSrc() + "\n" + mv_embed_path + 'libEmbedVideo/binPlayers/flowplayer/flowplayer-3.0.1.swf' ) ;
+               var flowConfig = {
+                       clip: {
+                               url: this.getSrc(),
+                               // when this is false playback does not start until play button is pressed
+                               autoPlay: true
+                       },
+                       plugins: {
+                               controls: {
+                                  all: false,
+                                  fullscreen: true,
+                                  backgroundColor: 'transparent',
+                                  backgroundGradient: 'none',
+                                  autoHide:'always',
+                                  top:'95%',
+                                  right:'0px'
+                               }
+                       },
+                       screen: {
+                               opacity : '1.0'
+                       }
+               };
+
+               // if in preview mode set grey and lower volume until "ready"
+               if ( this.preview_mode ) {
+                       flowConfig.screen.opacity = 0.2;
+               }
+
+               $f( this.pid,  mv_embed_path + 'binPlayers/flowplayer/flowplayer-3.0.1.swf', flowConfig );
+               // get the this.fla value:
+               this.getFLA();
+               // set up bindings (for when interacting with the swf causes action:
+               this.fla.onPause( function() {
+                       _this.parent_pause();   // update the interface
+               } )
+               this.fla.onResume( function() {
+                       _this.parent_play();    // update the interface
+               } );
+
+               // start monitor:
+               this.monitor();
+               this.old_pid++;
+       },
+       /* js hooks/controls */
+       play: function() {
+               this.getFLA();
+               // update play/pause button etc
+               this.parent_play();
+               if ( this.fla ) {
+                       this.fla.play();
+
+                       // on a resume make sure volume and opacity are correct
+                       this.restorePlayer();
+                       setTimeout( '$j(\'#' + this.id + '\').get(0).monitor()', 250 );
+               }
+       },
+       // @@todo support mute
+       toggleMute: function() {
+               this.parent_toggleMute();
+               this.getFLA();
+               if ( this.fla ) {
+                       if ( this.muted ) {
+
+                       } else {
+
+                       }
+               }
+       },
+       // @@ Suport UpDateVolumen
+       updateVolumen:function( perc ) {
+               this.getFLA();
+               if ( this.fla )this.fla.setVolume( perc * 100 );
+
+    },
+    // @@ Get Volumen
+       getVolumen:function() {
+               this.getFLA();
+               if ( this.fla )
+                       return this.fla.getVolume() / 100;
+    },
+       fullscreen:function() {
+               if ( this.fla ) {
+                       this.fla.fullscreen();
+               } else {
+                       js_log( 'must be playing before you can go fullscreen' );
+               }
+       },
+       pause : function()
+       {
+               this.getFLA();
+               if ( !this.thumbnail_disp ) {
+                       this.parent_pause();
+                       if ( this.fla ) {
+                               js_log( "Flash:Pause: " + this.fla.isPaused() );
+                               if ( this.fla['pause'] ) {
+                                       if ( ! this.fla.isPaused() ) {
+                                               js_log( 'calling plugin pause' );
+                                               this.fla.pause();
+
+                                               // restore volume and opacity
+                                               this.restorePlayer();
+                                       }
+                               }
+                       }
+               }
+       },
+       monitor : function()
+       {
+               var _this = this;
+               // date time
+               if ( !this.dateStartTime ) {
+                       var d = new Date();
+                       this.dateStartTime = d.getTime();
+
+               } else {
+                       var d = new Date();
+                       if ( !this.didDateStartTimeRestore  && this.preview_mode )
+                               this.fla.setVolume( 0 );
+
+                       if ( ( d.getTime() - this.dateStartTime ) > 6000  && !this.didDateStartTimeRestore ) {
+                               this.restorePlayer();
+                       }
+               }
+
+               var flash_state = this.fla.getStatus();
+               // update the duration from the clip if its zero or not set:
+               if ( !this.duration || this.duration == 0 ) {
+                       if ( this.fla.getClip() ) {
+                               this.duration = this.fla.getClip().fullDuration;
+                               js_log( 'set duration via clip value: ' + this.getDuration() );
+                       }
+               }
+               // update the duration ntp values:
+               this.getDuration();
+
+               if ( typeof flash_state == 'undefined' ) {
+                        var flash_state = {
+                                "time" : this.fla.getTime()
+                        };
+                       // we are not getting buffered data restore volume and opacity
+                       this.restorePlayer();
+               } else {
+                       // simplification of buffer state ... should move to support returning time rages like:
+                       // http://www.whatwg.org/specs/web-apps/current-work/#normalized-timeranges-object
+                       this.bufferedPercent = flash_state.bufferEnd / this.getDuration();
+               }
+               // set the current Time (based on timeFormat)
+               if ( this.supportsURLTimeEncoding() ) {
+                       this.currentTime = flash_state.time;
+                       // js_log('set buffer: ' + flash_state.bufferEnd + ' at time: ' + flash_state.time +' of total dur: ' + this.getDuration());
+               } else {
+                       this.currentTime = flash_state.time + this.start_offset;
+                       // stop buffering if greater than the duration:
+                       if ( flash_state.bufferEnd > this.getDuration() + 5 ) {
+                               // js_log('should stop buffering (does not seem to work)' + flash_state.bufferEnd + ' > dur: ' + this.getDuration() );
+                               this.fla.stopBuffering();
+                       }
+               }
+
+               if ( this.currentTime > npt2seconds( this.start_ntp ) && !this.startedTimedPlayback ) {
+                       var fail = false;
+                       try
+                       {
+                               this.restorePlayer();
+                       }
+                       catch ( err )
+                       {
+                               js_log( 'failed to set values' );
+                               fail = true;
+                       }
+                       if ( !fail )
+                               this.startedTimedPlayback = true;
+               }
+
+               /* to support local seeks */
+               if ( this.currentTime > 1 && this.seek_time_sec != 0 && !this.supportsURLTimeEncoding() )
+               {
+                       js_log( 'flashEmbed: _local_ Seeking to ' + this.seek_time_sec );
+                       this.fla.seek( this.seek_time_sec );
+                       this.seek_time_sec = 0;
+               }
+
+               // checks to see if we reached the end of playback:
+               if ( this.duration && this.startedTimedPlayback &&
+                       (        this.currentTime > ( npt2seconds( this.end_ntp ) + 2 )
+                               ||
+                               ( this.currentTime > ( npt2seconds( this.end_ntp ) - 1 )
+                                       && this.prevTime == this.currentTime ) )
+                       ) {
+                       js_log( 'prbally reached end of stream: ' + seconds2npt( this.currentTime ) );
+                       this.onClipDone();
+               }
+
+               // update the status and check timmer via universal parent monitor
+               this.parent_monitor();
+
+
+               this.prevTime = this.currentTime;
+               // js_log('cur perc loaded: ' + this.fla.getPercentLoaded() +' cur time : ' + (this.currentTime - npt2seconds(this.start_ntp)) +' / ' +(npt2seconds(this.end_ntp)-npt2seconds(this.start_ntp)));
+       },
+       restorePlayer:function() {
+               if ( !this.fla )
+                       this.getFLA();
+               if ( this.fla ) {
+                       js_log( 'f:do restorePlayer' );
+                       this.fla.setVolume( 90 );
+                       $f().getPlugin( 'screen' ).css( { 'opacity':'1.0' } );
+                       // set the fallback date restore flag to true:
+                       this.didDateStartTimeRestore = true;
+               }
+       },
+       // get the embed fla object
+       getFLA : function () {
+               this.fla = $f( this.pid );
+       },
+       stop : function() {
+               js_log( 'f:flashEmbed:stop' );
+               this.startedTimedPlayback = false;
+               if ( this.monitorTimerId != 0 )
+               {
+                       clearInterval( this.monitorTimerId );
+                       this.monitorTimerId = 0;
+               }
+               if ( this.fla )
+                       this.fla.unload();
+               this.parent_stop();
+       },
+       onStop: function() {
+               js_log( 'f:onStop' );
+               // stop updates:
+               if ( this.monitorTimerId != 0 )
+               {
+                       clearInterval( this.monitorTimerId );
+                       this.monitorTimerId = 0;
+               }
+       },
+       onClipDone: function() {
+               js_log( 'f:flash:onClipDone' );
+               if ( ! this.startedTimedPlayback ) {
+                       js_log( 'clip done before timed playback started .. not good. (ignoring) ' );
+                       // keep monitoring:
+                       this.monitor();
+               } else {
+                       js_log( 'clip done and ' + this.startedTimedPlayback );
+                       // stop the clip if its not stopped already:
+                       this.stop();
+                       this.setStatus( "Clip Done..." );
+                       // run the onClip done action:
+                       this.parent_onClipDone();
+               }
+       }
+};
diff --git a/js2/mwEmbed/libEmbedVideo/genericEmbed.js b/js2/mwEmbed/libEmbedVideo/genericEmbed.js
new file mode 100644 (file)
index 0000000..3e965e7
--- /dev/null
@@ -0,0 +1,17 @@
+/* the most simple implementation used for unknown application/ogg plugin */
+var genericEmbed = {
+        supports: {
+               'play_head':false,
+               'pause':false,
+               'stop':true,
+               'fullscreen':false,
+               'time_display':false,
+               'volume_control':false
+       },
+       instanceOf:'genericEmbed',
+       getEmbedHTML:function() {
+               return '<object type="application/ogg" ' +
+                       'width="' + this.width + '" height="' + this.height + '" ' +
+                       'data="' + this.getURI( this.seek_time_sec ) + '"></object>';
+       }
+};
diff --git a/js2/mwEmbed/libEmbedVideo/htmlEmbed.js b/js2/mwEmbed/libEmbedVideo/htmlEmbed.js
new file mode 100644 (file)
index 0000000..fdb515a
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * used to embed HTML as a movie clip
+ * for use with mv_playlist SMIL additions
+ * (we make assumptions about this.pc (parent clip) being available)
+ */
+var pcHtmlEmbedDefaults = {
+       'dur':4 // default duration of 4 seconds
+}
+
+var htmlEmbed = {
+       supports: {
+               'play_head':true,
+               'pause':true,
+               'fullscreen':false,
+               'time_display':true,
+               'volume_control':true,
+
+               'overlays':true,
+               'playlist_swap_loader':true // if the object supports playlist functions
+       },
+       ready_to_play:true,
+       pauseTime:0,
+       currentTime:0,
+       start_offset:0,
+       monitorTimerId:false,
+       play:function() {
+               // call the parent
+               this.parent_play();
+
+               js_log( 'f:play: htmlEmbedWrapper' );
+               var ct = new Date();
+               this.clockStartTime = ct.getTime();
+
+               // Start up monitor:
+               this.monitor();
+       },
+       stop:function() {
+               this.currentTime = 0;
+               this.pause();
+               // window.clearInterval( this.monitorTimerId );
+       },
+       pause:function() {
+               js_log( 'f:pause: htmlEmbedWrapper' );
+               var ct = new Date();
+               this.pauseTime = this.currentTime;
+               js_log( 'pause time: ' + this.pauseTime );
+               
+               window.clearInterval( this.monitorTimerId );
+       },
+       doSeek:function( perc ){
+               this.pauseTime = perc * this.getDuration();
+               this.play();
+       },
+       setCurrentTime:function( perc, callback ){
+               this.pauseTime = perc * this.getDuration();
+               if( callback )
+                       callback();
+       },
+       // Monitor just needs to keep track of time 
+       monitor:function() {
+               //js_log('html:monitor: '+ this.currentTime);           
+               var ct = new Date();
+               this.currentTime = ( ( ct.getTime() - this.clockStartTime ) / 1000 ) + this.pauseTime;
+               var ct = new Date();
+               // js_log('mvPlayList:monitor trueTime: '+ this.currentTime);
+               
+               // Once currentTime is updated call parent_monitor
+               this.parent_monitor();
+       },
+       // set up minimal media_element emulation:       
+       media_element: {
+               autoSelectSource:function() {
+                       return true;
+               },
+               selectedPlayer: {
+                       library : "html"
+               },
+               selected_source: {
+                       URLTimeEncoding:false
+               },
+               timedTextSources:function() {
+                       return false;
+               }
+       },
+       inheritEmbedObj:function() {
+               return true;
+       },
+       renderTimelineThumbnail:function( options ) {
+               js_log( "HTMLembed req w, height: " + options.width + ' ' + options.height );
+               // generate a scaled down version _that_ we can clone if nessisary
+               // add a not vissiable container to the body:
+               var do_refresh = ( typeof options['refresh'] != 'undefined' ) ? true:false;
+
+               var thumb_render_id =   this.id + '_thumb_render_' + options.height;
+               if ( $j( '#' + thumb_render_id ).length == 0  ||  do_refresh ) {
+                       // set the font scale down percentage: (kind of arbitrary)
+                       var scale_perc = options.width / this.pc.pp.width;
+                       js_log( 'scale_perc:' + options.width + ' / ' + $j( this ).width() + ' = ' + scale_perc );
+                       // min scale font percent of 70 (overflow is hidden)
+                       var font_perc  = ( Math.round( scale_perc * 100 ) < 80 ) ? 80 : Math.round( scale_perc * 100 );
+                       var thumb_class = ( typeof options['thumb_class'] != 'undefined' ) ? options['thumb_class'] : '';
+                       $j( 'body' ).append( '<div id="' + thumb_render_id + '" style="display:none">' +
+                                                                       '<div class="' + thumb_class + '" ' +
+                                                                       'style="width:' + options.width + 'px;height:' + options.height + 'px;" >' +
+                                                                                       this.getThumbnailHTML( {
+                                                                                               'width':  options.width,
+                                                                                               'height': options.height
+                                                                                       } ) +
+                                                                       '</div>' +
+                                                               '</div>'
+                                                         );
+                       // scale down the fonts:
+                       $j( '#' + thumb_render_id + ' *' ).filter( 'span,div,p,h,h1,h2,h3,h4,h5,h6' ).css( 'font-size', font_perc + '%' )
+                       
+                       // replace out links:
+                       $j( '#' + thumb_render_id + ' a' ).each( function() {
+                               $j( this ).replaceWith( "<span>" + $j( this ).html() + "</span>" );
+                       } );
+                       
+                       // scale images that have width or height:
+                       $j( '#' + thumb_render_id + ' img' ).filter( '[width]' ).each( function() {
+                               $j( this ).attr( {
+                                               'width': Math.round( $j( this ).attr( 'width' ) * scale_perc ),
+                                               'height': Math.round( $j( this ).attr( 'height' ) * scale_perc )
+                                        }
+                               );
+                       } );
+               }
+               return $j( '#' + thumb_render_id ).html();
+       },
+       // nothing to update in static html display: (return a static representation) 
+       // @@todo render out a mini text "preview"
+       updateThumbTime:function( float_time ) {
+               return ;
+       },
+       getEmbedHTML:function() {
+               js_log( 'f:html:getEmbedHTML: ' + this.id );
+               // set up the css for our parent div:            
+               $j( this ).css( {
+                       'width':this.pc.pp.width,
+                       'height':this.pc.pp.height,
+                       'overflow':"hidden"
+               } );
+               // @@todo support more smil animation layout stuff: 
+
+               // wrap output in videoPlayer_ div:
+               $j( this ).html( '<div id="videoPlayer_' + this.id + '">' + this.getThumbnailHTML() + '</div>' );
+       },
+       getThumbnailHTML:function( opt ) {
+               var out = '';
+               if ( !opt )
+                       opt = { };
+               var height = ( opt.height ) ? opt.height:this.pc.pp.height;
+               var width = ( opt.width ) ? opt.width: this.pc.pp.width;
+               js_log( '1req ' + opt.height + ' but got: ' + height );
+               if ( this.pc.type == 'image/jpeg' ||  this.pc.type == 'image/png' ) {
+                       js_log( 'should put src: ' + this.pc.src );
+                       out = '<img style="width:' + width + 'px;height:' + height + 'px" src="' + this.pc.src + '">';
+               } else {
+                       out = this.pc.wholeText;
+               }
+               // js_log('f:getThumbnailHTML: got thumb: '+out);
+               return out;
+       },
+       doThumbnailHTML:function() {
+               js_log( 'htmlEmbed:doThumbnailHTML()' );
+               this.getEmbedHTML();
+       },
+       /* since its just html display get the "embed" right away */
+       getHTML:function() {
+               js_log( 'htmlEmbed::getHTML() ' + this.id );
+               this.getEmbedHTML();
+       },
+       getDuration:function() {
+               if( !this.duration ){
+                       if( this.pc.dur ){
+                               this.duration = this.pc.dur;
+                       }else if( pcHtmlEmbedDefaults.dur ){
+                               this.duration =pcHtmlEmbedDefaults.dur ;
+                       } 
+               }  
+               return this.parent_getDuration(); 
+       },
+       updateVideoTime:function( start_ntp, end_ntp ) {
+               // since we don't really have timeline for html elements just take the delta and set it as the duration
+               this.pc.dur = npt2seconds( end_ntp ) - npt2seconds( start_ntp );
+       },
+       // gives a chance to make any nesseary external requests
+       // @@todo we can "start loading images" if we want
+       on_dom_swap:function() {
+               this.loading_external_data = false
+               this.ready_to_play = true;
+               return ;
+       }
+};
\ No newline at end of file
diff --git a/js2/mwEmbed/libEmbedVideo/javaEmbed.js b/js2/mwEmbed/libEmbedVideo/javaEmbed.js
new file mode 100644 (file)
index 0000000..e696b8e
--- /dev/null
@@ -0,0 +1,177 @@
+window.cortadoDomainLocations = {
+       'upload.wikimedia.org' : 'http://upload.wikimedia.org/jars/cortado.jar',
+       'tinyvid.tv' : 'http://tinyvid.tv/static/cortado.jar',
+       'media.tinyvid.tv' : 'http://media.tinyvid.tv/cortado.jar'
+}
+
+var javaEmbed = {
+       instanceOf:'javaEmbed',
+       iframe_src:'',
+       logged_domain_error:false,
+       supports: {
+               'play_head':true,
+               'pause':true,
+               'stop':true,
+               'fullscreen':false,
+               'time_display':true,
+               'volume_control':false
+       },
+       getEmbedHTML : function () {
+               // big delay on embed html cuz its just for status updates and ie6 is crazy. 
+               if ( this.controls )
+                       setTimeout( 'document.getElementById(\'' + this.id + '\').postEmbedJS()', 500 );
+               // set a default duration of 30 seconds: cortao should detect duration.
+               return this.wrapEmebedContainer( this.getEmbedObj() );
+       },
+       getEmbedObj:function() {
+               js_log( "java play url:" + this.getURI( this.seek_time_sec ) );
+               // get the duration
+               this.getDuration();
+               // if still unset set to an arbitrary time 60 seconds: 
+               if ( !this.duration )this.duration = 60;
+               // @@todo we should have src property in our base embed object
+               var mediaSrc = this.getSrc();
+               
+               if ( mediaSrc.indexOf( '://' ) != -1 & mw.parseUri( document.URL ).host !=  mw.parseUri( mediaSrc ).host ) {
+                       if ( window.cortadoDomainLocations[mw.parseUri( mediaSrc ).host] ) {
+                               applet_loc =  window.cortadoDomainLocations[mw.parseUri( mediaSrc ).host];
+                       } else {
+                               applet_loc  = 'http://theora.org/cortado.jar';
+                       }
+               } else {
+                       // should be identical to cortado.jar
+                       applet_loc = mv_embed_path + 'libEmbedVideo/binPlayers/cortado/cortado-ovt-stripped-0.5.0.jar';
+               }
+                       // load directly in the page..
+                       // (media must be on the same server or applet must be signed)
+                       var appplet_code = '' +
+                       '<applet id="' + this.pid + '" code="com.fluendo.player.Cortado.class" archive="' + applet_loc + '" width="' + this.width + '" height="' + this.height + '">    ' + "\n" +
+                               '<param name="url" value="' + mediaSrc + '" /> ' + "\n" +
+                               '<param name="local" value="false"/>' + "\n" +
+                               '<param name="keepaspect" value="true" />' + "\n" +
+                               '<param name="video" value="true" />' + "\n" +
+                               '<param name="showStatus" value="hide" />' + "\n" +
+                               '<param name="audio" value="true" />' + "\n" +
+                               '<param name="seekable" value="true" />' + "\n" +
+                               '<param name="duration" value="' + this.duration + '" />' + "\n" +
+                               '<param name="bufferSize" value="4096" />' + "\n" +
+                       '</applet>';
+                                                                       
+                       // Wrap it in an iframe to avoid hanging the event thread in FF 2/3 and similar
+                       // Doesn't work in MSIE or Safari/Mac or Opera 9.5
+                       if ( embedTypes.mozilla ) {
+                               var iframe = document.createElement( 'iframe' );
+                               iframe.setAttribute( 'width', params.width );
+                               iframe.setAttribute( 'height', playerHeight );
+                               iframe.setAttribute( 'scrolling', 'no' );
+                               iframe.setAttribute( 'frameborder', 0 );
+                               iframe.setAttribute( 'marginWidth', 0 );
+                               iframe.setAttribute( 'marginHeight', 0 );
+                               iframe.setAttribute( 'id', 'cframe_' + this.id )
+                               elt.appendChild( iframe );
+                               var newDoc = iframe.contentDocument;
+                               newDoc.open();
+                               newDoc.write( '<html><body>' + appplet_code + '</body></html>' );
+                               newDoc.close(); // spurious error in some versions of FF, no workaround known
+                       } else {
+                               return appplet_code;
+                       }
+       },
+       postEmbedJS:function() {
+               // reset logged domain error flag:
+               this.logged_domain_error = false;
+               // start monitor: 
+               this.monitor();
+       },
+       monitor:function() {
+               this.getJCE();
+               if ( this.isPlaying() ) {
+                       if ( this.jce && this.jce.getPlayPosition ) {
+                               try {
+                                  // java reads ogg media time.. so no need to add the start or seek offset:
+                                  // js_log(' ct: ' + this.jce.getPlayPosition() + ' ' +  this.supportsURLTimeEncoding());                                                                                                
+                                  this.currentTime = this.jce.getPlayPosition();
+                                  if ( this.jce.getPlayPosition() < 0 ) {
+                                               js_log( 'pp:' + this.jce.getPlayPosition() );
+                                               // probably reached clip end                                    
+                                               this.onClipDone();
+                                  }
+                               } catch ( e ) {
+                                  js_log( 'could not get time from jPlayer: ' + e );
+                               }
+                       }
+               }
+               // once currentTime is updated call parent_monitor 
+               this.parent_monitor();
+       },
+       /* 
+        * (local cortado seek does not seem to work very well)  
+        */
+       doSeek:function( perc ) {
+               js_log( 'java:seek:p: ' + perc + ' : '  + this.supportsURLTimeEncoding() + ' dur: ' + this.getDuration() + ' sts:' + this.seek_time_sec );
+               this.getJCE();
+               
+               if ( this.supportsURLTimeEncoding() ) {
+                       this.parent_doSeek( perc );
+                       // this.seek_time_sec = npt2seconds( this.start_ntp ) + parseFloat( perc * this.getDuration() );                                                
+                  // this.jce.setParam('url', this.getURI( this.seek_time_sec ))
+                       // this.jce.restart();
+               } else if ( this.jce ) {
+                  // do a (genneraly broken) local seek:   
+                  js_log( "cortado javascript seems to always fail ... but here we go... doSeek(" + ( perc * parseFloat( this.getDuration() ) ) );
+                  this.jce.doSeek( perc * parseFloat( this.getDuration() )  );
+               } else {
+                       this.doPlayThenSeek( perc );
+               }
+       },
+       doPlayThenSeek:function( perc ) {
+               js_log( 'doPlayThenSeek Hack' );
+               var _this = this;
+               this.play();
+               var rfsCount = 0;
+               var readyForSeek = function() {
+                       _this.getJCE();
+                       // if we have .jre ~in theory~ we can seek (but probably not) 
+                       if ( _this.jce ) {
+                               _this.doSeek( perc );
+                       } else {
+                               // try to get player for 10 seconds: 
+                               if ( rfsCount < 200 ) {
+                                       setTimeout( readyForSeek, 50 );
+                                       rfsCount++;
+                               } else {
+                                       js_log( 'error:doPlayThenSeek failed' );
+                               }
+                       }
+               }
+               readyForSeek();
+       },
+       // get java cortado embed object
+       getJCE:function() {
+               if ( embedTypes.mozilla ) {
+                       this.jce = window.frames['cframe_' + this.id ].document.getElementById( this.pid );
+               } else {
+                       this.jce = $j( '#' + this.pid ).get( 0 );
+               }
+       },
+       doThumbnailHTML:function() {
+               // empty out player html (jquery with java applets does mix) :                  
+               var pelm = document.getElementById( 'dc_' + this.id );
+               if ( pelm ) {
+                       pelm.innerHTML = '';
+               }
+               this.parent_doThumbnailHTML();
+       },
+       play:function() {
+               this.getJCE();
+               this.parent_play();
+               if ( this.jce )
+                       this.jce.doPlay();
+       },
+       pause:function() {
+               this.getJCE();
+               this.parent_pause();
+               if ( this.jce )
+                       this.jce.doPause();
+       }
+};
diff --git a/js2/mwEmbed/libEmbedVideo/kplayerEmbed.js b/js2/mwEmbed/libEmbedVideo/kplayerEmbed.js
new file mode 100644 (file)
index 0000000..d61161b
--- /dev/null
@@ -0,0 +1,140 @@
+var kplayerEmbed = {
+       instanceOf:'kplayerEmbed',
+       supports: {
+               'play_head':true,
+               'pause':true,
+               'stop':true,
+               'time_display':true,
+               'volume_control':true,
+               'overlay':false,
+               'fullscreen':false
+       },
+       getEmbedHTML : function () {
+               var embed_code =  this.getEmbedObj();
+               alert
+               var _this = this;
+               setTimeout(function(){
+                       _this.postEmbedJS();
+               }, 50);
+               js_log( "return embed html" );
+               return this.wrapEmebedContainer( embed_code );
+       },
+       getEmbedObj:function() {        
+               var player_path = mv_embed_path + 'libEmbedVideo/binPlayers/kaltura-player';
+               return '<object width="' + this.width + '" height="' + this.height + '" '+ 
+                        'data="' + player_path + '/wrapper.swf" allowfullscreen="true" '+ 
+                        'allownetworking="all" allowscriptaccess="always" '+
+                        'type="application/x-shockwave-flash" '+ 
+                        'id="' + this.pid + '" name="' + this.pid + '">'+
+                               '<param value="always" name="allowScriptAccess"/>'+
+                               '<param value="all" name="allowNetworking"/>'+
+                               '<param value="true" name="allowFullScreen"/>'+
+                               '<param value="#000000" name="bgcolor"/>'+
+                               '<param value="wrapper.swf" name="movie"/>'+
+                               '<param value="' + 
+                                       'kdpUrl=' + player_path + '/kdp.swf' +
+                                       '&ks=dummy&partner_id=0&subp_id=0' +
+                                       '&uid=0&emptyF=onKdpEmpty&readyF=onKdpReady' +
+                                       '" ' + 
+                                       'name="flashVars"/>'+
+                         '<param value="opaque" name="wmode"/>'+
+                        '</object>';           
+       },
+       postEmbedJS:function() {
+               var _this = this;
+               this.getKDP();  
+               //alert(        this.kdp );
+               if( this.kdp && this.kdp.insertMedia){
+                       // Add KDP listeners
+                       
+                       //this.kdp.addJsListener("doPlay","kdpDoOnPlay");
+                       //this.kdp.addJsListener("doStop","kdpDoOnStop");
+                       //myKdp.addJsListener("fastForward","kdpDoOnFF");
+                                               
+                       _this.bindKdpFunc( 'doPause', 'kdpPause' );
+                       _this.bindKdpFunc( 'doPlay', 'play' );
+                       _this.bindKdpFunc( 'playerPlayEnd', 'onClipDone' );
+                                               
+                       // KDP player likes an absolute url for the src:
+                       var src = mw.absoluteUrl( _this.getSrc() );
+                       js_log('play src: ' + src);
+                       // Insert the src:      
+                       this.kdp.insertMedia("-1", src, 'true' );                       
+                       this.kdp.dispatchKdpEvent('doPlay');
+                       
+                       // Start the monitor
+                       this.monitor();
+               }else{
+                       js_log('insert media: not defiend' + typeof this.kdp.insertMedia );
+                       setTimeout( function(){
+                               _this.postEmbedJS();
+                       }, 25);
+               }               
+       },      
+       /**
+       * bindKdpFunc
+       * 
+       * @param {String} flash binding name
+       * @param {String} function callback name
+       */
+       bindKdpFunc:function( bName, fName ){
+               var cbid = fName + '_cb_' + this.id.replace(' ', '_');
+               eval( 'window[ \'' + cbid +'\' ] = function(){$j(\'#' + this.id + '\').get(0).'+ fName +'();}' );
+               this.kdp.addJsListener( bName , cbid);
+       },
+       kdpPause:function(){            
+               this.parent_pause();
+       },
+       play:function() {
+               if( this.kdp && this.kdp.dispatchKdpEvent )
+                       this.kdp.dispatchKdpEvent('doPlay');
+               this.parent_play();
+       },
+       pause:function() {
+               this.kdp.dispatchKdpEvent('doPause');
+               this.parent_pause();
+       },
+       doSeek:function( prec ){
+               var _this = this;
+               if( this.kdp ){
+                       var seek_time = prec * this.getDuration(); 
+                       this.kdp.dispatchKdpEvent('doSeek',  seek_time);
+                       // Kdp is missing seek done callback
+                       setTimeout(function(){
+                               _this.seeking= false;
+                       },500);
+               }
+               this.monitor();
+       },
+       updateVolumen:function( perc ) {
+               if( this.kdp && this.kdp.dispatchKdpEvent )
+                       this.kdp.dispatchKdpEvent('volumeChange', perc);
+       },
+       monitor:function() {    
+               if( this.kdp && this.kdp.getMediaSeekTime ){
+                       this.currentTime = this.kdp.getMediaSeekTime();
+               }
+               this.parent_monitor();
+       },
+       // get the embed fla object
+       getKDP: function () {
+               this.kdp = document.getElementById( this.pid );
+       }
+}
+
+function kdpDoOnPause( player ){
+       var cat = player
+       debugger;
+}
+
+function onKdpReady( playerId ) {
+        js_log( "IN THEORY PLAYER IS READY:" + playerId);
+        /*
+        window.myKdp=get(playerId);
+        get("Player_State").innerHTML="<br>&nbsp; READY (Id=" + playerId + ")";
+        get("nowPlaying").innerHTML=(myKdp.evaluate('{entryId}'));
+        getDuration();
+        attachKdpEvents();
+        addKdpListners();
+        */
+}
diff --git a/js2/mwEmbed/libEmbedVideo/nativeEmbed.js b/js2/mwEmbed/libEmbedVideo/nativeEmbed.js
new file mode 100644 (file)
index 0000000..9bb1632
--- /dev/null
@@ -0,0 +1,300 @@
+// native embed library:
+var nativeEmbed = {
+       instanceOf:'nativeEmbed',
+       canPlayThrough:false,
+       grab_try_count:0,
+       onlyLoadFlag:false,
+       onLoadedCallback : new Array(),
+       urlAppend:'',
+       prevCurrentTime: -1,
+       supports: {
+               'play_head':true,
+               'pause':true,
+               'fullscreen':false,
+               'time_display':true,
+               'volume_control':true,
+               
+               'overlays':true,
+               'playlist_swap_loader':true // if the object supports playlist functions                
+       },
+       getEmbedHTML : function () {
+               var embed_code =  this.getEmbedObj();
+               js_log( "embed code: " + embed_code )
+               setTimeout( '$j(\'#' + this.id + '\').get(0).postEmbedJS()', 150 );
+               return this.wrapEmebedContainer( embed_code );
+       },
+       getEmbedObj:function() {
+               // we want to let mv_embed handle the controls so notice the absence of control attribute
+               // controls=false results in controls being displayed: 
+               // http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2008-August/016159.html          
+               js_log( "native play url:" + this.getSrc() + ' start_offset: ' + this.start_ntp + ' end: ' + this.end_ntp );
+               var eb = '<video ' +
+                                       'id="' + this.pid + '" ' +
+                                       'style="width:' + this.width + 'px;height:' + this.height + 'px;" ' +
+                                       'width="' + this.width + '" height="' + this.height + '" ' +
+                                          'src="' + this.getSrc() + '" ';
+                                          
+               /*if(!this.onlyLoadFlag)
+                       eb+='autoplay="true" ';*/
+                       
+               // continue with the other attr:                                                
+               eb += 'oncanplaythrough="$j(\'#' + this.id + '\').get(0).oncanplaythrough();return false;" ' +
+                         'onloadedmetadata="$j(\'#' + this.id + '\').get(0).onloadedmetadata();return false;" ' +
+                         'loadedmetadata="$j(\'#' + this.id + '\').get(0).onloadedmetadata();return false;" ' +
+                         'onprogress="$j(\'#' + this.id + '\').get(0).onprogress( event );return false;" ' +
+                         'onended="$j(\'#' + this.id + '\').get(0).onended();return false;" ' +
+                         'onseeking="$j(\'#' + this.id + '\').get(0).onseeking();" ' +
+                         'onseeked="$j(\'#' + this.id + '\').get(0).onseeked();" >' +
+                       '</video>';
+               return eb;
+       },
+       // @@todo : loading progress    
+       postEmbedJS:function() {
+               var _this = this;
+               js_log( "f:native:postEmbedJS:" );
+               this.getVID();
+               if ( typeof this.vid != 'undefined' ) {
+                       // always load the media:
+                       if ( this.onlyLoadFlag ) {
+                               this.vid.load();
+                       } else {
+                               // issue play request                           
+                               this.vid.play();
+                       }
+                       setTimeout( '$j(\'#' + this.id + '\').get(0).monitor()', 100 );
+               } else {
+                       js_log( 'could not grab vid obj trying again:' + typeof this.vid );
+                       this.grab_try_count++;
+                       if (    this.grab_count == 20 ) {
+                               js_log( ' could not get vid object after 20 tries re-run: getEmbedObj() ?' ) ;
+                       } else {
+                               setTimeout( function(){
+                                       _this.postEmbedJS();
+                               }, 200 );
+                       }
+               }
+       },
+       onseeking:function() {
+               js_log( "onseeking" );
+               this.seeking = true;
+               this.setStatus( gM( 'mwe-seeking' ) );
+       },
+       onseeked: function() {
+               js_log("onseeked");
+               this.seeking = false;
+       },
+       doSeek:function( perc ) {
+               js_log( 'native:seek:p: ' + perc + ' : '  + this.supportsURLTimeEncoding() + ' dur: ' + this.getDuration() + ' sts:' + this.seek_time_sec );
+               // @@todo check if the clip is loaded here (if so we can do a local seek)
+               if ( this.supportsURLTimeEncoding() ) {
+                       // Make sure we could not do a local seek instead:
+                       if ( perc < this.bufferedPercent && this.vid.duration && !this.didSeekJump ) {
+                               js_log( "do local seek " + perc + ' is already buffered < ' + this.bufferedPercent );
+                               this.doNativeSeek( perc );
+                       } else {
+                               // We support URLTimeEncoding call parent seek: 
+                               this.parent_doSeek( perc );
+                       }
+               } else if ( this.vid && this.vid.duration ) {
+                       // (could also check bufferedPercent > perc seek (and issue oggz_chop request or not) 
+                       this.doNativeSeek( perc );
+               } else {
+                       // try to do a play then seek: 
+                       this.doPlayThenSeek( perc )
+               }
+       },
+       doNativeSeek:function( perc ) {
+               js_log( 'native::doNativeSeek::' + perc );
+               this.seek_time_sec = 0;
+               this.vid.currentTime = perc * this.duration;
+               this.monitor();
+       },
+       doPlayThenSeek:function( perc ) {
+               js_log( 'native::doPlayThenSeek::' );
+               var _this = this;
+               this.play();
+               var rfsCount = 0;
+               var readyForSeek = function() {
+                       _this.getVID();
+                       if ( _this.vid )
+                               js_log( 'readyForSeek looking::' + _this.vid.duration );
+                       // if we have duration then we are ready to do the seek
+                       if ( _this.vid && _this.vid.duration ) {
+                               _this.doNativeSeek( perc );
+                       } else {
+                               // Try to get player for 40 seconds: 
+                               // (it would be nice if the onmetadata type callbacks where fired consistently)
+                               if ( rfsCount < 800 ) {
+                                       setTimeout( readyForSeek, 50 );
+                                       rfsCount++;
+                               } else {
+                                       js_log( 'error:doPlayThenSeek failed' );
+                               }
+                       }
+               }
+               readyForSeek();
+       },
+       setCurrentTime: function( pos, callback ) {     
+               var _this = this;
+               js_log( 'native:setCurrentTime::: ' + pos + ' :  dur: ' + _this.getDuration() );
+               this.getVID();
+               if ( !this.vid ) {
+                       this.load( function() {                         
+                               _this.doSeekedCb( pos, callback );              
+                       } );
+               } else {
+                       _this.doSeekedCb( pos, callback );              
+               }
+       },
+       doSeekedCb : function( pos, cb ){
+               var _this = this;                       
+               this.getVID();          
+               var once = function( event ) {
+                       js_log("did seek cb");
+                       cb();
+                       _this.vid.removeEventListener( 'seeked', once, false );
+               };              
+               // Assume we will get to add the Listener before the seek is done
+               _this.vid.currentTime = pos;
+               _this.vid.addEventListener( 'seeked', once, false );                                            
+       },
+       monitor : function() {
+               this.getVID(); // make sure we have .vid obj
+               if ( !this.vid ) {
+                       js_log( 'could not find video embed: ' + this.id + ' stop monitor' );
+                       this.stopMonitor();
+                       return false;
+               }
+               // don't update status if we are not the current clip 
+               // (playlist leakage?) .. should move to playlist overwrite of monitor? 
+               if ( this.pc ) {
+                       if ( this.pc.pp.cur_clip.id != this.pc.id )
+                               return true;
+               }
+               
+               // Do a seek check (on seeked does not seem fire consistently)  
+               if ( this.prevCurrentTime != -1 && this.prevCurrentTime != 0
+                       && this.prevCurrentTime < this.currentTime && this.seeking )
+                       this.seeking = false;
+                                                               
+               this.prevCurrentTime =  this.currentTime;
+               
+               // update currentTime                           
+               this.currentTime = this.vid.currentTime;
+               this.addPresTimeOffset();
+                               
+               // js_log('currentTime:' + this.currentTime);
+               // js_log('this.currentTime: ' + this.currentTime );
+               // once currentTime is updated call parent_monitor
+               this.parent_monitor();
+       },
+       getSrc:function() {
+               var src = this.parent_getSrc();
+               if (  this.urlAppend != '' )
+                       return src + ( ( src.indexOf( '?' ) == -1 ) ? '?':'&' ) + this.urlAppend;
+               return src;
+       },
+       /*
+        * native callbacks for the video tag: 
+        */
+       oncanplaythrough : function() {
+               js_log('f:oncanplaythrough');
+               this.getVID();
+               if ( ! this.paused )
+                       this.vid.play();                
+       },
+       onloadedmetadata: function() {
+               this.getVID();
+               js_log( 'f:onloadedmetadata metadata ready (update duration)' );
+               // update duration if not set (for now trust the getDuration more than this.vid.duration                
+               if ( this.getDuration() == 0  &&  ! isNaN( this.vid.duration ) ) {
+                       js_log( 'updaed duration via native video duration: ' + this.vid.duration )
+                       this.duration = this.vid.duration;
+               }
+               //fire "onLoaded" flags if set
+               while( this.onLoadedCallback.length ){
+                       func = this.onLoadedCallback.pop()
+                       if( typeof func == 'function' )
+                               func();
+               }
+       },
+       onprogress: function( e ) {
+               this.bufferedPercent =   e.loaded / e.total;
+               // js_log("onprogress:" +e.loaded + ' / ' +  (e.total) + ' = ' + this.bufferedPercent);
+       },
+       onended:function() {
+               var _this = this
+               this.getVID();
+               js_log( 'native:onended:' + this.vid.currentTime + ' real dur:' +  this.getDuration() );
+               // if we just started (under 1 second played) & duration is much longer.. don't run onClipDone just yet . (bug in firefox native sending onended event early) 
+               if ( this.vid.currentTime  < 1 && this.getDuration() > 1 && this.grab_try_count < 5 ) {
+                       js_log( 'native on ended called with time:' + this.vid.currentTime + ' of total real dur: ' +  this.getDuration() + ' attempting to reload src...' );
+                       var doRetry = function() {
+                               _this.urlAppend = 'retry_src=' + _this.grab_try_count;
+                               _this.doEmbedHTML();
+                               _this.grab_try_count++;
+                       }
+                       setTimeout( doRetry, 100 );
+               } else {
+                       js_log( 'native onClipDone done call' );
+                       this.onClipDone();
+               }
+       },
+       pause : function() {
+               this.getVID();
+               this.parent_pause(); // update interface                
+               if ( this.vid ) {
+                       this.vid.pause();
+               }
+               // stop updates: 
+               this.stopMonitor();
+       },
+       play:function() {
+               this.getVID();
+               this.parent_play(); // update interface
+               if ( this.vid ) {
+                       this.vid.play();
+                       // re-start the monitor: 
+                       this.monitor();
+               }
+       },
+       toggleMute:function() {
+               this.parent_toggleMute();
+               this.getVID();
+               if ( this.vid )
+                       this.vid.muted = this.muted;
+       },
+       updateVolumen:function( perc ) {
+               this.getVID();
+               if ( this.vid )
+                       this.vid.volume = perc;
+       },
+    getVolumen:function() {
+               this.getVID();
+               if ( this.vid )
+                       return this.vid.volume;
+       },
+       getNativeDuration:function() {
+               if ( this.vid )
+                       return this.vid.duration;
+       },
+       load:function( callback ) {
+               this.getVID();          
+               if ( !this.vid ) {
+                       // No vid loaded
+                       js_log( 'native::load() ... doEmbed' );
+                       this.onlyLoadFlag = true;
+                       this.doEmbedHTML();
+                       this.onLoadedCallback.push( callback );
+               } else {
+                       // Should not happen offten
+                       this.vid.load();
+                       if( callback)
+                               callback();
+               }
+       },
+       // get the embed vlc object 
+       getVID : function () {
+               this.vid = $j( '#' + this.pid ).get( 0 );
+       }
+};
diff --git a/js2/mwEmbed/libEmbedVideo/omtkEmbed.js b/js2/mwEmbed/libEmbedVideo/omtkEmbed.js
new file mode 100644 (file)
index 0000000..0dae32d
--- /dev/null
@@ -0,0 +1,65 @@
+var omtkEmbed = {
+       instanceOf:'omtkEmbed',
+       supports: {
+               'pause':true,
+                       'time_display':true
+       },
+       getEmbedHTML : function () {
+               var embed_code =  this.getEmbedObj();
+               // Need omtk to fire an onReady event.
+               setTimeout( '$j(\'#' + this.id + '\').get(0).postEmbedJS()', 2000 );
+               return this.wrapEmebedContainer( embed_code );
+       },
+       getEmbedObj:function() {
+               var player_path = mv_embed_path + 'libEmbedVideo/binPlayers/omtk-fx/omtkp.swf';
+               // player_path = 'omtkp.swf';
+               js_log( "player path: " + player_path );
+               return  '<object id="' + this.pid + '" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="1" height="1">' +
+                                       '<param name="movie" value="' + player_path + '" />' + "\n" +
+                                       '<!--[if !IE]>-->' + "\n" +
+                                               '<object id="' + this.pid + '_ie" type="application/x-shockwave-flash" data="' + player_path + '" width="1" height="1">' + "\n" +
+                                       '<!--<![endif]-->' + "\n" +
+                                                 '<p>Error with Display of Flash Plugin</p>' + "\n" +
+                                       '<!--[if !IE]>-->' + "\n" +
+                                               '</object>' + "\n" +
+                                       '<!--<![endif]-->' + "\n" +
+                                 '</object>';
+       },
+       postEmbedJS:function() {
+               this.getOMTK();
+               // play the url: 
+               js_log( "play: pid:" + this.pid + ' src:' + this.src );
+                               
+               this.omtk.play( this.src );
+               
+               this.monitor();
+               // $j('#omtk_player').get(0).play(this.src);
+               // $j('#'+this.pid).get(0).play( this.src );
+       },
+       pause:function() {
+               this.stop();
+       },
+       monitor:function() {
+               if ( this.omtk.getPosition )
+                       this.currentTime = this.omtk.getPosition() / 1000;
+               
+               this.parent_monitor();
+       },
+       getOMTK : function () {
+               this.omtk = $j( '#' + this.pid ).get( 0 );
+               if ( !this.omtk.play )
+                       this.omtk = $j( '#' + this.pid + '_ie' ).get( 0 );
+               
+               if ( this.omtk.play ) {
+                       // js_log('omtk obj is missing .play (probably not omtk obj)');
+               }
+       },
+}
+
+function OMTK_P_complete() {
+       js_log( 'OMTK_P_complete' );
+}
+
+function OMTK_P_metadataUpdate() {
+       js_log( 'OMTK_P_metadataUpdate' );
+}
diff --git a/js2/mwEmbed/libEmbedVideo/vlcEmbed.js b/js2/mwEmbed/libEmbedVideo/vlcEmbed.js
new file mode 100644 (file)
index 0000000..6c1fd24
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+* vlc embed based on: http://people.videolan.org/~damienf/plugin-0.8.6.html
+* javascript api: http://www.videolan.org/doc/play-howto/en/ch04.html
+*  assume version > 0.8.5.1
+*/
+var vlcEmbed = {
+       instanceOf : 'vlcEmbed',
+       supports : { 
+               'play_head':true,
+               'pause':true,
+               'stop':true,
+               'fullscreen':true,
+               'time_display':true,
+               'volume_control':true,
+               
+               'playlist_driver':true, // if the object supports playlist functions
+               'overlay':false
+       },
+       // init vars: 
+       monitorTimerId : 0,
+       prevState : 0,
+       pejs_count:0, // post embed js count
+
+       getEmbedHTML: function() {
+               // give VLC 150ms to initialize before we start playback 
+               // @@todo should be able to do this as an ready event
+               this.pejs_count = 0;
+               setTimeout( 'document.getElementById(\'' + this.id + '\').postEmbedJS()', 150 );
+                  return this.getEmbedObj();
+       },
+       getEmbedObj:function() {
+               var embed_code = '<object classid="clsid:9BE31822-FDAD-461B-AD51-BE1D1C159921" ' +
+                       'codebase="http://downloads.videolan.org/pub/videolan/vlc/latest/win32/axvlc.cab#Version=0,8,6,0" ' +
+                       'id="' + this.pid + '" events="True" height="' + this.height + '" width="' + this.width + '"' +
+                       '>' +
+                               '<param name="MRL" value="">' +
+                               '<param name="ShowDisplay" value="True">' +
+                               '<param name="AutoLoop" value="False">' +
+                               '<param name="AutoPlay" value="False">' +
+                               '<param name="Volume" value="50">' +
+                               '<param name="StartTime" value="0">' +
+                               '<embed pluginspage="http://www.videolan.org" type="application/x-vlc-plugin" ' +
+                                       'progid="VideoLAN.VLCPlugin.2" name="' + this.pid + '" ' +
+                                       'height="' + this.height + '" width="' + this.width + '" ' +
+                                       // set the style too 'just to be sure'
+                                       'style="width:' + this.width + 'px;height:' + this.height + 'px;" ' +
+                               '>' +
+                       '</object>';
+               js_log( 'embed with: ' + embed_code );
+               return embed_code;
+       },
+       
+       /*
+       * some java script to start vlc playback after the embed:
+       */
+       postEmbedJS: function() {
+               // load a pointer to the vlc into the object (this.vlc)
+               this.getVLC();
+               if ( this.vlc.log ) {
+                       // manipulate the dom object to make sure vlc has the correct size: 
+                       this.vlc.style.width = this.width;
+                       this.vlc.style.height = this.height;
+                       this.vlc.playlist.items.clear();
+                       var src = mw.absoluteUrl( this.getSrc() ) ;
+                       // @@todo if client supports seeking no need to send seek_offset to URI
+                       js_log( 'vlc play::' + src );
+                       var itemId = this.vlc.playlist.add( src );
+                       if ( itemId != -1 ) {
+                               // play
+                               this.vlc.playlist.playItem( itemId );
+                       } else {
+                               js_log( "error:cannot play at the moment !" );
+                       }
+                       // if controls enabled start up javascript interface and monitor:
+                       if ( this.controls ) {
+                               // activate the slider: scriptaculus based)
+                               // this.activateSlider();  
+                               // start doing status updates every 1/10th of a second                                                     
+                       }
+                       setTimeout( '$j(\'#' + this.id + '\').get(0).monitor()', 100 );
+               } else {
+                       js_log( 'postEmbedJS:vlc not ready' );
+                       this.pejs_count++;
+                       if ( this.pejs_count < 10 ) {
+                               setTimeout( 'document.getElementById(\'' + this.id + '\').postEmbedJS()', 100 );
+                       } else {
+                               js_log( 'vlc never ready' );
+                       }
+               }
+       },
+       // disable local seeking (while we don't know what we have avaliable)
+       doSeek : function( perc ) {
+               this.getVLC();
+               if ( this.supportsURLTimeEncoding() ) {
+                       this.parent_doSeek( perc );
+               } else if ( this.vlc ) {
+                       this.seeking = true;
+                       js_log( "do vlc http seek to: " + perc )
+                       if ( ( this.vlc.input.state == 3 ) && ( this.vlc.input.position != perc ) )
+                       {
+                               this.vlc.input.position = perc;
+                               this.setStatus( 'seeking...' );
+                       }
+               } else {
+                       this.doPlayThenSeek( perc );
+               }
+               this.parent_monitor();
+       },
+       doPlayThenSeek:function( perc ) {
+               js_log( 'doPlayThenSeekHack' );
+               var _this = this;
+               this.play();
+               var rfsCount = 0;
+               var readyForSeek = function() {
+                       _this.getVLC();
+                       var newState = _this.vlc.input.state;
+                       // if playing we are ready to do the 
+                       if ( newState == 3 ) {
+                               _this.doSeek( perc );
+                       } else {
+                               // try to get player for 10 seconds: 
+                               if ( rfsCount < 200 ) {
+                                       setTimeout( readyForSeek, 50 );
+                                       rfsCount++;
+                               } else {
+                                       js_log( 'error:doPlayThenSeek failed' );
+                               }
+                       }
+               }
+               readyForSeek();
+       },
+       playMovieAt: function ( order ) {
+               // @@todo add clips to playlist after (order) and then play
+               this.play();
+       },
+       /* 
+       * updates the status time
+       */
+       monitor: function() {
+               this.getVLC();
+               if ( !this.vlc )
+                       return ;
+               if ( this.vlc.log ) {
+                       // js_log( 'state:' + this.vlc.input.state);
+                       // js_log('time: ' + this.vlc.input.time);
+                       // js_log('pos: ' + this.vlc.input.position);
+                       if ( this.vlc.log.messages.count > 0 ) {
+                               // there is one or more messages in the log
+                               var iter = this.vlc.log.messages.iterator();
+                               while ( iter.hasNext ) {
+                                       var msg = iter.next();
+                                  var msgtype = msg.type.toString();
+                                  if ( ( msg.severity == 1 ) && ( msgtype == "input" ) )
+                                  {
+                                                  js_log( msg.message );
+                                  }
+                               }
+                               // clear the log once finished to avoid clogging
+                               this.vlc.log.messages.clear();
+                       }
+                       var newState = this.vlc.input.state;
+                       if ( this.prevState != newState ) {
+                                  if ( newState == 0 )
+                               {
+                                       // current media has stopped 
+                                       this.onStop();
+                               }
+                               else if ( newState == 1 )
+                               {
+                                       // current media is opening/connecting
+                                       this.onOpen();
+                               }
+                               else if ( newState == 2 )
+                               {
+                                       // current media is buffering data
+                                       this.onBuffer();
+                               }
+                               else if ( newState == 3 )
+                               {
+                                  // current media is now playing
+                                  this.onPlay();
+                               }
+                                  else if ( this.vlc.input.state == 4 )
+                               {
+                                       // current media is now paused
+                                       this.onPause();
+                               }
+                               this.prevState = newState;
+                       } else if ( newState == 3 ) {
+                               // current media is playing
+                               this.onPlaying();
+                       }
+               }
+               // update the status and check timmer via universal parent monitor
+               this.parent_monitor();
+       },
+       /* events */
+       onOpen: function() {
+               this.setStatus( "Opening..." );
+       },
+       onBuffer: function() {
+               this.setStatus( "Buffering..." );
+       },
+       onPlay: function() {
+               this.onPlaying();
+       },
+       liveFeedRoll: 0,
+       onPlaying: function() {
+               this.seeking = false;
+               // for now trust the duration from url over vlc input.length
+               if ( !this.getDuration() && this.vlc.input.length > 0 )
+               {
+                       // js_log('setting duration to ' + this.vlc.input.length /1000);                        
+                       this.duration = this.vlc.input.length / 1000;
+               }
+               this.currentTime = this.vlc.input.time / 1000;
+       },
+       onPause: function() {
+               this.parent_pause(); // update the inteface if paused via native control
+       },
+       onStop: function() {
+               js_log( 'vlc:onStop:' );
+               if ( !this.seeking )
+                       this.onClipDone();
+       },
+       /* js hooks/controls */
+       play : function() {
+               js_log( 'f:vlcPlay' );
+                       this.getVLC();
+                       // call the parent
+               this.parent_play();
+               if ( this.vlc ) {
+                       // plugin is already being present send play call: 
+                       // clear the message log and enable error logging
+                       if ( this.vlc.log ) {
+                               this.vlc.log.messages.clear();
+                       }
+                       if ( this.vlc.playlist )
+                               this.vlc.playlist.play();
+                               
+                       this.monitor();
+                       this.paused = false;
+               }
+       },
+       stop : function() {
+               if ( this.vlc ) {
+                       if ( typeof this.vlc != 'undefined' ) {
+                               if ( typeof this.vlc.playlist != 'undefined' ) {
+                                       // dont' stop (issues all the plugin-stop actions) 
+                                       // this.vlc.playlist.stop();
+                                       if ( this.monitorTimerId != 0 )
+                                       {
+                                               clearInterval( this.monitorTimerId );
+                                               this.monitorTimerId = 0;
+                                       }
+                               }
+                       }
+               }
+               // this.onStop();
+               // do parent stop
+               this.parent_stop();
+       },
+       pause : function() {
+               this.parent_pause(); // update the interface if paused via native control
+               if ( this.vlc ) {
+                       this.vlc.playlist.togglePause();
+               }
+       },
+       toggleMute:function() {
+               this.parent_toggleMute();
+               this.getVLC();
+               if ( this.vlc )
+                       this.vlc.audio.toggleMute();
+       },
+       // @@ Support UpDateVolumen 
+       updateVolumen:function( perc ) {
+               this.getVLC();
+               if ( this.vlc )
+                       this.vlc.audio.volume = perc * 100;
+       },
+       // @@ Get Volumen 
+       getVolumen:function() {
+               this.getVLC();
+               if ( this.vlc )
+               return this.vlc.audio.volume / 100;
+       },
+       fullscreen : function() {
+               if ( this.vlc ) {
+                       if ( this.vlc.video )
+                               this.vlc.video.toggleFullscreen();
+               }
+       },      
+       // get the embed vlc object 
+       getVLC : function() {
+               this.vlc = this.getPluginEmbed();
+       }
+};
diff --git a/js2/mwEmbed/libMwApi/NestedCallbackIframe.html b/js2/mwEmbed/libMwApi/NestedCallbackIframe.html
new file mode 100644 (file)
index 0000000..c896446
--- /dev/null
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Simple nested iframe callback page</title>
+<script type="text/javascript">
+window.onload = function (){
+       //call the nested callback in top most frame:
+       top.$mw.proxy.nested( window.location.href.split("#")[1] || false );            
+}
+</script>
+</head>
+<body>
+Nested Iframe callback
+</body>
+</html>
\ No newline at end of file
diff --git a/js2/mwEmbed/libMwApi/json2.js b/js2/mwEmbed/libMwApi/json2.js
new file mode 100644 (file)
index 0000000..c422a6e
--- /dev/null
@@ -0,0 +1,479 @@
+/*
+    http://www.JSON.org/json2.js
+    2009-09-29
+
+    Public Domain.
+
+    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+
+    See http://www.JSON.org/js.html
+
+    This file creates a global JSON object containing two methods: stringify
+    and parse.
+
+        JSON.stringify(value, replacer, space)
+            value       any JavaScript value, usually an object or array.
+
+            replacer    an optional parameter that determines how object
+                        values are stringified for objects. It can be a
+                        function or an array of strings.
+
+            space       an optional parameter that specifies the indentation
+                        of nested structures. If it is omitted, the text will
+                        be packed without extra whitespace. If it is a number,
+                        it will specify the number of spaces to indent at each
+                        level. If it is a string (such as '\t' or '&nbsp;'),
+                        it contains the characters used to indent at each level.
+
+            This method produces a JSON text from a JavaScript value.
+
+            When an object value is found, if the object contains a toJSON
+            method, its toJSON method will be called and the result will be
+            stringified. A toJSON method does not serialize: it returns the
+            value represented by the name/value pair that should be serialized,
+            or undefined if nothing should be serialized. The toJSON method
+            will be passed the key associated with the value, and this will be
+            bound to the value
+
+            For example, this would serialize Dates as ISO strings.
+
+                Date.prototype.toJSON = function (key) {
+                    function f(n) {
+                        // Format integers to have at least two digits.
+                        return n < 10 ? '0' + n : n;
+                    }
+
+                    return this.getUTCFullYear()   + '-' +
+                         f(this.getUTCMonth() + 1) + '-' +
+                         f(this.getUTCDate())      + 'T' +
+                         f(this.getUTCHours())     + ':' +
+                         f(this.getUTCMinutes())   + ':' +
+                         f(this.getUTCSeconds())   + 'Z';
+                };
+
+            You can provide an optional replacer method. It will be passed the
+            key and value of each member, with this bound to the containing
+            object. The value that is returned from your method will be
+            serialized. If your method returns undefined, then the member will
+            be excluded from the serialization.
+
+            If the replacer parameter is an array of strings, then it will be
+            used to select the members to be serialized. It filters the results
+            such that only members with keys listed in the replacer array are
+            stringified.
+
+            Values that do not have JSON representations, such as undefined or
+            functions, will not be serialized. Such values in objects will be
+            dropped; in arrays they will be replaced with null. You can use
+            a replacer function to replace those with JSON values.
+            JSON.stringify(undefined) returns undefined.
+
+            The optional space parameter produces a stringification of the
+            value that is filled with line breaks and indentation to make it
+            easier to read.
+
+            If the space parameter is a non-empty string, then that string will
+            be used for indentation. If the space parameter is a number, then
+            the indentation will be that many spaces.
+
+            Example:
+
+            text = JSON.stringify(['e', {pluribus: 'unum'}]);
+            // text is '["e",{"pluribus":"unum"}]'
+
+
+            text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
+            // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
+
+            text = JSON.stringify([new Date()], function (key, value) {
+                return this[key] instanceof Date ?
+                    'Date(' + this[key] + ')' : value;
+            });
+            // text is '["Date(---current time---)"]'
+
+
+        JSON.parse(text, reviver)
+            This method parses a JSON text to produce an object or array.
+            It can throw a SyntaxError exception.
+
+            The optional reviver parameter is a function that can filter and
+            transform the results. It receives each of the keys and values,
+            and its return value is used instead of the original value.
+            If it returns what it received, then the structure is not modified.
+            If it returns undefined then the member is deleted.
+
+            Example:
+
+            // Parse the text. Values that look like ISO date strings will
+            // be converted to Date objects.
+
+            myData = JSON.parse(text, function (key, value) {
+                var a;
+                if (typeof value === 'string') {
+                    a =
+/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
+                    if (a) {
+                        return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
+                            +a[5], +a[6]));
+                    }
+                }
+                return value;
+            });
+
+            myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
+                var d;
+                if (typeof value === 'string' &&
+                        value.slice(0, 5) === 'Date(' &&
+                        value.slice(-1) === ')') {
+                    d = new Date(value.slice(5, -1));
+                    if (d) {
+                        return d;
+                    }
+                }
+                return value;
+            });
+
+
+    This is a reference implementation. You are free to copy, modify, or
+    redistribute.
+
+    This code should be minified before deployment.
+    See http://javascript.crockford.com/jsmin.html
+
+    USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
+    NOT CONTROL.
+*/
+
+/*jslint evil: true, strict: false */
+
+/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
+    call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
+    getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
+    lastIndex, length, parse, prototype, push, replace, slice, stringify,
+    test, toJSON, toString, valueOf
+*/
+
+
+// Create a JSON object only if one does not already exist. We create the
+// methods in a closure to avoid creating global variables.
+
+if (!this.JSON) {
+    this.JSON = {};
+}
+
+(function () {
+
+    function f(n) {
+        // Format integers to have at least two digits.
+        return n < 10 ? '0' + n : n;
+    }
+
+    if (typeof Date.prototype.toJSON !== 'function') {
+
+        Date.prototype.toJSON = function (key) {
+
+            return isFinite(this.valueOf()) ?
+                   this.getUTCFullYear()   + '-' +
+                 f(this.getUTCMonth() + 1) + '-' +
+                 f(this.getUTCDate())      + 'T' +
+                 f(this.getUTCHours())     + ':' +
+                 f(this.getUTCMinutes())   + ':' +
+                 f(this.getUTCSeconds())   + 'Z' : null;
+        };
+
+        String.prototype.toJSON =
+        Number.prototype.toJSON =
+        Boolean.prototype.toJSON = function (key) {
+            return this.valueOf();
+        };
+    }
+
+    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+        escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+        gap,
+        indent,
+        meta = {    // table of character substitutions
+            '\b': '\\b',
+            '\t': '\\t',
+            '\n': '\\n',
+            '\f': '\\f',
+            '\r': '\\r',
+            '"' : '\\"',
+            '\\': '\\\\'
+        },
+        rep;
+
+
+    function quote(string) {
+
+// If the string contains no control characters, no quote characters, and no
+// backslash characters, then we can safely slap some quotes around it.
+// Otherwise we must also replace the offending characters with safe escape
+// sequences.
+
+        escapable.lastIndex = 0;
+        return escapable.test(string) ?
+            '"' + string.replace(escapable, function (a) {
+                var c = meta[a];
+                return typeof c === 'string' ? c :
+                    '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+            }) + '"' :
+            '"' + string + '"';
+    }
+
+
+    function str(key, holder) {
+
+// Produce a string from holder[key].
+
+        var i,          // The loop counter.
+            k,          // The member key.
+            v,          // The member value.
+            length,
+            mind = gap,
+            partial,
+            value = holder[key];
+
+// If the value has a toJSON method, call it to obtain a replacement value.
+
+        if (value && typeof value === 'object' &&
+                typeof value.toJSON === 'function') {
+            value = value.toJSON(key);
+        }
+
+// If we were called with a replacer function, then call the replacer to
+// obtain a replacement value.
+
+        if (typeof rep === 'function') {
+            value = rep.call(holder, key, value);
+        }
+
+// What happens next depends on the value's type.
+
+        switch (typeof value) {
+        case 'string':
+            return quote(value);
+
+        case 'number':
+
+// JSON numbers must be finite. Encode non-finite numbers as null.
+
+            return isFinite(value) ? String(value) : 'null';
+
+        case 'boolean':
+        case 'null':
+
+// If the value is a boolean or null, convert it to a string. Note:
+// typeof null does not produce 'null'. The case is included here in
+// the remote chance that this gets fixed someday.
+
+            return String(value);
+
+// If the type is 'object', we might be dealing with an object or an array or
+// null.
+
+        case 'object':
+
+// Due to a specification blunder in ECMAScript, typeof null is 'object',
+// so watch out for that case.
+
+            if (!value) {
+                return 'null';
+            }
+
+// Make an array to hold the partial results of stringifying this object value.
+
+            gap += indent;
+            partial = [];
+
+// Is the value an array?
+
+            if (Object.prototype.toString.apply(value) === '[object Array]') {
+
+// The value is an array. Stringify every element. Use null as a placeholder
+// for non-JSON values.
+
+                length = value.length;
+                for (i = 0; i < length; i += 1) {
+                    partial[i] = str(i, value) || 'null';
+                }
+
+// Join all of the elements together, separated with commas, and wrap them in
+// brackets.
+
+                v = partial.length === 0 ? '[]' :
+                    gap ? '[\n' + gap +
+                            partial.join(',\n' + gap) + '\n' +
+                                mind + ']' :
+                          '[' + partial.join(',') + ']';
+                gap = mind;
+                return v;
+            }
+
+// If the replacer is an array, use it to select the members to be stringified.
+
+            if (rep && typeof rep === 'object') {
+                length = rep.length;
+                for (i = 0; i < length; i += 1) {
+                    k = rep[i];
+                    if (typeof k === 'string') {
+                        v = str(k, value);
+                        if (v) {
+                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
+                        }
+                    }
+                }
+            } else {
+
+// Otherwise, iterate through all of the keys in the object.
+
+                for (k in value) {
+                    if (Object.hasOwnProperty.call(value, k)) {
+                        v = str(k, value);
+                        if (v) {
+                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
+                        }
+                    }
+                }
+            }
+
+// Join all of the member texts together, separated with commas,
+// and wrap them in braces.
+
+            v = partial.length === 0 ? '{}' :
+                gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
+                        mind + '}' : '{' + partial.join(',') + '}';
+            gap = mind;
+            return v;
+        }
+    }
+
+// If the JSON object does not yet have a stringify method, give it one.
+
+    if (typeof JSON.stringify !== 'function') {
+        JSON.stringify = function (value, replacer, space) {
+
+// The stringify method takes a value and an optional replacer, and an optional
+// space parameter, and returns a JSON text. The replacer can be a function
+// that can replace values, or an array of strings that will select the keys.
+// A default replacer method can be provided. Use of the space parameter can
+// produce text that is more easily readable.
+
+            var i;
+            gap = '';
+            indent = '';
+
+// If the space parameter is a number, make an indent string containing that
+// many spaces.
+
+            if (typeof space === 'number') {
+                for (i = 0; i < space; i += 1) {
+                    indent += ' ';
+                }
+
+// If the space parameter is a string, it will be used as the indent string.
+
+            } else if (typeof space === 'string') {
+                indent = space;
+            }
+
+// If there is a replacer, it must be a function or an array.
+// Otherwise, throw an error.
+
+            rep = replacer;
+            if (replacer && typeof replacer !== 'function' &&
+                    (typeof replacer !== 'object' ||
+                     typeof replacer.length !== 'number')) {
+                throw new Error('JSON.stringify');
+            }
+
+// Make a fake root object containing our value under the key of ''.
+// Return the result of stringifying the value.
+
+            return str('', {'': value});
+        };
+    }
+
+
+// If the JSON object does not yet have a parse method, give it one.
+
+    if (typeof JSON.parse !== 'function') {
+        JSON.parse = function (text, reviver) {
+
+// The parse method takes a text and an optional reviver function, and returns
+// a JavaScript value if the text is a valid JSON text.
+
+            var j;
+
+            function walk(holder, key) {
+
+// The walk method is used to recursively walk the resulting structure so
+// that modifications can be made.
+
+                var k, v, value = holder[key];
+                if (value && typeof value === 'object') {
+                    for (k in value) {
+                        if (Object.hasOwnProperty.call(value, k)) {
+                            v = walk(value, k);
+                            if (v !== undefined) {
+                                value[k] = v;
+                            } else {
+                                delete value[k];
+                            }
+                        }
+                    }
+                }
+                return reviver.call(holder, key, value);
+            }
+
+
+// Parsing happens in four stages. In the first stage, we replace certain
+// Unicode characters with escape sequences. JavaScript handles many characters
+// incorrectly, either silently deleting them, or treating them as line endings.
+
+            cx.lastIndex = 0;
+            if (cx.test(text)) {
+                text = text.replace(cx, function (a) {
+                    return '\\u' +
+                        ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+                });
+            }
+
+// In the second stage, we run the text against regular expressions that look
+// for non-JSON patterns. We are especially concerned with '()' and 'new'
+// because they can cause invocation, and '=' because it can cause mutation.
+// But just to be safe, we want to reject all unexpected forms.
+
+// We split the second stage into 4 regexp operations in order to work around
+// crippling inefficiencies in IE's and Safari's regexp engines. First we
+// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
+// replace all simple value tokens with ']' characters. Third, we delete all
+// open brackets that follow a colon or comma or that begin the text. Finally,
+// we look to see that the remaining characters are only whitespace or ']' or
+// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
+
+            if (/^[\],:{}\s]*$/.
+test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
+replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
+replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
+
+// In the third stage we use the eval function to compile the text into a
+// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
+// in JavaScript: it can begin a block or an object literal. We wrap the text
+// in parens to eliminate the ambiguity.
+
+                j = eval('(' + text + ')');
+
+// In the optional fourth stage, we recursively walk the new structure, passing
+// each name/value pair to a reviver function for possible transformation.
+
+                return typeof reviver === 'function' ?
+                    walk({'': j}, '') : j;
+            }
+
+// If the text is not JSON parseable, then a SyntaxError is thrown.
+
+            throw new SyntaxError('JSON.parse');
+        };
+    }
+}());
diff --git a/js2/mwEmbed/libMwApi/mw.proxy.js b/js2/mwEmbed/libMwApi/mw.proxy.js
new file mode 100644 (file)
index 0000000..c3cd6da
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+* 
+* Api proxy system
+*
+* Supports cross domain uploading, and api actions for a approved set of domains.
+*
+* The framework /will/ support a request approval system for per-user domain approval
+* and a central blacklisting of domains controlled by the site 
+*
+*  Flow outline below:  
+* 
+* Domain A (lets say en.wiki)  
+*      invokes add-media-wizard and wants to upload to domain B ( commons.wiki )
+* 
+*      Domain A loads iframe to domain B ? with request param to to insert from Domain A
+*              Domain B checks list of approved domains for (Domain A) & checks the user is logged in ( and if the same account name ) 
+*                      if user is not logged in 
+*                              a _link_ to Domain B to new window login page is given
+*                      if user has not approved domain and (Domain A) is not pre-approved 
+*                              a new page link is generated with a approve domain request
+*                                      if user approves domain it goes into their User:{username}/apiProxyDomains.js config
+*              If Domain A is approved we then: 
+*                      loads a "push" and "pull" iframe back to Domain A 
+                               (Domain B can change the #hash values of these children thereby proxy the data)  
+*      Domain A now gets the iframe "loaded" callback a does a initial echo to confirm cross domain proxy
+*              echo sends "echo" to push and (Domain A) js passes the echo onto the "pull"
+*      Domain A now sends api requests to the iframe "push" child and gets results from the iframe "pull"
+*              api actions happen with status updates and everything and we can reuse existing api interface code  
+* 
+* if the browser supports it we can pass msgs with the postMessage  API
+* http://ejohn.org/blog/cross-window-messaging/
+*
+* @@todo it would be nice if this supported multiple proxy targets (ie to a bright widgets future) 
+*
+*/
+
+loadGM( {
+       "mwe-setting-up-proxy" : "Setting up proxy...",
+       "mwe-re-try" : "Retry API request",
+       "mwe-re-trying" : "Retrying API request...",
+       "mwe-proxy-not-ready" : "Proxy is not configured",
+       "mwe-please-login" : "You are not <a target=\"_new\" href=\"$1\">logged in<\/a> on $2 or mwEmbed has not been enabled. Resolve the issue, and then retry the request.",
+       "mwe-remember-loging" : "General security reminder: Only login to web sites when your address bar displays that site's address."
+} );
+
+( function( $ ) {
+       /**
+        * Base API Proxy object
+        *       
+        */
+       $.proxy = { };
+       
+       /**
+        * The client setup function: 
+        */
+       $.proxy.client = function( pConf, conf ) {
+               var _this = this;
+               // Do client setup: 
+               if ( pConf.server_frame )
+                       $.proxy.server_frame = pConf.server_frame;
+               
+               if ( pConf.client_frame_path ) {
+                       $.proxy.client_frame_path = pConf.client_frame_path;
+               } else {
+                       // Set to default mwEmbed iframe path:
+                       $.proxy.client_frame_path =  wgScriptPath + '/js2/mwEmbed/libMwApi/NestedCallbackIframe.html';
+               }
+                               
+               if ( mw.parseUri( $.proxy.server_frame ).host ==  mw.parseUri( document.URL ).host ) {
+                       js_log( "Error: trying to proxy local domain? " );
+                       return false;
+               }
+               return true;
+       }
+       // Set the frameProxy Flag: 
+       var frameProxyOk = false;
+       
+       /** 
+       * doFrameProxy
+       *       Writes an iframe with a hashed value of the requestQuery
+       */
+       $.proxy.doFrameProxy = function( requestQuery ) {
+               var hashPack = {
+                       'cd': mw.parseUri( document.URL ).host,
+                       'cfp': $.proxy.client_frame_path,
+                       'req': requestQuery
+               }
+               js_log( "Do frame proxy request on src: \n" + $.proxy.server_frame + "\n" +
+                                       JSON.stringify(  requestQuery ) );
+               // we can't update src's so we have to remove and add all the time :(
+               // @@todo we should support frame msg system 
+               $j( '#frame_proxy' ).remove();
+               $j( 'body' ).append( '<iframe style="display:none" id="frame_proxy" name="frame_proxy" ' +
+                               'src="' + $.proxy.server_frame +
+                                '#' + escape( JSON.stringify( hashPack ) ) +
+                                '"></iframe>' );
+                                
+               // add an onLoad hook: 
+               $j( '#frame_proxy' ).get( 0 ).onload = function() {
+                       // add a 5 second timeout for setting up the nested child callback (after page load) 
+                       setTimeout( function() {
+                               if ( !frameProxyOk ) {
+                                       // we timmed out no api proxy (should make sure the user is "logged in")
+                                       js_log( "Error:: api proxy timeout are we logged in? mwEmbed is on?" );
+                                       $.proxy.proxyNotReadyDialog();
+                               }
+                       }, 5000 );
+               }
+       }
+       var lastApiReq = { };
+       $.proxy.proxyNotReadyDialog = function() {
+               var buttons = { };
+               buttons[ gM( 'mwe-re-try' ) ] = function() {
+                       $j.addLoaderDialog( gM( 'mwe-re-trying' ) );
+                       $.proxy.doFrameProxy( lastApiReq );
+               }
+               buttons[ gM( 'mwe-cancel' ) ] = function() {
+                       $j.closeLoaderDialog();
+               }
+               var pUri =  mw.parseUri( $.proxy.server_frame );
+               
+               // FIXME we should have a Hosted iframe once we deploy mwEmbed on the servers.
+               // A hosted iframe would be much faster since than a normal page view 
+               
+               var login_url = pUri.protocol + '://' + pUri.host;
+               login_url += pUri.path.replace( 'MediaWiki:ApiProxy', 'Special:UserLogin' );
+               
+               $j.addDialog( 
+                       gM( 'mwe-proxy-not-ready' ), 
+                       gM( 'mwe-please-login', [ login_url, pUri.host] ) +
+                               '<p style="font-size:small">' + 
+                                       gM( 'mwe-remember-loging' ) + 
+                               '</p>',
+                       buttons
+               )
+       }
+       /* 
+       * doRequest 
+       * Takes a requestQuery, executes the query and then calls the callback
+       */
+       $.proxy.doRequest = function( requestQuery, callback ) {
+               js_log( "doRequest:: " + JSON.stringify( reqObj ) );
+               lastApiReq = reqObj;
+               // setup the callback:
+               $.proxy.callback = callback;
+               // do the proxy req:
+               $.proxy.doFrameProxy( requestQuery );
+       }
+       /**
+        * The nested iframe action that passes its result back up to the top frame instance     
+        */
+       $.proxy.nested = function( hashResult ) {
+               // Close the loader if present: 
+               $j.closeLoaderDialog();
+               js_log( '$.proxy.nested callback :: ' + unescape( hashResult ) );
+               frameProxyOk = true;
+               
+               // Try to parse the hash result: 
+               try {
+                       var rObj = JSON.parse( unescape( hashResult ) );
+               } catch ( e ) {
+                       js_log( "Error could not parse hashResult" );
+               }
+               
+               // Special callback to frameProxyOk flag 
+               // (only used to test the proxy connection)   
+               if ( rObj.state == 'ok' )
+                       return ;
+               
+               // Pass the callback:
+               $.proxy.callback( rObj );
+       }
+       /**
+        * The server handles the actual proxy 
+        * it adds child frames pointing to the parent "blank" frames
+        * 
+        * This is (Domain B) in the above described setup
+        */
+       $.proxy.server = function( pConf, callback ) {
+               /* clear the body of any html */
+               $j( 'body' ).html( 'proxy setup' );
+               
+               // read the anchor action from the requesting url
+               var jmsg = unescape( mw.parseUri( document.URL ).anchor );
+               try {
+                       var aObj = JSON.parse( jmsg );
+               } catch ( e ) {
+                       js_log( "ProxyServer:: could not parse anchor" );
+               }
+               if ( !aObj.cd ) {
+                       js_log( "Error: no client domain provided " );
+                       return false;
+               }
+               
+               js_log( "Setup server on: "  + mw.parseUri( document.URL ).host +
+                       ' client from: ' + aObj.cd +
+                       ' to nested target: ' + aObj.cfp );
+               
+               // Make sure we are logged in 
+               // (its a normal mediaWiki page so all site vars should be defined)             
+               if ( !wgUserName ) {
+                       js_log( 'Error Not logged in' );
+                       return false;
+               }
+                       
+               var domain =  aObj.cd;
+               var nested_frame_src = 'http://' + aObj.cd + aObj.cfp;
+               // Check the master whitelist
+               for ( var i in pConf.master_whitelist ) {
+                       if ( domain ==  pConf.master_whitelist[ i ] ) {
+                               // Do the request:                      
+                               return doNestedProxy( aObj.req );
+                       }
+               }
+               // Check master blacklist
+               for ( var i in pConf.master_blacklist ) {
+                       if ( domain == pConf.master_blacklist ) {
+                               js_log( 'domain: ' + domain + ' is blacklisted' );
+                               return false;
+                       }
+               }
+               // FIXME grab the users whitelist for our current domain                                
+               /*var local_api = wgScriptPath + '/index' + wgScriptExtension + '?title=' +
+                               'User:' + wgUserName + '/apiProxyDomainList.js' +
+                               '&action=raw&smaxage=0&gen=js';
+               $j.get( local_api, function( data ){
+                       debugger;
+               });*/
+               
+               // if still not found: 
+               js_log( "domain " + domain + " not approved" );
+               
+               // FIXME :: offer the user the ability to "approve" requested domain save to
+               // their user/ apiProxyDomainList.js page
+
+               function doNestedProxy( reqObj ) {
+                       js_log( "doNestedProxy to: " + nested_frame_src );
+
+                       // Do a quick response to establish the proxy is working
+                       // ( before we actually run the api-request )  
+                       doNestedFrame ( 'nested_ok' , { 'state':'ok' } );
+                       
+                       var outputhash = escape( JSON.stringify( reqObj ) );
+
+                       // Add some api stuff: 
+                       reqObj[ 'format' ] = 'json';
+
+                       // Process the api request
+                       $j.post( wgScriptPath + '/api' + wgScriptExtension,
+                               reqObj,
+                               function( data ) {                                      
+                                       // Put it into the nested frame hash string: 
+                                       doNestedFrame( 'nested_push', JSON.parse( data ) );
+                               }
+                       );
+               }
+               // Add the doNestedFrame iframe: 
+               function doNestedFrame( nestname, resultObj ) {
+                       $j( '#nested_push' ).remove();
+                       // Setup the nested proxy that points back to top domain:                       
+                       $j( 'body' ).append( '<iframe id="nested_push" name="nested_push" ' +
+                               'src="' + nested_frame_src +
+                               '#' + escape( JSON.stringify( resultObj ) ) +
+                               '"></iframe>' );
+               }
+       }
+       
+} )( window.mw );
diff --git a/js2/mwEmbed/libSequencer/mvFirefoggRender.js b/js2/mwEmbed/libSequencer/mvFirefoggRender.js
new file mode 100644 (file)
index 0000000..0c00040
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Handles driving the firefogg render system 
+*/
+var mvFirefoggRender = function( options ) {
+       return this.init( options );
+};
+var default_render_options = {
+       "videoQuality" : 10,
+       "framerate"     : 30
+}
+var default_FirefoggRender_options = {
+       start_time:0,
+       // if we should save to disk (if false setup upload stuff below) 
+       save_to_disk:true
+}
+// set up the mvPlaylist object
+mvFirefoggRender.prototype = {
+       // default empty render options: 
+       renderOptions: { },
+       continue_rendering:false,
+       init:function( options ) {
+               var _this = this;
+               
+               // grab the mvFirefogg object to do basic tests
+               this.myFogg = new mvFirefogg( {
+                       'only_fogg':true
+               } );
+               
+               // check for firefogg:
+               if ( this.myFogg.getFirefogg() ) {
+                       this.enabled = true;
+               } else {
+                       this.enabled = false;
+                       return this;
+               }
+               
+               // set up local fogg pointer: 
+               this.fogg = this.myFogg.fogg;
+               
+               // setup player instance
+               this.player = $j( options.player_target ).get( 0 );
+               this.player_target = options.player_target;
+               
+               // Extend the render options with any provided details
+               if( options['render_options'] )
+                       $j.extend(this.renderOptions, options['render_options']);
+               
+               // If no height width provided use target DOM width/height
+               if( !this.renderOptions.width && !this.renderOptions.height ){
+                       this.renderOptions.width = $j(this.player_target).width();
+                       this.renderOptions.height = $j(this.player_target).height();    
+               }
+               
+               
+               // Setup the application options (with defaults) 
+               for ( var i in default_FirefoggRender_options ) {
+                       if ( options[ i ] ) {
+                               this[ i ] = options[ i ];
+                       } else {
+                               this[ i ] = default_FirefoggRender_options[i];
+                       }
+               }
+               // Should be externally controlled              
+               if ( options.target_startRender ) {
+                       $j( options.target_startRender ).click( function() {
+                               js_log( "Start render" );
+                               _this.startRender();
+                       } )
+                       this.target_startRender = options.target_startRender;
+               }
+               if ( options.target_stopRender ) {
+                       $j( options.target_stopRender ).click( function() {
+                               _this.stopRender();
+                       } )
+                       this.target_stopRender = options.target_stopRender;
+               }
+               if ( options.target_timeStatus ) {
+                       this.target_timeStatus = options.target_timeStatus;
+               }
+       },
+       startRender:function() {
+               var _this = this;
+               var t = this.start_time;
+               // get the interval from renderOptions framerate
+               var interval =  1 / this.renderOptions.framerate
+               
+               // issue a load request on the player:
+               //this.player.load();
+               
+               // init the Render
+               this.fogg.initRender(  JSON.stringify( _this.renderOptions ), 'foggRender' );
+               
+               // add audio if we had any:
+
+               // request a target (should support rendering to temp location too) 
+               //this.fogg.saveVideoAs();
+               
+               // set the continue rendering flag to true:
+               this.continue_rendering = true;
+               
+               // internal function to hanndle updates:                                
+               var doNextFrame = function() {
+                       $j( _this.target_timeStatus ).val( " on " + ( Math.round( t * 10 ) / 10 ) + " of " +
+                               ( Math.round( _this.player.getDuration() * 10 ) / 10 ) );
+                       _this.player.setCurrentTime( t, function() {                                                            
+                               //_this.fogg.addFrame( $j( _this.player_target ).attr( 'id' ) );
+                               t += interval;                          
+                               if ( t >= _this.player.getDuration() ) {
+                                       _this.doFinalRender();
+                               } else {
+                                       if ( _this.continue_rendering ) {
+                                               doNextFrame();
+                                       } else {
+                                               js_log('done with render');
+                                               // else quit:
+                                               //_this.doFinalRender();
+                                       }
+                               }
+                       } );
+               }
+               doNextFrame();
+       },
+       stopRender:function() {
+               this.continue_rendering = false;
+       },
+       doFinalRender:function() {
+               $j( this.target_timeStatus ).val( "doing final render" );
+               this.fogg.render();
+               this.updateStatus();
+       },
+       updateStatus:function() {
+               var _this = this;
+               var doUpdateStatus = function() {
+                       var rstatus = _this.fogg.renderstatus()
+                   $j( _this.target_timeStatus ).val( rstatus );
+                   if ( rstatus != 'done' && rstatus != 'rendering failed' ) {
+                       setTimeout( doUpdateStatus, 100 );
+                   } else {
+                       $j( _this.target_startRender ).attr( "disabled", false );
+                   }
+               }
+               doUpdateStatus();
+       }
+
+       
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/libSequencer/mvPlayList.js b/js2/mwEmbed/libSequencer/mvPlayList.js
new file mode 100644 (file)
index 0000000..e0d9be4
--- /dev/null
@@ -0,0 +1,2300 @@
+/* 
+ * the mvPlayList object code 
+ * only included if playlist object found
+ * 
+ * part of mwEmbed media projects see:  
+ * http://www.mediawiki.org/wiki/Media_Projects_Overview
+ * 
+ * @author: Michael Dale  mdale@wikimedia.org
+ * @license GPL2
+ */
+var mv_default_playlist_attributes = {
+       // playlist attributes :
+       "id":null,
+       "title":null,
+       "width":400,
+       "height":300,
+       "desc":'',
+       "controls":true,
+       // playlist user controlled features
+       "linkback":null,
+       "src":null,
+       "embed_link":true,
+       
+       // enable sequencer? (only display top frame no navigation or accompanying text
+       "sequencer":false
+}
+// The call back rate for animations and internal timers in ms: 33 is about 30 frames a second: 
+var MV_ANIMATION_CB_RATE = 33;
+
+// globals:
+// 10 possible colors for clips: (can be in hexadecimal)
+var mv_clip_colors = new Array( 'aqua', 'blue', 'fuchsia', 'green', 'lime', 'maroon', 'navy', 'olive', 'purple', 'red' );
+
+// The base url for requesting stream metadata 
+if ( typeof wgServer == 'undefined' ) {
+       var defaultMetaDataProvider = 'http://metavid.org/overlay/archive_browser/export_cmml?stream_name=';
+} else {
+       var defaultMetaDataProvider = wgServer + wgScript + '?title=Special:MvExportStream&feed_format=roe&stream_name=';
+}
+/*
+ * The playlist Object implements ~most~ of embedVideo but we don't inherit (other than to use the control builder)  
+ * because pretty much every function has to be changed for the playlist context
+ */
+var mvPlayList = function( element ) {
+       return this.init( element );
+};
+// set up the mvPlaylist object
+mvPlayList.prototype = {
+       instanceOf:'mvPlayList',
+       pl_duration:null,
+       update_tl_hook:null,
+       clip_ready_count:0,
+       cur_clip:null,
+       start_clip:null,
+       start_clip_src:null,
+       disp_play_head:null,
+       userSlide:false,
+       loading:true,
+       loading_external_data:true, // if we are loading external data (set to loading by default)
+       //set initial state to "paused"
+       paused:true,
+
+       activeClipList:null,
+       playlist_buffer_time: 20, // how many seconds of future clips we should buffer
+
+       interface_url:null, // the interface url 
+       tracks: { },
+       default_track:null, // the default track to add clips to.
+       // the layout for the playlist object
+       pl_layout : {
+               seq_title:.1,
+               clip_desc:.63, // displays the clip description
+               clip_aspect:1.33,  // 4/3 video aspect ratio
+               seq:.25,                                 // display clip thumbnails 
+               seq_thumb:.25,   // size for thumbnails (same as seq by default) 
+               seq_nav:0,      // for a nav bar at the base (currently disabled)
+               // some pl_layout info:
+               title_bar_height:17,
+               control_height:29
+       },
+       // embed object type support system; 
+       supports: {
+               'play_head':true,
+               'pause':true,
+               'fullscreen':false,
+               'time_display':true,
+               'volume_control':true,
+               
+               'overlays':true,
+               'playlist_swap_loader':true // if the object supports playlist functions                
+       },
+       init : function( element ) {
+               js_log( 'mvPlayList:init:' );
+               this.tracks = { };
+               this.default_track = null;
+               
+               this.activeClipList = new activeClipList();
+               // add default track & default track pointer: 
+               this.tracks[0] = new trackObj( { 'inx':0 } );
+               this.default_track = this.tracks[0];
+               
+               // get all the attributes:
+                for ( var attr in mv_default_playlist_attributes ) {
+                       if ( element.getAttribute( attr ) ) {
+                               this[attr] = element.getAttribute( attr );
+                               // js_log('attr:' + attr + ' val: ' + video_attributes[attr] +" "+'elm_val:' + element.getAttribute(attr) + "\n (set by elm)");  
+                       } else {
+                               this[attr] = mv_default_playlist_attributes[attr];
+                               // js_log('attr:' + attr + ' val: ' + video_attributes[attr] +" "+ 'elm_val:' + element.getAttribute(attr) + "\n (set by attr)");  
+                       }
+               }
+               // make sure height and width are int:
+               this.width = parseInt( this.width );
+               this.height = parseInt( this.height );
+               
+               // if style is set override width and height
+               if ( element.style.width )this.width = parseInt( element.style.width.replace( 'px', '' ) );
+               if ( element.style.height )this.height = parseInt( element.style.height.replace( 'px', '' ) );
+                               
+               // if controls=false hide the title and the controls:
+               if ( this.controls === false ) {
+                       this.pl_layout.control_height = 0;
+                       this.pl_layout.title_bar_height = 0;
+               } else {
+                       // setup the controlBuilder object:
+                       this.ctrlBuilder = new ctrlBuilder( this );
+               }
+       },
+       // the element has now been swapped into the dom: 
+       on_dom_swap:function() {
+               js_log( 'pl: dom swap' );
+               // get and load the html:
+               this.getHTML();
+       },
+       // run inheritEmbedObj on every clip (we have changed the playback method) 
+       inheritEmbedObj:function() {
+               $j.each( this.tracks, function( i, track ) {
+                       track.inheritEmbedObj();
+               } );
+       },
+       doOptionsHTML:function() {
+               // grab "options" use current clip:
+               this.cur_clip.embed.doOptionsHTML();
+       },
+       // pulls up the video editor inline
+       doEditor:function() {
+               // black out the page: 
+               // $j('body').append('<div id="ui-widget-overlay"/> <div id="modalbox" class="ui-widget ui-widget-content ui-corner-all modal_editor">' );
+               $j( 'body' ).append( '<div class="ui-widget-overlay" style="width: 100%; height: 100%px; z-index: 10;"></div>' );
+               $j( 'body' ).append( '<div id="sequencer_target" style="z-index:11;position:fixed;top:10px;left:10px;right:10px;bottom:10px;" ' +
+                               'class="ui-widget ui-widget-content ui-corner-all"></div>' );
+                                       
+               // @@todo clone the playlist (for faster startup)
+               /*
+                * var this_plObj_Clone = $j('#'+this.id).get(0).cloneNode(true);
+                *      this_plObj_Clone.sequencer=true;
+                *      this_plObj_Clone.id= 'seq_plobj';
+                *      debugger;
+                */
+                
+               // load sequencer: 
+               $j( "#sequencer_target" ).sequencer( {
+                       "mv_pl_src" : this.src
+               } );
+                                       
+       },
+       showPlayerselect:function() {
+               this.cur_clip.embed.showPlayerselect();
+       },
+       closeDisplayedHTML:function() {
+               this.cur_clip.embed.closeDisplayedHTML();
+       },
+       showDownload:function() {
+               this.cur_clip.embed.showDownload();
+       },
+       showShare:function() {
+               var embed_code = '&lt;script type=&quot;text/javascript&quot; ' +
+                                               'src=&quot;' + mv_embed_path + 'mv_embed.js&quot;&gt;&lt;/script&gt ' + "\n" +
+                                               '&lt;playlist id=&quot;' + this.id + '&quot; ';
+                                               if ( this.src ) {
+                                                       embed_code += 'src=&quot;' + this.src + '&quot; /&gt;';
+                                               } else {
+                                                       embed_code += '&gt;' + "\n";
+                                                       embed_code += escape( this.data );
+                                                       embed_code += '&lt;playlist/&gt;';
+                                               }
+               this.cur_clip.embed.showShare( embed_code );
+       },
+       timedTextSources:function() {
+               return false;
+       },
+       getPlaylist:function() {
+               js_log( "f:getPlaylist: " + this.srcType );
+               // @@todo lazy load plLib
+               eval( 'var plObj = ' + this.srcType + 'Playlist;' );
+               // import methods from the plObj to this
+               for ( var method in plObj ) {
+                       // js parent preservation for local overwritten methods
+                       if ( this[method] )this['parent_' + method] = this[method];
+                       this[method] = plObj[method];
+                       js_log( 'inherit:' + method );
+               }
+                       
+               if ( typeof this.doParse != 'function' ) {
+                       js_log( 'error: method doParse not found in plObj' + this.srcType );
+                       return false;
+               }
+                                                
+               if ( typeof this.doParse == 'function' ) {
+                                if ( this.doParse() ) {
+                                        this.doWhenParseDone();
+                                } else {
+                                        js_log( "error: failed to parse playlist" );
+                                        return false;
+                                        // error or parse needs to do ajax requests    
+                                }
+               }
+       },
+       doNativeWarningCheck:function() {
+               var clip =       this.default_track.clips[0];
+               if ( clip ) {
+                       return clip.embed.doNativeWarningCheck();
+               }
+       },
+       doWhenParseDone:function() {
+               js_log( 'f:doWhenParseDone' );
+               // do additional init for clips: 
+               var _this = this;
+               var error = false;
+               _this.clip_ready_count = 0;
+               for ( var i in this.default_track.clips ) {
+                       var clip =       this.default_track.clips[i];
+                       if ( clip.embed.load_error ) {
+                               var error = clip.embed.load_error;
+                               // break on any clip we can't playback:
+                               break;
+                       }
+                       if ( clip.embed.ready_to_play ) {
+                               _this.clip_ready_count++;
+                               continue;
+                       }
+                       // js_log('clip sources count: '+ clip.embed.media_element.sources.length);             
+                       clip.embed.on_dom_swap();
+                       if ( clip.embed.loading_external_data == false &&
+                                  clip.embed.init_with_sources_loadedDone == false ) {
+                                       clip.embed.init_with_sources_loaded();
+                       }
+               }
+               
+               // @@todo for some plugins we have to conform types of clips
+               // ie vlc can play flash _followed_by_ ogg _followed_by_ whatever 
+               //               but
+               // native ff 3.1a2 can only play ogg 
+               if ( error ) {
+                       this.load_error = error;
+                       this.is_ready = false;
+               } else if ( _this.clip_ready_count == _this.getClipCount() ) {
+                       js_log( "done init all clips: " +  _this.clip_ready_count + ' = ' + _this.getClipCount() );
+                       this.doWhenClipLoadDone();
+               } else {
+                       js_log( "only " + _this.clip_ready_count + " clips done, scheduling callback:" );
+                       if ( !mvJsLoader.load_error )   // re-issue request if no load error:
+                               setTimeout( function(){
+                                       _this.doWhenParseDone();
+                                       //debugger;
+                               }, 100 );
+               }
+       },
+       doWhenClipLoadDone:function() {
+               js_log( 'mvPlaylist:doWhenClipLoadDone' );
+               this.ready_to_play = true;
+               this.loading = false;
+               this.getHTML();
+       },
+       getDuration:function( regen ) {
+               // js_log("GET PL DURRATION for : "+ this.tracks[this.default_track_id].clips.length + 'clips');
+               if ( !regen && this.pl_duration )
+                       return this.pl_duration;
+                                               
+               var durSum = 0;
+               $j.each( this.default_track.clips, function( i, clip ) {
+                       if ( clip.embed ) {
+                               clip.dur_offset = durSum;
+                               // only calculate the solo Duration if a smil clip that could contain a transition: 
+                               if ( clip.instanceOf == 'mvSMILClip' ) {
+                                       // don't include transition time (for playlist_swap_loader compatible clips)                            
+                                       durSum += clip.getSoloDuration();
+                               } else {
+                                       durSum += clip.getDuration();
+                               }
+                       } else {
+                               js_log( "ERROR: clip " + clip.id + " not ready" );
+                       }
+               } );
+               this.pl_duration = durSum;
+               // js_log("return dur: " + this.pl_duration);
+               return this.pl_duration;
+       },
+       getTimeReq:function() {
+               // playlist does not really support time request atm ( in theory in the future we could embed playlists with temporal urls)
+               return '0:0:0/' +  seconds2npt( this.getDuration() );
+       },
+       getDataSource:function() {
+               js_log( "f:getDataSource " + this.src );
+               // determine the type / first is it m3u or xml?  
+               var pl_parent = this;
+               this.makeURLAbsolute();
+               if ( this.src != null ) {
+                       do_request( this.src, function( data ) {
+                               pl_parent.data = data;
+                               pl_parent.getSourceType();
+                       } );
+               }
+       },
+       getSrc: function(){
+               return this.src;
+       },
+       getSourceType:function() {
+               js_log( 'data type of: ' + this.src + ' = ' + typeof ( this.data ) + "\n" + this.data );
+               this.srcType = null;
+               // if not external use different detection matrix
+               if ( this.loading_external_data ) {
+                       if ( typeof this.data == 'object' ) {
+                               js_log( 'object' );
+                               // object assume xml (either xspf or rss) 
+                               plElm = this.data.getElementsByTagName( 'playlist' )[0];
+                               if ( plElm ) {
+                                       if ( plElm.getAttribute( 'xmlns' ) == 'http://xspf.org/ns/0/' ) {
+                                               this.srcType = 'xspf';
+                                       }
+                               }
+                               // check itunes style rss "items" 
+                               rssElm = this.data.getElementsByTagName( 'rss' )[0];
+                               if ( rssElm ) {
+                                       if ( rssElm.getAttribute( 'xmlns:itunes' ) == 'http://www.itunes.com/dtds/podcast-1.0.dtd' ) {
+                                               this.srcType = 'itunes';
+                                       }
+                               }
+                               // check for smil tag: 
+                               smilElm = this.data.getElementsByTagName( 'smil' )[0];
+                               if ( smilElm ) {
+                                       // don't check dtd yet.. (have not defined the smil subset) 
+                                       this.srcType = 'smil';
+                               }
+                       } else if ( typeof this.data == 'string' ) {
+                               js_log( 'String' );
+                               // look at the first line: 
+                               var first_line = this.data.substring( 0, this.data.indexOf( "\n" ) );
+                               js_log( 'first line: ' + first_line );
+                               // string
+                               if ( first_line.indexOf( '#EXTM3U' ) != -1 ) {
+                                       this.srcType = 'm3u';
+                               } else if ( first_line.indexOf( '<smil' ) != -1 ) {
+                                       // @@todo parse string
+                                       this.srcType = 'smil';
+                               }
+                       }
+               }
+               if ( this.srcType ) {
+                       js_log( 'is of type:' + this.srcType );
+                       this.getPlaylist();
+               } else {
+                       // unknown playlist type
+                       js_log( 'unknown playlist type?' );
+                       if ( this.src ) {
+                               this.innerHTML = 'error: unknown playlist type at url:<br> ' + this.src;
+                       } else {
+                               this.innerHTML = 'error: unset src or unknown inline playlist data<br>';
+                       }
+               }
+       },
+       // simple function to make a path into an absolute url if its not already
+       makeURLAbsolute:function() {
+               if ( this.src ) {
+                       if ( this.src.indexOf( '://' ) == -1 ) {
+                               var purl = mw.parseUri( document.URL );
+                               if ( this.src.charAt( 0 ) == '/' ) {
+                                       this.src = purl.protocol + '://' + purl.host + this.src;
+                               } else {
+                                       this.src = purl.protocol + '://' + purl.host + purl.directory + this.src;
+                               }
+                       }
+               }
+       },
+       // set up minimal media_element emulation:       
+       media_element: {
+               selected_source: {
+                       supports_url_time_encoding:true
+               }
+       },
+       // @@todo needs to update for multi-track clip counts
+       getClipCount:function() {
+               return this.default_track.clips.length;
+       },
+       // },
+       // takes in the playlist 
+       // inherits all the properties 
+       // swaps in the playlist object html/interface div      
+       getHTML:function() {
+               js_log( 'mvPlaylist:getHTML:  loading:' + this.loading );
+               if ( this.loading ) {
+                       $j( '#' + this.id ).html( 'loading playlist...' );
+                       if ( this.loading_external_data ) {
+                               // load the data source chain of functions (to update the innerHTML)                       
+                               this.getDataSource();
+                       } else {
+                               // detect datatype and parse directly: 
+                               this.getSourceType();
+                       }
+               } else {
+                       // check for empty playlist otherwise renderDisplay:            
+                       if ( this.default_track.getClipCount() == 0 ) {
+                               $j( this ).html( 'empty playlist' );
+                               return ;
+                       } else {
+                               this.renderDisplay();
+                       }
+               }
+       },
+       renderDisplay:function() {
+               js_log( 'mvPlaylist:renderDisplay:: track length: ' + this.default_track.getClipCount() );
+               var _this = this;
+                                                       
+               // append container and videoPlayer; 
+               $j( this ).html( '<div id="dc_' + this.id + '" style="width:' + this.width + 'px;' +
+                               'height:' + ( this.height + this.pl_layout.title_bar_height +
+                               this.pl_layout.control_height ) + 'px;position:relative;">' +
+                       '</div>' );
+               if ( this.controls == true ) {
+                       var cpos = _this.height + _this.pl_layout.title_bar_height;
+                       // give more space if not in sequence:
+                       cpos += ( this.sequencer ) ? 2:5;
+                       // append title:
+                       $j( '#dc_' + _this.id ).append(
+                               '<div style="font-size:13px;border:solid thin;width:' + this.width + 'px;" id="ptitle_' + this.id + '"></div>' +
+                               '<div class="' + this.ctrlBuilder.pClass + '" style="position:absolute;top:' + cpos + 'px">' +
+                               '<div class="ui-widget-header ui-helper-clearfix control-bar" ' +
+                                       'style="width:' + _this.width + 'px" >' +
+                                                _this.getControlsHTML() +
+                                       '</div>' +
+                               '</div>'
+                       );
+                                                               
+               // once the controls are in the DOM add hooks:          
+                       this.ctrlBuilder.addControlHooks( );
+               } else {
+                       // just append the video: 
+                       $j( '#dc_' + _this.id ).append(
+                               '<div class="' + this.ctrlBuilder.pClass + '" style="position:absolute;top:' + ( _this.height + _this.pl_layout.title_bar_height + 4 ) + 'px"></div>'
+                       );
+               }
+               this.setupClipDisplay();
+                                               
+               // update the title and status bar
+               this.updateBaseStatus();
+               this.doSmilActions();
+       },
+       setupClipDisplay:function() {
+               js_log( 'mvPlaylist:setupClipDisplay:: clip len:' + this.default_track.clips.length );
+               var _this = this;
+               $j.each( this.default_track.clips, function( i, clip ) {
+                       var cout = '<div class="clip_container cc_" id="clipDesc_' + clip.id + '" ' +
+                               'style="display:none;position:absolute;text-align: center;width:' + _this.width + 'px;' +
+                               'height:' + ( _this.height ) + 'px;' +
+                               'top:' + this.title_bar_height + 'px;left:0px;';
+                       if ( _this.controls ) {
+                               cout += 'border:solid thin black;';
+                       }
+                       cout += '"></div>';
+                       $j( '#dc_' + _this.id ).append( cout );
+                       // update the embed html:                                        
+                       clip.embed.height = _this.height;
+                       clip.embed.width = _this.width;
+                       clip.embed.play_button = false;
+                       clip.embed.controls = false;
+                       
+                       clip.embed.getHTML();// get the thubnails for everything                        
+
+                       $j( clip.embed ).css( {
+                               'position':"absolute",
+                               'top':"0px",
+                               'left':"0px"
+                       } );
+                       if ( $j( '#clipDesc_' + clip.id ).length != 0 ) {
+                               js_log( "should set: #clipDesc_" + clip.id + ' to: ' + $j( clip.embed ).html() )
+                               $j( '#clipDesc_' + clip.id ).append( clip.embed );
+                       } else {
+                               js_log( 'cound not find: clipDesc_' + clip.id );
+                       }
+               } );
+               if ( this.cur_clip )
+                       $j( '#clipDesc_' + this.cur_clip.id ).css( { display:'inline' } );
+       },
+       updateThumbPerc:function( perc ) {
+               // get float seconds:
+               var float_sec =  ( this.getDuration() * perc );
+               this.updateThumbTime( float_sec );
+       },
+       updateThumbTime:function( float_sec ) {
+               // update display & cur_clip:
+               var pl_sum_time = 0;
+               var clip_float_sec = 0;
+               // js_log('seeking clip: ');
+               for ( var i in this.default_track.clips ) {
+                       var clip = this.default_track.clips[i];
+                       if ( ( clip.getDuration() + pl_sum_time ) >= float_sec ) {
+                               if ( this.cur_clip.id != clip.id ) {
+                                       $j( '#clipDesc_' + this.cur_clip.id ).hide();
+                                       this.cur_clip = clip;
+                                       $j( '#clipDesc_' + this.cur_clip.id ).show();
+                               }
+                               break;
+                       }
+                       pl_sum_time += clip.getDuration();
+               }
+               
+               // issue thumbnail update request: (if plugin supports it will render out frame 
+               // if not then we do a call to the server to get a new jpeg thumbnail  
+               this.cur_clip.embed.updateThumbTime( float_sec - pl_sum_time );
+               
+               this.cur_clip.embed.currentTime = ( float_sec - pl_sum_time ) + this.cur_clip.embed.start_offset ;
+               this.cur_clip.embed.seek_time_sec = ( float_sec - pl_sum_time );
+               
+               // render effects ontop: (handled by doSmilActions)             
+               this.doSmilActions();
+       },
+       updateBaseStatus:function() {
+               var _this = this;
+               js_log( 'Playlist:updateBaseStatus' );
+               
+               $j( '#ptitle_' + this.id ).html( '' +
+                       '<b>' + this.title + '</b> ' +
+                       this.getClipCount() + ' clips, <i>' +
+                       seconds2npt( this.getDuration() ) + '</i>' );
+               
+               // should probably be based on if we have a provider api url
+               if ( typeof wgEnableWriteAPI != 'undefined' && !this.sequencer ) {
+                       $j( $j.btnHtml( 'edit', 'editBtn_' + this.id, 'pencil',
+                               { 'style':'position:absolute;right:0;;font-size:x-small;height:10px;margin-bottom:0;padding-bottom:7px;padding-top:0;' } )
+                       ).click( function() {
+                               _this.stop();
+                                       _this.doEditor();
+                                       return false;
+                       } ).appendTo( '#ptitle_' + this.id );
+               $j( '.editBtn_' + this.id ).btnBind();
+               }
+               // render out the dividers on the timeline: 
+               this.colorPlayHead();
+               // update status:
+               this.setStatus( '0:0:00/' + seconds2npt( this.getDuration() ) );
+       },
+       /*setStatus override (could call the jquery directly) */
+       setStatus:function( value ) {
+               $j( '#' + this.id + ' .time-disp' ).text( value );
+       },
+       setSliderValue:function( value ) {              
+               // slider is on 1000 scale: 
+               var val = parseInt( value * 1000 );
+               //js_log( 'update slider: #' + this.id + ' .play_head to ' + val );
+               $j( '#' + this.id + ' .play_head' ).slider( 'value', val );
+       },
+       getPlayHeadPos: function( prec_done ) {
+               var     _this = this;
+               if ( $j( '#mv_seeker_' + this.id ).length == 0 ) {
+                       js_log( 'no playhead so we can\'t get playhead pos' );
+                       return 0;
+               }
+               var track_len = $j( '#mv_seeker_' + this.id ).css( 'width' ).replace( /px/ , '' );
+               // assume the duration is static and present at .duration during playback
+               var clip_perc = this.cur_clip.embed.duration / this.getDuration();
+               var perc_offset = time_offset = 0;
+               for ( var i in this.default_track.clips ) {
+                       var clip = this.default_track.clips[i];
+                       if ( this.cur_clip.id == clip.id )break;
+                       perc_offset += ( clip.embed.duration /  _this.getDuration() );
+                       time_offset += clip.embed.duration;
+               }
+               // run any update time line hooks:              
+               if ( this.update_tl_hook ) {
+                       var cur_time_ms = time_offset + Math.round( this.cur_clip.embed.duration * prec_done );
+                       if ( typeof update_tl_hook == 'function' ) {
+                               this.update_tl_hook( cur_time_ms );
+                       } else {
+                               // string type passed use eval: 
+                               eval( this.update_tl_hook + '(' + cur_time_ms + ');' );
+                       }
+               }
+               
+               // handle offset hack @@todo fix so this is not needed:
+               if ( perc_offset > .66 )
+                       perc_offset += ( 8 / track_len );
+               // js_log('perc:'+ perc_offset +' c:'+ clip_perc + '*' + prec_done + ' v:'+(clip_perc*prec_done));
+               return perc_offset + ( clip_perc * prec_done );
+       },
+       // attempts to load the embed object with the playlist
+       loadEmbedPlaylist: function() {
+               // js_log('load playlist');
+       },
+       /** mannages the loading of future clips
+        * called regurally while we are playing clips
+        * 
+        * load works like so: 
+        * if the current clip is full loaded 
+        *               load clips untill buffredEndTime < playlist_buffer_time load next
+        * 
+        * this won't work so well with time range loading for smil (need to work on that)   
+        */
+       loadFutureClips:function() {
+               /*if( this.cur_clip.embed.bufferedPercent == 1){
+                       //set the buffer to the currentTime - duration 
+                       var curBuffredTime = this.cur_clip.getDuration() - this.cur_clip.embed.currentTime;             
+                       
+                       if(curBuffredTime < 0)
+                               curBuffredTime = 0;
+                               
+                       js_log( "curBuffredTime:: " + curBuffredTime );                 
+                       if( curBuffredTime <  this.playlist_buffer_time ){
+                               js_log(" we only have " + curBuffredTime + ' buffed but we need: ' +  this.playlist_buffer_time);
+                                               
+                               for(var inx = this.cur_clip.order + 1; inx < this.default_track.clips.length; inx++ ){                                  
+                                       var cClip = this.default_track.getClip( inx );                                  
+                               
+                                       //check if the clip is already loaded (add its duration)  
+                                       if( cClip.embed.bufferedPercent == 1){
+                                               curBuffredTime += cClip.embed.getDuration();
+                                       }                                                               
+                                       //check if we still have to load a resource:            
+                                       if( curBuffredTime < this.playlist_buffer_time ){
+                                               //issue the load request                                
+                                               if( cClip.embed.networkState==0 ){
+                                                       cClip.embed.load();
+                                               }
+                                               break; //check back next time
+                                       }                                                                                                                                                                
+                               }               
+                       }       
+               }*/
+       },
+       // called to play the next clip if done call onClipDone 
+       playNext: function() {
+               // advance the playhead to the next clip                        
+               var next_clip = this.getNextClip();
+               
+               if ( !next_clip ) {
+                       js_log( 'play next with no next clip... must be done:' );
+                       this.onClipDone();
+                       return ;
+               }
+               // @@todo where the plugin supports pre_loading future clips and manage that in javascript
+               // stop current clip
+               this.cur_clip.embed.stop();
+               
+               this.updateCurrentClip( next_clip );
+               //if part of a transition should continue playing where it left off     
+               this.cur_clip.embed.play();
+       },
+       onClipDone:function() {
+               js_log( "pl onClipDone" );
+               this.cur_clip.embed.stop();
+       },
+       updateCurrentClip : function( new_clip , into_perc) {
+               js_log( 'f:updateCurrentClip:' + new_clip.id );
+                       
+               // keep the active play clip in sync (stop the other clip) 
+               if ( this.cur_clip ) {
+                       // make sure we are not switching to the current
+                       if ( this.cur_clip.id == new_clip.id ) {
+                               js_log( 'trying to updateCurrentClip to same clip' );
+                               return false;
+                       }
+                       
+                       if ( !this.cur_clip.embed.isStoped() )
+                                this.cur_clip.embed.stop();
+                       this.activeClipList.remove( this.cur_clip )
+                       
+                       //hide the current clip
+                       $j( '#clipDesc_' + this.cur_clip.id ).hide();
+               }                                               
+               this.activeClipList.add( new_clip );                            
+               // do swap:             
+               this.cur_clip = new_clip;
+               $j( '#clipDesc_' + this.cur_clip.id ).show();
+               
+               // Update the playhead:
+               if( this.controls ){
+                       // Check if we have into_perc 
+                       if( into_perc ){
+                               var clip_time =  this.cur_clip.dur_offset + ( into_perc * this.cur_clip.getDuration() );
+                       }else{
+                               var clip_time =  this.cur_clip.dur_offset;
+                       }
+                               
+                       this.setSliderValue( clip_time / this.getDuration() );
+               }
+       },
+       playPrev: function() {
+               // advance the playhead to the previous clip                    
+               var prev_clip = this.getPrevClip();
+               if ( !prev_clip ) {
+                       js_log( "tried to play PrevClip with no prev Clip.. setting prev_clip to start clip" );
+                       prev_clip = this.start_clip;
+               }
+               // @@todo we could do something fancy like use playlist for sets of clips where supported. 
+               // or in cases where the player nativly supports the playlist format we can just pass it in (ie m3u or xspf)
+               if ( this.cur_clip.embed.supports['playlist_swap_loader'] ) {
+                       // where the plugin supports pre_loading future clips and manage that in javascript
+                       // pause current clip
+                       this.cur_clip.embed.pause();
+                       // do swap:
+                       this.updateCurrentClip( prev_clip );
+                       this.cur_clip.embed.play();
+               } else {
+                       js_log( 'do prev hard embed swap' );
+                       this.switchPlayingClip( prev_clip );
+               }
+       },
+       switchPlayingClip:function( new_clip ) {
+               // swap out the existing embed code for next clip embed code
+               $j( '#mv_ebct_' + this.id ).empty();
+               new_clip.embed.width = this.width;
+               new_clip.embed.height = this.height;
+               // js_log('set embed to: '+ new_clip.embed.getEmbedObj());
+               $j( '#mv_ebct_' + this.id ).html( new_clip.embed.getEmbedObj() );
+               this.cur_clip = new_clip;
+               // run js code: 
+               this.cur_clip.embed.pe_postEmbedJS();
+       },
+       // playlist play
+       play: function() {
+               var _this = this;
+               js_log( 'pl play' );
+               // hide the playlist play button: 
+               $j( this.id + ' .play-btn-large' ).hide();
+               
+               // un-pause if paused:
+               if ( this.paused )
+                       this.paused = false;
+               
+               // update the control:           
+               this.start_clip = this.cur_clip;
+               this.start_clip_src = this.cur_clip.src;
+                
+               if ( this.cur_clip.embed.supports['playlist_swap_loader'] ) {
+                       // set the cur_clip to active
+                       this.activeClipList.add( this.cur_clip );
+                       
+                       // navtive support:
+                       // * pre-loads clips
+                       // * mv_playlist smil extension, manages transitions animations overlays etc.                    
+                       // js_log('clip obj supports playlist swap_loader (ie playlist controlled playback)');                                                  
+                       // @@todo pre-load each clip:
+                       // play all active clips (playlist_swap_loader can have more than one clip active)               
+                       $j.each( this.activeClipList.getClipList(), function( inx, clip ) {
+                               clip.embed.play();
+                       } );
+               } else if ( this.cur_clip.embed.supports['playlist_driver'] ) {
+                       // js_log('playlist_driver');
+                       // embedObject is feed the playlist info directly and manages next/prev
+                       this.cur_clip.embed.playMovieAt( this.cur_clip.order );
+               } else {
+                       // not much playlist support just play the first clip:
+                       // js_log('basic play');
+                       // play cur_clip                        
+                       this.cur_clip.embed.play();
+               }
+               // start up the playlist monitor                        
+               this.monitor();
+       },
+       /*
+        * the load function loads all the clips in order 
+        */
+       load:function() {
+               // do nothing right now)
+               alert('load pl');               
+       },
+       toggleMute:function() {
+               this.cur_clip.embed.toggleMute();
+       },
+       pause:function() {
+               // js_log('f:pause: playlist');
+               var ct = new Date();
+               this.pauseTime = this.currentTime;
+               this.paused = true;
+               // js_log('pause time: '+ this.pauseTime + ' call embed pause:');
+
+               // pause all the active clips:
+               $j.each( this.activeClipList.getClipList(), function( inx, clip ) {
+                       clip.embed.pause();
+               } );
+       },
+       // @@todo mute across all child clips: 
+       toggleMute:function() {
+               var this_id = ( this.pc != null ) ? this.pc.pp.id:this.id;
+               if ( this.muted ) {
+                       this.muted = false;
+                       $j( '#volume_control_' + this_id + ' span' ).removeClass( 'ui-icon-volume-off' ).addClass( 'ui-icon-volume-on' );
+                       $j( '#volume_bar_' + this_id ).slider( 'value', 100 );
+                       this.updateVolumen( 1 );
+               } else {
+                       this.muted = true;
+                       $j( '#volume_control_' + this_id + ' span' ).removeClass( 'ui-icon-volume-on' ).addClass( 'ui-icon-volume-off' );
+                       $j( '#volume_bar_' + this_id ).slider( 'value', 0 );
+                       this.updateVolumen( 0 );
+               }
+               js_log( 'f:toggleMute::' + this.muted );
+       },
+       updateVolumen:function( perc ) {
+               js_log( 'update volume not supported with current playback type' );
+       },
+       fullscreen:function() {
+               this.cur_clip.embed.fullscreen();
+       },
+       // playlist stops playback for the current clip (and resets state for start clips)
+       stop:function() {
+               var _this = this;
+               /*js_log("pl stop:"+ this.start_clip.id + ' c:'+this.cur_clip.id);
+               //if start clip 
+               if(this.start_clip.id!=this.cur_clip.id){
+                       //restore clipDesc visibility & hide desc for start clip: 
+                       $j('#clipDesc_'+this.start_clip.id).html('');
+                       this.start_clip.getDetail();
+                       $j('#clipDesc_'+this.start_clip.id).css({display:'none'});
+                       this.start_clip.setBaseEmbedDim(this.start_clip.embed);
+                       //equivalent of base stop
+                       $j('#'+this.start_clip.embed.id).html(this.start_clip.embed.getThumbnailHTML());
+                       this.start_clip.embed.thumbnail_disp=true;
+               }
+               //empty the play-back container
+               $j('#mv_ebct_'+this.id).empty();*/
+               
+               // stop all the clips: monitor: 
+               window.clearInterval( this.smil_monitorTimerId );
+               /*for (var i=0;i<this.clips.length;i++){
+                       var clip = this.clips[i];
+                       if(clip){
+                               clip.embed.stop();
+                               $j('#clipDesc_'+clip.id).hide();
+                       }
+               }*/
+               // stop, hide and remove all active clips:
+               $j.each( this.activeClipList.getClipList(), function( inx, clip ) {
+                       if ( clip ) {
+                               clip.embed.stop();
+                               $j( '#clipDesc_' + clip.id ).hide();
+                               _this.activeClipList.remove( clip );
+                       }
+               } );
+               // set the current clip to the first clip: 
+               if ( this.start_clip ) {
+                       this.cur_clip = this.start_clip;
+                       // display the first clip thumb: 
+                       this.cur_clip.embed.stop();
+                       // hide other clips:
+                       $j( '#' + this.id + ' .clip_container' ).hide();
+                       // show the first/current clip:
+                       $j( '#clipDesc_' + this.cur_clip.id ).show();
+               }
+               // reset the currentTime: 
+               this.currentTime = 0;
+               // rest the sldier
+               this.setSliderValue( 0 );
+               // FIXME still some issues with "stoping" and reseting the playlist     
+       },
+       doSeek:function( v ) {
+               js_log( 'pl:doSeek:' + v + ' sts:' + this.seek_time_sec );
+               var _this = this;
+               
+               var time = v * this.getDuration()
+               _this.currentTime = time;
+               var relative_perc = _this.updateClipByTime();
+               
+               // Update the clip relative seek_time_sec
+               _this.cur_clip.embed.doSeek( relative_perc );
+               _this.monitor();
+               
+               return '';
+       },
+       setCurrentTime: function( time, callback ) {
+               js_log( 'pl:setCurrentTime:' + time );
+               var _this = this;
+               _this.currentTime = time;
+               
+               var pl_perc =  time / this.getDuration();
+               var relative_perc = _this.updateClipByTime();   
+               var clip_time = relative_perc * _this.cur_clip.embed.getDuration();             
+               _this.cur_clip.embed.setCurrentTime( clip_time, function() {
+                       //update the smil actions now that the seek is done 
+                       _this.doSmilActions();
+                       //say we are "ready"
+                       if ( callback )
+                               callback();
+               } );                                    
+       },
+       /*
+       * updateClipByTime::
+       *
+       * @returns the relative offsets of the current clip (given the playlist time) 
+       */
+       updateClipByTime: function(){
+               var _this = this;
+               var prevClip = null;
+               //set the current percent done: 
+               var pt = this.currentTime / _this.getDuration();
+               // jump to the clip in the current percent. 
+               var perc_offset = 0;
+               var next_perc_offset = 0;
+               for ( var i in _this.default_track.clips ) {
+                       var clip = _this.default_track.clips[i];
+                       next_perc_offset += ( clip.getDuration() /  _this.getDuration() ) ;
+                       // js_log('on ' + clip.getDuration() +' next_perc_offset:'+ next_perc_offset);
+                       if ( next_perc_offset > pt ) {           
+                               // js_log('seek:'+ pt +' - '+perc_offset + ') /  (' + next_perc_offset +' - '+ perc_offset);
+                               var relative_perc =  ( pt - perc_offset ) /  ( next_perc_offset - perc_offset );
+                               // update the current clip:                                                              
+                               _this.updateCurrentClip( clip, relative_perc );
+                               return relative_perc;
+                       }
+                       perc_offset = next_perc_offset;
+               }
+               return 0;
+       },
+       // gets playlist controls large control height for sporting 
+       // next prev button and more status display
+       getControlsHTML:function() {
+               // get controls from current clip  (add some playlist specific controls:                                        
+               return this.ctrlBuilder.getControls( this );
+       },
+       // ads colors/dividers between tracks
+       colorPlayHead: function() {
+               var _this = this;
+               
+               if ( !_this.mv_seeker_width )
+                       _this.mv_seeker_width = $j( '#' + _this.id + ' .play_head' ).width();
+       
+               if ( !_this.track_len )
+                       _this.track_len = $j( '#' + _this.id + ' .play_head' ).width();
+                       
+               // total duration:              
+               var pl_duration = _this.getDuration();
+               
+               var cur_pixle = 0;
+               // set up _this
+
+               // js_log("do play head total dur: "+pl_duration );
+               $j.each( this.default_track.clips, function( i, clip ) {
+                       // (use getSoloDuration to not include transitions and such)     
+                       var perc = ( clip.getSoloDuration() / pl_duration );
+                       var pwidth = Math.round( perc * _this.track_len );
+                       // js_log('pstatus:c:'+ clip.getDuration() + ' of '+ pl_duration+' %:' + perc + ' width: '+ pwidth + ' of total: ' + _this.track_len);
+                       // var pwidth = Math.round( perc  * _this.track_len - (_this.mv_seeker_width*perc) );
+
+                       // add the buffer child indicator:                                               
+                       var barHtml = '<div id="cl_status_' + clip.embed.id + '" class="cl_status"  style="' +
+                                       'left:' + cur_pixle + 'px;' +
+                                       'width:' + pwidth + 'px;';
+                       // set left or right border based on track pos 
+                       barHtml += ( i == _this.default_track.getClipCount() - 1 ) ?
+                                'border-left:solid thin black;':
+                                'border-right:solid thin black;';
+                       barHtml += 'filter:alpha(opacity=40);' +
+                                       '-moz-opacity:.40;">';
+                       
+                       barHtml += _this.ctrlBuilder.getMvBufferHtml();
+                       
+                       barHtml += '</div>';
+                       
+                       // background:#DDD +clip.getColor();
+
+                       $j( '#' + _this.id + ' .play_head' ).append( barHtml );
+                                                                                                                                                                                                               
+                       // js_log('offset:' + cur_pixle +' width:'+pwidth+' add clip'+ clip.id + ' is '+clip.embed.getDuration() +' = ' + perc +' of ' + _this.track_len);
+                       cur_pixle += pwidth;
+               } );
+       },
+       // @@todo currently not really in use
+       setUpHover:function() {
+               js_log( 'Setup Hover' );
+               // set up hover for prev,next 
+               var th = 50;
+               var tw = th * this.pl_layout.clip_aspect;
+               var _this = this;
+               $j( '#mv_prev_link_' + _this.id + ',#mv_next_link_' + _this.id ).hover( function() {
+                         var clip = ( this.id == 'mv_prev_link_' + _this.id ) ? _this.getPrevClip() : _this.getNextClip();
+                         if ( !clip )
+                                 return js_log( 'missing clip for Hover' );
+                         // get the position of #mv_perv|next_link:
+                         var loc = getAbsolutePos( this.id );
+                         // js_log('Hover: x:'+loc.x + ' y:' + loc.y + ' :'+clip.img);
+                          $j( "body" ).append( '<div id="mv_Athub" style="position:absolute;' +
+                                  'top:' + loc.y + 'px;left:' + loc.x + 'px;width:' + tw + 'px;height:' + th + 'px;">' +
+                               '<img style="border:solid 2px ' + clip.getColor() + ';position:absolute;top:0px;left:0px;" width="' + tw + '" height="' + th + '" src="' + clip.img + '"/>' +
+                       '</div>' );
+         }, function() {
+                         $j( '#mv_Athub' ).remove();
+         } );
+       },
+       // @@todo we need to move a lot of this track logic like "cur_clip" to the track Obj
+       // and have the playlist just drive the tracks. 
+       getNextClip:function( track ) {
+               if ( !track )
+                       track = this.default_track;
+               var tc = parseInt( this.cur_clip.order ) + 1;
+               var cat = track;
+               if ( tc > track.getClipCount() - 1 )
+                       return false; // out of range
+
+               return   track.getClip( tc );
+       },
+       getPrevClip:function( track ) {
+               if ( !track )
+                       track = this.default_track;
+               var tc = parseInt( this.cur_clip.order ) - 1;
+               if ( tc < 0 )
+                       return false;
+               return track.getClip( tc );
+       },
+       /* 
+        * generic add Clip to ~default~ track
+        */
+       addCliptoTrack: function( clipObj, pos ) {
+               if ( typeof clipObj['track_id'] == 'undefined' ) {
+                       var track = this.default_track;
+               } else {
+                       var track = this.tracks[ clipObj.track_id ]
+               }
+               js_log( 'add clip:' + clipObj.id + ' to track: at:' + pos );
+               // set the first clip to current (maybe deprecated ) 
+               if ( clipObj.order == 0 ) {
+                       if ( !this.cur_clip )this.cur_clip = clipObj;
+               }
+               track.addClip( clipObj, pos );
+       },
+       swapClipDesc: function( req_clipID, callback ) {
+               // hide all but the requested
+               var _this = this;
+               js_log( 'r:' + req_clipID + ' cur:' + _this.id );
+               if ( req_clipID == _this.cur_clip.id ) {
+                       js_log( 'no swap to same clip' );
+               } else {
+                       // fade out clips
+                       req_clip = null;
+                       $j.each( this.default_track.clips, function( i, clip ) {
+                               if ( clip.id != req_clipID ) {
+                                       // fade out if display!=none already
+                                       if ( $j( '#clipDesc_' + clip.id ).css( 'display' ) != 'none' ) {
+                                               $j( '#clipDesc_' + clip.id ).fadeOut( "slow" );
+                                       }
+                               } else {
+                                       req_clip = clip;
+                               }
+                       } );
+                       // fade in requested clip *and set req_clip to current
+                       $j( '#clipDesc_' + req_clipID ).fadeIn( "slow", function() {
+                                       _this.cur_clip = req_clip;
+                                       if ( callback )
+                                               callback();
+                       } );
+               }
+       },
+       // this is pretty outdated:      
+       getPLControls: function() {
+               js_log( 'getPL cont' );
+               return   '<a id="mv_prev_link_' + this.id + '" title="Previus Clip" onclick="document.getElementById(\'' + this.id + '\').playPrev();return false;" href="#">' +
+                                       getTransparentPng( { id:'mv_prev_btn_' + this.id, style:'float:left', width:'27', height:'27', border:"0",
+                                               src:mv_skin_img_path + 'vid_prev_sm.png' } ) +
+                               '</a>' +
+                               '<a id="mv_next_link_' + this.id + '"  title="Next Clip"  onclick="document.getElementById(\'' + this.id + '\').playNext();return false;" href="#">' +
+                                       getTransparentPng( { id:'mv_next_btn_' + this.id, style:'float:left', width:'27', height:'27', border:"0",
+                                               src:mv_skin_img_path + 'vid_next_sm.png' } ) +
+                               '</a>';
+       },
+       run_transition: function( clip_inx, trans_type ) {
+               if ( typeof this.default_track.clips[ clip_inx ][ trans_type ] == 'undefined' )
+                       clearInterval( this.default_track.clips[ clip_inx ].timerId );
+               else
+                       this.default_track.clips[ clip_inx ][ trans_type ].run_transition();
+       },
+       playerPixelWidth : function()
+       {
+               var player = $j( '#dc_' + this.id ).get( 0 );
+               if ( typeof player != 'undefined' && player['offsetWidth'] )
+                       return player.offsetWidth;
+               else
+                       return parseInt( this.width );
+       },
+       playerPixelHeight : function()
+       {
+               var player = $j( '#dc_' + this.id ).get( 0 );
+               if ( typeof player != 'undefined' && player['offsetHeight'] )
+                       return player.offsetHeight;
+               else
+                       return parseInt( this.height );
+       }
+}
+
+/* Object Stubs: 
+ * 
+ * @videoTrack ... stores clips and layer info
+ * 
+ * @clip... each clip segment is a clip object. 
+ * */
+var mvClip = function( o ) {
+       if ( o )
+               this.init( o );
+       return this;
+};
+// set up the mvPlaylist object
+mvClip.prototype = {
+       id:null, // clip id
+       pp:null, // parent playlist
+       order:null, // the order/array key for the current clip
+       src:null,
+       info:null,
+       title:null,
+       mvclip:null,
+       type:null,
+       img:null,
+       duration:null,
+       loading:false,
+       isAnimating:false,
+       init:function( o ) {
+               // init object including pointer to parent
+               for ( var i in o ) {
+                       this[i] = o[i];
+               };
+               js_log( 'id is: ' + this.id );
+       },
+       // setup the embed object:
+       setUpEmbedObj:function() {
+               js_log( 'mvClip:setUpEmbedObj()' );
+               
+               this.embed = null;
+               // js_log('setup embed for clip '+ this.id + ':id is a function?'); 
+               // set up the pl_mv_embed object:
+               var init_pl_embed = { id:'e_' + this.id,
+                       pc:this, // parent clip
+                       src:this.src
+               };
+
+               this.setBaseEmbedDim( init_pl_embed );
+
+               
+               // if in sequence mode hide controls / embed links               
+               //                      init_pl_embed.play_button=false;
+               // init_pl_embed.controls=true; 
+               // if(this.pp.sequencer=='true'){
+               init_pl_embed.embed_link = null;
+               init_pl_embed.linkback = null;
+               
+               if( this.durationHint )
+                       init_pl_embed.durationHint =  this.durationHint;
+               
+               if ( this.poster )init_pl_embed['thumbnail'] = this.poster;
+               
+               if ( this.type )init_pl_embed['type'] = this.type;
+                               
+               this.embed = new PlMvEmbed( init_pl_embed );
+                                       
+               // js_log('media Duration:' + this.embed.getDuration() );
+               // js_log('media element:'+ this.embed.media_element.length);
+               // js_log('type of embed:' + typeof(this.embed) + ' seq:' + this.pp.sequencer+' pb:'+ this.embed.play_button);          
+       },
+       doAdjust:function( side, delta ) {
+               js_log( "f:doAdjust: " + side + ' , ' +  delta );
+               if ( this.embed ) {
+                       if ( side == 'start' ) {
+                               var start_offset = parseInt( this.embed.start_offset ) + parseInt( delta * -1 );
+                               this.embed.updateVideoTime( seconds2npt( start_offset ), seconds2npt ( this.embed.start_offset + this.embed.getDuration() ) );
+                       } else if ( side == 'end' ) {
+                               var end_offset = parseInt( this.embed.start_offset ) + parseInt( this.embed.getDuration() ) + parseInt( delta );
+                               this.embed.updateVideoTime( seconds2npt( this.embed.start_offset ), seconds2npt( end_offset ) );
+                       }
+                       // update everything: 
+                       this.pp.refresh();
+                       /*var base_src = this.src.substr(0,this.src.indexOf('?'));
+                       js_log("delta:"+ delta);
+                       if(side=='start'){
+                               //since we adjust start invert the delta: 
+                               var start_offset =parseInt(this.embed.start_offset/1000)+parseInt(delta*-1);
+                               this.src = base_src +'?t='+ seconds2npt(start_offset) +'/'+ this.embed.end_ntp;                                                 
+                       }else if(side=='end'){
+                               //put back into seconds for adjustment: 
+                               var end_offset = parseInt(this.embed.start_offset/1000) + parseInt(this.embed.duration/1000) + parseInt(delta);
+                               this.src = base_src +'?t='+ this.embed.start_ntp +'/'+ seconds2npt(end_offset);
+                       }                               
+                       this.embed.updateVideoTime( this.src );
+                       //update values
+                       this.duration = this.embed.getDuration();
+                       this.pp.pl_duration=null;
+                       //update playlist stuff:
+                       this.pp.updateTitle();*/
+               }
+       },
+       getDuration:function() {
+               if ( !this.embed )this.setUpEmbedObj();
+               return this.embed.getDuration();
+       },
+       setBaseEmbedDim:function( o ) {
+               if ( !o )o = this;
+               // o.height=Math.round(pl_layout.clip_desc*this.pp.height)-2;//give it some padding:
+               // o.width=Math.round(o.height*pl_layout.clip_aspect)-2;
+               o.height =      this.pp.height;
+               o.width =       this.pp.width;
+       },
+       // output the detail view:
+       // @@todo
+       /*getDetail:function(){
+               //js_log('get detail:' + this.pp.title);
+               var th=Math.round( this.pl_layout.clip_desc * this.pp.height ); 
+               var tw=Math.round( th * this.pl_layout.clip_aspect );           
+               
+               var twDesc = (this.pp.width-tw)-2;
+               
+               if(this.title==null)
+                       this.title='clip ' + this.order + ' ' +this.pp.title;
+               if(this.desc==null)
+                       this.desc=this.pp.desc;
+               //update the embed html: 
+               this.embed.getHTML();
+                                       
+               $j(this.embed).css({ 'position':"absolute",'top':"0px", 'left':"0px"});
+               
+               //js_log('append child to:#clipDesc_'+this.id);
+               if($j('#clipDesc_'+this.id).get(0)){
+                       $j('#clipDesc_'+this.id).get(0).appendChild(this.embed);
+                       
+                       $j('#clipDesc_'+this.id).append(''+
+                       '<div id="pl_desc_txt_'+this.id+'" class="pl_desc" style="position:absolute;left:'+(tw+2)+'px;width:'+twDesc+'px;height:'+th+'px;overflow:auto;">'+
+                                       '<b>'+this.title+'</b><br>'+                    
+                                       this.desc + '<br>' + 
+                                       '<b>clip length:</b> '+ seconds2npt( this.embed.getDuration() ); 
+                       '</div>');              
+               }
+       },*/
+       getTitle:function() {
+               if ( typeof this.title == 'string' )
+                       return this.title
+                       
+               return 'untitled clip ' + this.order;
+       },
+       getClipImg:function( start_offset, size ) {
+               js_log( 'f:getClipImg ' + start_offset + ' s:' + size );
+               if ( !this.img ) {
+                       return mv_default_thumb_url;
+               } else {
+                       if ( !size && !start_offset ) {
+                               return this.img;
+                       } else {
+                               // if a metavid image (has request parameters) use size and time args
+                               if ( this.img.indexOf( '?' ) != -1 ) {
+                                       js_log( 'get with offset: ' + start_offset );
+                                       var time = seconds2npt( start_offset + ( this.embed.start_offset / 1000 ) );
+                                       js_log( "time is: " + time );
+                                       this.img = this.img.replace( /t\=[^&]*/gi, "t=" + time );
+                                       if ( this.img.indexOf( '&size=' ) != -1 ) {
+                                               this.img = this.img.replace( /size=[^&]*/gi, "size=" + size );
+                                       } else {
+                                               this.img += '&size=' + size;
+                                       }
+                               }
+                               return this.img;
+                       }
+               }
+       },
+       getColor: function() {
+               // js_log('get color:'+ num +' : '+  num.toString().substr(num.length-1, 1) + ' : '+colors[ num.toString().substr(num.length-1, 1)] );
+               var num = this.id.substr( this.id.length - 1, 1 );
+               if ( !isNaN( num ) ) {
+                       num = num.charCodeAt( 0 );
+               }
+               if ( num >= 10 )num = num % 10;
+               return mv_clip_colors[num];
+       }
+}
+/* mv_embed extensions for playlists */
+var PlMvEmbed = function( vid_init ) {
+       // js_log('PlMvEmbed: '+ vid_init.id);  
+       // create the div container
+       var ve = document.createElement( 'div' );
+       // extend ve with all this 
+       this.init( vid_init );
+       for ( method in this ) {
+               if ( method != 'readyState' ) {
+                       ve[method] = this[method];
+               }
+       }
+       js_log( 've src len:' + ve.media_element.sources.length );
+       return ve;
+}
+// all the overwritten and new methods for playlist extension of baseEmbed
+PlMvEmbed.prototype = {
+       init:function( vid_init ) {
+               // send embed_video a created video element: 
+               ve = document.createElement( 'div' );
+               for ( var i in vid_init ) {
+                       // set the parent clip pointer:  
+                       if ( i == 'pc' ) {
+                               this['pc'] = vid_init['pc'];
+                       } else {
+                               ve.setAttribute( i, vid_init[i] );
+                       }
+               }
+               var videoInterface = new embedVideo( ve );
+               // inherit the videoInterface
+               for ( method in videoInterface ) {
+                       if ( method != 'style' ) {
+                               if ( this[ method ] ) {
+                                       // parent embed method preservation:
+                                       this['pe_' + method] = videoInterface[method];
+                               } else {
+                                       this[method] = videoInterface[method];
+                               }
+                       }
+                       // string -> boolean:
+                       if ( this[method] == "false" )this[method] = false;
+                       if ( this[method] == "true" )this[method] = true;
+               }
+       },
+       onClipDone:function() {
+               js_log( 'pl onClipDone (should go to next)' );
+               // go to next in playlist: 
+               this.pc.pp.playNext();
+       },
+       stop:function() {
+               js_log( 'pl:do stop' );
+               // set up convenience pointer to parent playlist
+               var _this = this.pc.pp;
+                                       
+               var th = Math.round( _this.pl_layout.clip_desc * _this.height );
+               var tw = Math.round( th * _this.pl_layout.clip_aspect );
+               
+               // run the parent stop:
+               this.pe_stop();
+               var pl_height = ( _this.sequencer == 'true' ) ? _this.height + 27:_this.height;
+               
+               this.getHTML();
+       },
+       play:function() {
+               // js_log('pl eb play');                
+               var _this = this.pc.pp;
+               // check if we are already playing
+               if ( !this.thumbnail_disp ) {
+                       this.pe_play();
+                       return '';
+               }
+               mv_lock_vid_updates = true;
+               this.pe_play();
+       },
+       // do post interface operations
+       postEmbedJS:function() {
+               // add playlist clips (if plugin supports it) 
+               if ( this.pc.pp.cur_clip.embed.playlistSupport() )
+                       this.pc.pp.loadEmbedPlaylist();
+               // color playlist points (if play_head present)
+               if ( this.pc.pp.disp_play_head )
+                       this.pc.pp.colorPlayHead();
+               // setup hover images (for playhead and next/prev buttons)
+               this.pc.pp.setUpHover();
+               // call the parent postEmbedJS
+               this.pe_postEmbedJS();
+               mv_lock_vid_updates = false;
+       },
+       getPlayButton:function() {
+               return this.pe_getPlayButton( this.pc.pp.id );
+       },
+       setStatus:function( value ) {
+               // status updates handled by playlist obj
+       },
+       setSliderValue:function( value ) {
+               //js_log( 'PlMvEmbed:setSliderValue:' + value );
+               // setSlider value handled by playlist obj              
+       }
+}
+
+/* 
+ *  m3u parse
+ */
+var m3uPlaylist = {
+       doParse:function() {
+               // for each line not # add as clip 
+               var inx = 0;
+               var this_pl = this;
+               // js_log('data:'+ this.data.toString());
+               $j.each( this.data.split( "\n" ), function( i, n ) {
+                       // js_log('on line '+i+' val:'+n+' len:'+n.length);
+                       if ( n.charAt( 0 ) != '#' ) {
+                               if ( n.length > 3 ) {
+                                       // @@todo make sure its a valid url
+                                       // js_log('add url: '+i + ' '+ n);
+                                       var cur_clip = new mvClip( { type:'srcClip', id:'p_' + this_pl.id + '_c_' + inx, pp:this_pl, src:n, order:inx } );
+                                       // setup the embed object 
+                                       cur_clip.setUpEmbedObj();
+                                       js_log( 'm3uPlaylist len:' + thisClip.embed.media_element.sources.length );
+                                       this_pl.addCliptoTrack( cur_clip );
+                                       inx++;
+                               }
+                       }
+               } );
+               return true;
+       }
+}
+
+var itunesPlaylist = {
+       doParse:function() {
+               var properties = { title:'title', linkback:'link',
+                                                  author:'itunes:author', desc:'description',
+                                                  date:'pubDate' };
+               var tmpElm = null;
+               for ( i in properties ) {
+                       tmpElm = this.data.getElementsByTagName( properties[i] )[0];
+                       if ( tmpElm ) {
+                               this[i] = tmpElm.childNodes[0].nodeValue;
+                               // js_log('set '+i+' to '+this[i]);
+                       }
+               }
+               // image src is nested in itunes rss:
+               tmpElm = this.data.getElementsByTagName( 'image' )[0];
+               if ( tmpElm ) {
+                       imgElm = tmpElm.getElementsByTagName( 'url' )[0];
+                               if ( imgElm ) {
+                                       this.img = imgElm.childNodes[0].nodeValue;
+                               }
+               }
+               // get the clips: 
+               var clips = this.data.getElementsByTagName( "item" );
+               properties.src = 'guid';
+               for ( var i = 0; i < clips.length; i++ ) {
+                       var cur_clip = new mvClip( { type:'srcClip', id:'p_' + this.id + '_c_' + i, pp:this, order:i } );
+                       for ( var j in properties ) {
+                               tmpElm = clips[i].getElementsByTagName( properties[j] )[0];
+                               if ( tmpElm != null ) {
+                                       cur_clip[j] = tmpElm.childNodes[0].nodeValue;
+                                       // js_log('set clip property: ' + j+' to '+cur_clip[j]);
+                               }
+                       }
+                       // image is nested
+                       tmpElm = clips[i].getElementsByTagName( 'image' )[0];
+                       if ( tmpElm ) {
+                               imgElm = tmpElm.getElementsByTagName( 'url' )[0];
+                                       if ( imgElm ) {
+                                               cur_clip.img = imgElm.childNodes[0].nodeValue;
+                                       }
+                       }
+                       // set up the embed object now that all the values have been set
+                       cur_clip.setUpEmbedObj();
+                       
+                       // add the current clip to the clip list
+                       this.addCliptoTrack( cur_clip );
+               }
+               return true;
+       }
+}
+
+/* 
+ * parse xsfp: 
+ * http://www.xspf.org/xspf-v1.html
+ */
+var xspfPlaylist = {
+       doParse:function() {
+               // js_log('do xsfp parse: '+ this.data.innerHTML);
+               var properties = { title:'title', linkback:'info',
+                                                  author:'creator', desc:'annotation',
+                                                  poster:'image', date:'date' };
+               var tmpElm = null;
+               // get the first instance of any of the meta tags (ok that may be the meta on the first clip)
+               // js_log('do loop on properties:' + properties);
+               for ( i in properties ) {
+                       js_log( 'on property: ' + i );
+                       tmpElm = this.data.getElementsByTagName( properties[i] )[0];
+                       if ( tmpElm ) {
+                               if ( tmpElm.childNodes[0] ) {
+                                       this[i] = tmpElm.childNodes[0].nodeValue;
+                                       js_log( 'set pl property: ' + i + ' to ' + this[i] );
+                               }
+                       }
+               }
+               var clips = this.data.getElementsByTagName( "track" );
+               js_log( 'found clips:' + clips.length );
+               // add any clip specific properties 
+               properties.src = 'location';
+               for ( var i = 0; i < clips.length; i++ ) {
+                       var cur_clip = new mvClip( { id:'p_' + this.id + '_c_' + i, pp:this, order:i } );
+                       // js_log('cur clip:'+ cur_clip.id);
+                       for ( var j in properties ) {
+                               tmpElm = clips[i].getElementsByTagName( properties[j] )[0];
+                               if ( tmpElm != null ) {
+                                       if ( tmpElm.childNodes.length != 0 ) {
+                                               cur_clip[j] = tmpElm.childNodes[0].nodeValue;
+                                               js_log( 'set clip property: ' + j + ' to ' + cur_clip[j] );
+                                       }
+                               }
+                       }
+                       // add mvClip ref from info link: 
+                       if ( cur_clip.linkback ) {
+                               // if mv linkback
+                               mvInx = 'Stream:';
+                               mvclippos = cur_clip.linkback.indexOf( mvInx );
+                               if ( mvclippos !== false ) {
+                                       cur_clip.mvclip = cur_clip.linkback.substr( mvclippos + mvInx.length );
+                               }
+                       }
+                       // set up the embed object now that all the values have been set
+                       cur_clip.setUpEmbedObj();
+                       // add the current clip to the clip list
+                       this.addCliptoTrack( cur_clip );
+               }
+               // js_log('done with parse');
+               return true;
+       }
+}
+/*****************************
+ * SMIL CODE (could be put into another js file / lazy_loaded for improved basic playlist performance / modularity)
+ *****************************/
+/*playlist driver extensions to the playlist object*/
+mvPlayList.prototype.monitor = function() {
+       // js_log('pl:monitor');                        
+       // if paused stop updates
+       if ( this.paused ) {
+               // clearInterval( this.smil_monitorTimerId );
+               return ;
+       }
+       // js_log("pl check: " + this.currentTime + ' > '+this.getDuration());
+       // check if we should be done:
+       if ( this.currentTime >  this.getDuration() )
+               this.stop();
+       
+       // update the playlist current time: 
+       // check for a trsnOut from the previus clip to subtract
+       this.currentTime = this.cur_clip.dur_offset + this.cur_clip.embed.relativeCurrentTime();
+               
+       // update slider: 
+       if ( !this.userSlide ) {
+               this.setStatus( seconds2npt( this.currentTime ) + '/' + seconds2npt( this.getDuration() ) );
+               this.setSliderValue( this.currentTime / this.getDuration() );
+       }
+       // pre-load any future clips:
+       this.loadFutureClips();
+       
+       
+       // status updates are handled by children clips ... playlist mostly manages smil actions
+       this.doSmilActions();
+       
+       if ( ! this.smil_monitorTimerId ) {
+               if ( document.getElementById( this.id ) ) {
+                       this.smil_monitorTimerId = setInterval( '$j(\'#' + this.id + '\').get(0).monitor()', 250 );
+               }
+       }
+}
+
+// handles the rendering of overlays load of future clips (if necessary)
+// @@todo could be lazy loaded if necessary 
+mvPlayList.prototype.doSmilActions = function( callback ) {
+       var _this = this;
+       // js_log('f:doSmilActions: ' + this.cur_clip.id + ' tid: ' + this.cur_clip.transOut );
+       var offSetTime = 0; // offset time should let us start a transition later on if we have to. 
+       var _clip = this.cur_clip;      // setup a local pointer to cur_clip
+
+       
+       // do any smil time actions that may change the current clip
+       if ( this.userSlide ) {
+               // current clip set is updated mannually outside the scope of smil Actions 
+       } else {
+               // Assume playing and go to next: 
+               if ( _clip.dur <= _clip.embed.currentTime
+                        && _clip.order != _clip.pp.getClipCount() - 1 ) {
+                       // force next clip
+                       js_log( 'order:'  + _clip.order + ' != count:' + ( _clip.pp.getClipCount() - 1 ) +
+                               ' smil dur: ' + _clip.dur + ' <= curTime: ' + _clip.embed.currentTime + ' go to next clip..' );
+                               // do a _play next:
+                               _clip.pp.playNext();
+               }
+       }
+       // @@todo could maybe generalize transIn with trasOut into one "flow" with a few scattered if statements        
+       // update/setup all transitions (will render current transition state)  
+
+       // process actions per transition types:
+       _this.procTranType( 'transIn', callback);
+       _this.procTranType( 'transOut', callback);
+}
+
+/*
+* procTranType
+* @param {string} tid the transition type [transIn|transOut]
+* @param {function} callback the callback function passed onto doUPdate
+*/
+mvPlayList.prototype.procTranType = function( tid, callback){
+       // Setup local clip pointer:
+       var _clip = this.cur_clip;      
+       
+       eval( 'var tObj =  _clip.' + tid );
+       if ( !tObj )
+               return;
+       // js_log('f:doSmilActions: ' + _clip.id + ' tid:'+tObj.id + ' tclip_id:'+ tObj.pClip.id);                                      
+       // Check if we are in range: 
+       if ( tid == 'transIn' )
+               in_range = ( _clip.embed.currentTime <= tObj.dur ) ? true : false;
+       
+       if ( tid == 'transOut' )
+               in_range = ( _clip.embed.currentTime >= ( _clip.dur - tObj.dur ) ) ? true : false;
+       
+       if ( in_range ) {
+               if ( this.userSlide || this.paused ) {
+                       if ( tid == 'transIn' ){
+                               mvTransLib.doUpdate( tObj, 
+                                       ( _clip.embed.currentTime / tObj.dur ), 
+                                       callback );     
+                       }               
+                       if ( tid == 'transOut' ){
+                               mvTransLib.doUpdate( tObj, 
+                                       ( ( _clip.embed.currentTime - ( _clip.dur - tObj.dur ) ) / tObj.dur ), 
+                                       callback );
+                       }
+               } else if ( tObj.animation_state == 0 ) {
+                       js_log( 'init/run_transition ' );
+                       tObj.run_transition();
+               }
+       } else {
+               // Close up transition if done & still onDispaly
+               if ( tObj.overlay_selector_id ) {
+                       js_log( 'close up transition :' + tObj.overlay_selector_id );
+                       mvTransLib.doCloseTransition( tObj );
+               }
+       }
+       // Run the callback:: 
+       if( callback ) 
+               callback();
+}
+
+/*
+ * mvTransLib library of transitions
+ * a single object called to initiate transition effects can easily be extended in separate js file
+ * /mvTransLib is a all static object no instances of mvTransLib/
+ * (that way a limited feature set "sequence" need not include a _lot_ of js unless necessary )
+ * 
+ * Smil Transition Effects see:  
+ * http://www.w3.org/TR/SMIL3/smil-transitions.html#TransitionEffects-TransitionAttribute
+ */
+var mvTransLib = {
+       /*
+        * function doTransition lookups up the transition in the  mvTransLib obj
+        *               and init the transition if its available 
+        * @param tObj transition attribute object
+        * @param offSetTime default value 0 if we need to start rendering from a given time 
+        */
+       doInitTransition:function( tObj ) {
+               js_log( 'mvTransLib:f:doInitTransition' );              
+               if ( !tObj.type ) {
+                       js_log( 'transition is missing type attribute' );
+                       return false;
+               }
+               
+               if ( !tObj.subtype ) {
+                       js_log( 'transition is missing subtype attribute' );
+                       return false;
+               }
+               
+               if ( !this['type'][tObj.type] ) {
+                       js_log( 'mvTransLib does not support type: ' + tObj.type );
+                       return false;
+               }
+               
+               if ( !this['type'][tObj.type][tObj.subtype] ) {
+                       js_log( 'mvTransLib does not support subType: ' + tObj.subtype );
+                       return false;
+               }
+                               
+               // setup overlay_selector_id                    
+               if ( tObj.subtype == 'crossfade' ) {
+                       if ( tObj.transAttrType == 'transIn' )
+                               var other_pClip = tObj.pClip.pp.getPrevClip();
+                       if ( tObj.transAttrType == 'transOut' )
+                               var other_pClip = tObj.pClip.pp.getNextClip();
+                               
+                       if ( typeof( other_pClip ) == 'undefined' || other_pClip === false || other_pClip.id == tObj.pClip.pp.cur_clip.id )
+                               js_log( 'Error: crossfade without target media asset' );
+                       // if not sliding start playback: 
+                       if ( !tObj.pClip.pp.userSlide && !tObj.pClip.pp.paused) {
+                               other_pClip.embed.play();                       
+                       }else{
+                               //issue a load request: 
+                               other_pClip.embed.load(); 
+                       }
+                       // manualy ad the extra layer to the activeClipList
+                       tObj.pClip.pp.activeClipList.add( other_pClip );
+                       tObj.overlay_selector_id = 'clipDesc_' + other_pClip.id;
+               } else {
+                       tObj.overlay_selector_id = this.getOverlaySelector( tObj );
+               }
+                                       
+               // all good call function with  tObj param
+               js_log( 'should call: ' + tObj.type + ' ' + tObj.subtype );
+               this['type'][tObj.type][tObj.subtype].init( tObj );
+       },
+       doCloseTransition:function( tObj ) {
+               if ( tObj.subtype == 'crossfade' ) {
+                       // close up crossfade
+                       js_log( "close up crossfade" );
+               } else {
+                       $j( '#' + tObj.overlay_selector_id ).remove();
+               }
+               // null selector: 
+               tObj.overlay_selector_id = null;
+       },
+       getOverlaySelector:function( tObj ) {
+               var overlay_selector_id = tObj.transAttrType + tObj.pClip.id;
+               js_log( 'f:getOverlaySelector: ' + overlay_selector_id + ' append to: ' + '#videoPlayer_' + tObj.pClip.embed.id );
+               // make sure overlay_selector_id not already here:      
+               if ( $j( '#' + overlay_selector_id ).length == 0  ) {
+                       $j( '#videoPlayer_' + tObj.pClip.embed.id ).prepend( '' +
+                               '<div id="' + overlay_selector_id + '" ' +
+                                       'style="position:absolute;top:0px;left:0px;' +
+                                       'height:' + parseInt( tObj.pClip.pp.height ) + 'px;' +
+                                       'width:' + parseInt( tObj.pClip.pp.width ) + 'px;' +
+                                       'z-index:2">' +
+                               '</div>' );
+               }
+               return overlay_selector_id;
+       },
+       doUpdate:function( tObj, percent, callback ) {
+               // init the transition if necessary:
+               if ( !tObj.overlay_selector_id )
+                       this.doInitTransition( tObj );
+               
+               // @@todo we should ensure viability outside of doUpate loop                    
+               if ( !$j( '#' + tObj.overlay_selector_id ).is( ':visible' ) )
+                       $j( '#' + tObj.overlay_selector_id ).show();
+               
+               // do update:
+               /*      js_log('doing update for: '+ tObj.pClip.id + 
+                       ' type:' + tObj.transAttrType +
+                       ' t_type:'+ tObj.type +
+                       ' subypte:'+ tObj.subtype  + 
+                       ' percent:' + percent);*/
+                       
+               this[ 'type' ][ tObj.type ][ tObj.subtype ].u( tObj, percent, callback);
+       },
+       getTransitionIcon:function( type, subtype ) {
+               return mv_embed_path + '/skins/common/transition_images/' + type + '_' + subtype + '.png';
+       },
+       /*
+        * mvTransLib: functional library mapping:
+        */
+       type: {
+               // Types:
+               fade: {
+                       fadeFromColor: {
+                               'attr' : ['fadeColor'],
+                               'init' : function( tObj ) {
+                                       // js_log('f:fadeFromColor: '+tObj.overlay_selector_id +' to color: '+ tObj.fadeColor);
+                                       if ( !tObj.fadeColor )
+                                               js_log( 'missing fadeColor' );
+                                       if ( $j( '#' + tObj.overlay_selector_id ).length == 0 ) {
+                                               js_log( "ERROR can't find: " + tObj.overlay_selector_id );
+                                       }
+                                       // set the initial state
+                                       $j( '#' + tObj.overlay_selector_id ).css( {
+                                               'background-color':tObj.fadeColor,
+                                               'opacity':"1"
+                                       } );
+                               },
+                               'u' : function( tObj, percent ) {
+                                       // js_log(':fadeFromColor:update: '+ percent);
+                                       // fade from color (invert the percent)
+                                       var percent = 1 - percent;
+                                       $j( '#' + tObj.overlay_selector_id ).css( {
+                                               "opacity" : percent
+                                       } );
+                               }
+                       },
+                       // corssFade
+                       crossfade: {
+                               "attr" : [],
+                               "init" : function( tObj ) {
+                                       js_log( 'f:crossfade: ' + tObj.overlay_selector_id );
+                                       if ( $j( '#' + tObj.overlay_selector_id ).length == 0 )
+                                               js_log( "ERROR overlay selector not found: " + tObj.overlay_selector_id );
+                                       
+                                       // set the initial state show the zero opacity animation 
+                                       $j( '#' + tObj.overlay_selector_id ).css( { 'opacity':0 } ).show();
+                               },
+                               'u':function( tObj, percent ) {
+                                       // Do the relative seek:
+                                       $j( '#' + tObj.overlay_selector_id ).css( {
+                                               "opacity" : percent
+                                       } );
+                               }
+                       }
+               }
+       }
+}
+
+/* object to manage embedding html with smil timings 
+ *  grabs settings from parent clip 
+ */
+var transitionObj = function( element ) {
+       this.init( element );
+};
+transitionObj.prototype = {
+       supported_attributes : new Array(
+               'id',
+               'type',
+               'subtype',
+               'fadeColor',
+               'dur'
+       ),
+       transAttrType:null, // transIn or transOut
+       overlay_selector_id:null,
+       pClip:null,
+       timerId:null,
+       animation_state:0, // can be 0=unset, 1=running, 2=done 
+       interValCount:0, // inter-intervalCount for animating between time updates
+       dur:2, // default duration of 2 
+       init:function( element ) {
+               // load supported attributes:    
+               var _this = this;
+               $j.each( this.supported_attributes, function( i, attr ) {
+                       if ( element.getAttribute( attr ) )
+                               _this[attr] = element.getAttribute( attr );
+               } );
+               // @@todo process duration (for now just strip s) per: 
+               // http://www.w3.org/TR/SMIL3/smil-timing.html#Timing-ClockValueSyntax
+               if ( _this.dur )
+                       _this.dur = smilParseTime( _this.dur );
+       },
+       /* 
+        * returns a visual representation of the transition
+        */
+       getIconSrc:function( opt ) {
+               // @@todo support some arguments 
+               return mvTransLib.getTransitionIcon( this.type, this.subtype );
+       },
+       getDuration:function() {
+               return this.dur;
+       },
+       // returns the values of supported_attributes: 
+       getAttributeObj:function() {
+               var elmObj = { };
+               for ( var i in this.supported_attributes ) {
+                       var attr = this.supported_attributes[i];
+                       if ( this[ attr ] )
+                               elmObj[ attr ] = this[ attr ];
+               }
+               return elmObj;
+       },
+       /*
+        * the main animation loop called every MV_ANIMATION_CB_RATE or 34ms ~around 30frames per second~
+        */
+       run_transition:function() {
+               // js_log('f:run_transition:' + this.interValCount);
+
+               // update the time from the video if native:   
+               if ( typeof this.pClip.embed.vid != 'undefined' ) {
+                       this.interValCount = 0;
+                       this.pClip.embed.currentTime = this.pClip.embed.vid.currentTime;
+               }
+               
+               // }else{
+                       // relay on currentTime update grabs (every 250ms or so) (ie for images)
+               //      if(this.prev_curtime!=this.pClip.embed.currentTime){    
+               //              this.prev_curtime =     this.pClip.embed.currentTime;
+               //              this.interValCount=0;
+               //      }
+               // }            
+               
+               // start_time =assigned by doSmilActions
+               // base_cur_time = pClip.embed.currentTime;
+               // dur = assigned by attribute          
+               if ( this.animation_state == 0 ) {
+                       mvTransLib.doInitTransition( this );
+                       this.animation_state = 1;
+               }
+               // set percentage include diffrence of currentTime to prev_curTime 
+               // ie updated in-between currentTime updates) 
+
+               if ( this.transAttrType == 'transIn' )
+                       var percentage = ( this.pClip.embed.currentTime +
+                                                                       ( ( this.interValCount * MV_ANIMATION_CB_RATE ) / 1000 )
+                                                       ) / this.dur ;
+                               
+               if ( this.transAttrType == 'transOut' )
+                       var percentage = ( this.pClip.embed.currentTime  +
+                                                                       ( ( this.interValCount * MV_ANIMATION_CB_RATE ) / 1000 )
+                                                                       - ( this.pClip.dur - this.dur )
+                                                       ) / this.dur ;
+               
+               /*js_log('percentage = ct:'+this.pClip.embed.currentTime + ' + ic:'+this.interValCount +' * cb:'+MV_ANIMATION_CB_RATE +
+                         ' / ' + this.dur + ' = ' + percentage );
+               */
+               
+               // js_log('cur percentage of transition: '+percentage);
+               // update state based on current time + cur_time_offset (for now just use pClip.embed.currentTime)
+               mvTransLib.doUpdate( this, percentage );
+               
+               if ( percentage >= 1 ) {
+                       js_log( "transition done update with percentage " + percentage );
+                       this.animation_state = 2;
+                       clearInterval( this.timerId );
+                       mvTransLib.doCloseTransition( this )
+                       return true;
+               }
+                                               
+               this.interValCount++;
+               // setInterval in we are still in running state and user is not using the playhead 
+               if ( this.animation_state == 1 ) {
+                       if ( !this.timerId ) {
+                               this.timerId = setInterval( 'document.getElementById(\'' + this.pClip.pp.id + '\').' +
+                                                       'run_transition(\'' + this.pClip.pp.cur_clip.order + '\',' +
+                                                               '\'' + this.transAttrType + '\')',
+                                                MV_ANIMATION_CB_RATE );
+                       }
+               } else {
+                       clearInterval( this.timerId );
+               }
+               return true;
+       },
+       clone :function() {
+               var cObj = new this.constructor();
+               for ( var i in this )
+                       cObj[i] = this[i];
+               return cObj;
+       }
+}
+
+// very limited smile feature set more details soon:  
+// region="video_region" transIn="fromGreen" begin="2s"
+// http://www.w3.org/TR/2007/WD-SMIL3-20070713/smil-extended-media-object.html#edef-ref
+var smilPlaylist = {
+       transitions: { },
+       doParse:function() {
+               var _this = this;
+               js_log( 'f:doParse smilPlaylist' );
+               // @@todo get/parse meta that we are interested in: 
+               var meta_tags = this.data.getElementsByTagName( 'meta' );
+               var metaNames = {
+                       'title':'',
+                       'interface_url':"",
+                       'linkback':"",
+                       'mTitle':"",
+                       'mTalk':"",
+                       'mTouchedTime':""
+               };
+               $j.each( meta_tags, function( i, meta_elm ) {
+                       // js_log( "on META tag: "+ $j(meta_elm).attr('name') );
+                       if ( $j( meta_elm ).attr( 'name' ) in metaNames ) {
+                               _this[ $j( meta_elm ).attr( 'name' ) ] = $j( meta_elm ).attr( 'content' );
+                       }
+                       // Special check for wikiDesc
+                       if (  $j( meta_elm ).attr( 'name' ) == 'wikiDesc' ) {
+                               if ( meta_elm.firstChild )
+                                       _this.wikiDesc  = meta_elm.firstChild.nodeValue;
+                       }
+               } );
+               // Add transition objects: 
+               var transition_tags = this.data.getElementsByTagName( 'transition' );
+               $j.each( transition_tags, function( i, trans_elm ) {
+                       if ( $j( trans_elm ).attr( "id" ) ) {
+                               _this.transitions[ $j( trans_elm ).attr( "id" )] = new transitionObj( trans_elm );
+                       } else {
+                               js_log( 'skipping transition: (missing id) ' + trans_elm );
+                       }
+               } );
+               js_log( 'loaded transitions:' + _this.transitions.length );
+               
+               // Add seq (latter we will have support more than one seq tag) / more than one "track" 
+               var seq_tags = this.data.getElementsByTagName( 'seq' );
+               $j.each( seq_tags, function( i, seq_elm ) {
+                       var inx = 0;
+                       // get all the clips for the given seq:
+                       $j.each( seq_elm.childNodes, function( i, mediaElement ) {
+                               // ~complex~ @@todo to handle a lot like "switch" "region" etc
+                               // js_log('process: ' + mediaElemnt.tagName); 
+                               if ( typeof mediaElement.tagName != 'undefined' ) {
+                                       if ( _this.tryAddMedia( mediaElement, inx ) ) {
+                                               inx++;
+                                       }
+                               }
+                       } );
+               } );
+               js_log( "done proc seq tags" );
+               return true;
+       },
+       tryAddMediaObj:function( mConfig, order, track_id ) {
+               js_log( 'tryAddMediaObj::' );
+               var mediaElement = document.createElement( 'div' );
+               for ( var i = 0; i < mv_smil_ref_supported_attributes.length; i++ ) {
+                       var attr =      mv_smil_ref_supported_attributes[i];
+                       if ( mConfig[attr] )
+                               $j( mediaElement ).attr( attr, mConfig[attr] );
+               }
+               this.tryAddMedia( mediaElement, order, track_id );
+       },
+       tryAddMedia:function( mediaElement, order, track_id ) {
+               js_log( 'SMIL:tryAddMedia:' + mediaElement );
+
+               var _this = this;
+               // Set up basic mvSMILClip send it the mediaElemnt & mvClip init: 
+               var clipObj = { };
+               var cConfig = {
+                       "id" : 'p_' + _this.id + '_c_' + order,
+                       "pp" : this, // set the parent playlist object pointer
+                       "order" : order
+               };
+               var clipObj = new mvSMILClip( mediaElement, cConfig );
+               
+               // set optional params track                                                                             
+               if ( typeof track_id != 'undefined' )
+                       clipObj["track_id"]     = track_id;
+                        
+               
+               if ( clipObj ) {
+                       // set up embed:                                                
+                       clipObj.setUpEmbedObj();
+                       // inhreit embedObject (only called on "new media" 
+                       clipObj.embed.init_with_sources_loaded();
+                       // add clip to track: 
+                       this.addCliptoTrack( clipObj , order );
+                       
+                       return true;
+               }
+               return false;
+       }
+}
+// http://www.w3.org/TR/2007/WD-SMIL3-20070713/smil-extended-media-object.html#smilMediaNS-BasicMedia
+// and added resource description elements
+// @@ supporting the "ID" attribute turns out to be kind of tricky since we use it internally 
+// (for now don't include) 
+var mv_smil_ref_supported_attributes = new Array(
+               'src',
+               'type',
+               'region',
+               'transIn',
+               'transOut',
+               'fill',
+               'dur',
+               'title',
+               // some custom attributes:
+               'uri',
+               'durationHint',
+               'poster'
+);
+/* extension to mvClip to support smil properties */
+var mvSMILClip = function( sClipElm, mvClipInit ) {
+       return this.init( sClipElm, mvClipInit );
+}
+// all the overwritten and new methods for SMIL extension of mv_embed
+mvSMILClip.prototype = {
+       instanceOf:'mvSMILClip',
+       params : { }, // support param as child of ref clips per SMIL spec  
+       init:function( sClipElm, mvClipInit ) {
+               _this = this;
+               this.params     = { };
+               // make new mvCLip with ClipInit vals  
+               var myMvClip = new mvClip( mvClipInit );
+               // inherit mvClip               
+               for ( var method in myMvClip ) {
+                       if ( typeof this[method] != 'undefined' ) {
+                               this['parent_' + method] = myMvClip[method];
+                       } else {
+                               this[method] = myMvClip[method];
+                       }
+               }
+               
+               // get supported media attr init non-set                
+               for ( var i = 0; i < mv_smil_ref_supported_attributes.length; i++ ) {
+                       var attr =      mv_smil_ref_supported_attributes[i];
+                       if ( $j( sClipElm ).attr( attr ) ) {                            
+                               _this[attr] = $j( sClipElm ).attr( attr );
+                       }
+               }
+               this['tagName'] = sClipElm.tagName;
+               
+               // Fix url paths (if needed) 
+               if( _this['src'] && _this.src.indexOf('/') != 0 && _this.src.indexOf('://') === -1)
+                       _this['src'] = mw.absoluteUrl(  _this['src'], mvClipInit.pp.getSrc() );                         
+               
+               if ( sClipElm.firstChild ) {
+                       this['wholeText'] = sClipElm.firstChild.nodeValue;
+                       js_log( "SET wholeText for: " + this['tagName'] + ' ' + this['wholeText'] );
+               }
+               // debugger;
+               // mv_embed specific property: 
+               if ( $j( sClipElm ).attr( 'poster' ) )
+                       this['img'] = $j( sClipElm ).attr( 'poster' );
+               
+               // lookup and assign copies of transitions 
+               // (since transition needs to hold some per-instance state info)                
+               if ( this.transIn && this.pp.transitions[ this.transIn ] ) {
+                       this.transIn = this.pp.transitions[ this.transIn ]. clone ();
+                       this.transIn.pClip = _this;
+                       this.transIn.transAttrType = 'transIn';
+               }
+               
+               if ( this.transOut && this.pp.transitions[ this.transOut ] ) {
+                       this.transOut = this.pp.transitions[ this.transOut ]. clone ();
+                       this.transOut.pClip = _this;
+                       this.transOut.transAttrType = 'transOut';
+               }
+               // parse duration / begin times: 
+               if ( this.dur )
+                       this.dur = smilParseTime( this.dur );
+                       
+               // parse the media duration hint ( the source media length) 
+               if ( this.durationHint )
+                       this.durationHint = smilParseTime( this.durationHint );
+               
+               // conform type to vido/ogg:
+               if ( this.type == 'application/ogg' )
+                       this.type = 'video/ogg'; // conform to 'video/ogg' type
+
+               // if unset type and we have innerHTML assume text/html type            
+               if ( !this.type  && this.wholeText ) {
+                       this.type = 'text/html';
+               }
+               // Also grab any child param elements if present: 
+               if ( sClipElm.getElementsByTagName( 'param' )[0] ) {
+                       for ( var i = 0; i < sClipElm.getElementsByTagName( 'param' ).length; i++ ) {
+                               this.params[ sClipElm.getElementsByTagName( 'param' )[i].getAttribute( "name" ) ] =
+                                                sClipElm.getElementsByTagName( 'param' )[i].firstChild.nodeValue;
+                       }
+               }
+               return this;
+       },
+       /**
+       * Returns the values of supported_attributes:
+       */ 
+       getAttributeObj:function() {
+               var elmObj = { };
+               for ( var i = 0; i < mv_smil_ref_supported_attributes.length; i++ ) {
+                       var attr = mv_smil_ref_supported_attributes[i];
+                       if ( this[attr] )
+                               elmObj[ attr ] = this[attr];
+               }
+               return elmObj;
+       },
+       /*
+        * getDuration
+        * @returns duration in int
+        */
+       getDuration:function() {
+               // check for smil dur: 
+               if ( this.dur )
+                       return this.dur;
+               return this.embed.getDuration();
+       },
+       // gets the duration of the clip subracting transitions
+       getSoloDuration:function() {
+               var fulldur = this.getDuration();
+               // see if we need to subtract from time eating transitions (transOut)
+               if ( this.transOut )
+                       fulldur -= this.transOut.getDuration();
+
+               // js_log("getSoloDuration:: td: " + this.getDuration() + ' sd:' + fulldur);
+               return fulldur;
+       },
+       // gets the duration of the original media asset (usefull for bounding setting of in-out-points)
+       getSourceDuration:function() {
+               if ( this.durationHint )
+                       return this.durationHint;
+               // if we have no source duration just return the media dur: 
+               return this.getDuration();
+       }
+}
+/*
+ * takes an input 
+ * @time_str input time string 
+ * returns time in seconds 
+ * 
+ * @@todo process duration (for now just srip s) per: 
+ * http://www.w3.org/TR/SMIL3/smil-timing.html#Timing-ClockValueSyntax
+ * (probably have to use a Time object to fully support the smil spec
+ */
+function smilParseTime( time_str ) {
+       time_str = time_str + '';
+       // first check for hh:mm:ss time: 
+       if ( time_str.split( ':' ).length == 3 ) {
+               return npt2seconds( time_str );
+       } else {
+               // assume 34s secconds representation 
+               return parseInt( time_str.replace( 's', '' ) );
+       }
+}
+// stores a list pointers to active clips (maybe this should just be a property of clips (but results in lots of seeks) 
+var activeClipList = function() {
+       return this.init();
+}
+activeClipList.prototype = {
+       init:function() {
+               this.clipList = new Array();
+       },
+       add:function( clip ) {
+               // make sure the clip is not already active: 
+               for ( var i = 0; i < this.clipList.lenght; i++ ) {
+                       var active_clip = this.clipList[i];
+                       if ( clip.id == active_clip.id ) // clip already active: 
+                               return false;
+               }
+               this.clipList.push( clip );
+               return true;
+       },
+       remove:function( clip ) {
+               for ( var i = 0; i < this.clipList.length; i++ ) {
+                       var active_clip = this.clipList[i];
+                       if ( clip.id == active_clip.id ) {
+                               this.clipList.splice( i, 1 );
+                               return true;
+                       }
+               }
+               return false;
+       },
+       getClipList:function() {
+               return this.clipList;
+       }
+}
+ var trackObj = function( iObj ) {
+        return this.init( iObj );
+ }
+ var supported_track_attr =
+trackObj.prototype = {
+       // should be something like "seq" per SMIL spec
+       // http://www.w3.org/TR/SMIL3/smil-timing.html#edef-seq
+       // but we don't really support anywhere near the full concept of seq containers yet either
+       supported_attributes: new Array(
+               'title',
+               'desc',
+               'inx'
+        ),
+       disp_mode:'timeline_thumb',
+       init : function( iObj ) {
+               if ( !iObj )
+                       iObj = { };
+               // make sure clips is new: 
+               this.clips = new Array();
+                               
+               var _this = this;
+               $j.each( this.supported_attributes, function( i, attr ) {
+                       if ( iObj[attr] )
+                               _this[attr] = iObj[attr];
+               } );
+       },
+       // returns the values of supported_attributes: 
+       getAttributeObj:function() {
+               var elmObj = { };
+               for ( var i in this.supported_attributes ) {
+                       var attr = this.supported_attributes[i];
+                       if ( this[attr] )
+                               elmObj[ attr ] = this[attr];
+               }
+               return elmObj;
+       },
+       addClip:function( clipObj, pos ) {
+               js_log( 'pl_Track: AddClip at:' + pos + ' clen: ' + this.clips.length );
+               if ( typeof pos == 'undefined' )
+                       pos = this.clips.length;
+               // get everything after pos     
+               this.clips.splice( pos, 0, clipObj );
+               // keep the clip order values accurate:
+               this.reOrderClips();
+               js_log( "did add now cLen: " + this.clips.length );
+       },
+       getClip:function( inx ) {
+               if ( !this.clips[inx] )
+                       return false;
+               return this.clips[inx];
+       },
+       reOrderClips:function() {
+               for ( var k in this.clips ) {
+                       this.clips[k].order = k;
+               }
+       },
+       getClipCount:function() {
+               return this.clips.length;
+       },
+       inheritEmbedObj: function() {
+               $j.each( this.clips, function( i, clip ) {
+                       clip.embed.inheritEmbedObj();
+               } );
+       }
+};
+       
+/* utility functions 
+ * (could be combined with other stuff) 
+*/
+function getAbsolutePos( objectId ) {
+       // Get an object left position from the upper left viewport corner
+       o = document.getElementById( objectId );
+       oLeft = o.offsetLeft;                   // Get left position from the parent object     
+       while ( o.offsetParent != null ) {   // Parse the parent hierarchy up to the document element
+               oParent = o.offsetParent        // Get parent object reference
+               oLeft += oParent.offsetLeft // Add parent left position
+               o = oParent
+       }
+       o = document.getElementById( objectId );
+       oTop = o.offsetTop;
+       while ( o.offsetParent != null ) { // Parse the parent hierarchy up to the document element
+               oParent = o.offsetParent  // Get parent object reference
+               oTop += oParent.offsetTop // Add parent top position
+               o = oParent
+       }
+       return { x:oLeft, y:oTop };
+}
diff --git a/js2/mwEmbed/libSequencer/mvSequencer.js b/js2/mwEmbed/libSequencer/mvSequencer.js
new file mode 100644 (file)
index 0000000..4f6efde
--- /dev/null
@@ -0,0 +1,1648 @@
+/*
+ * mvSequencer.js Created on Oct 17, 2007
+ *
+ * All Metavid Wiki code is Released under the GPL2
+ * for more info visit http://metavid.org/wiki/Code
+ *
+ * @author Michael Dale
+ * @email mdale@wikimedia.org
+ *
+ * Further developed in open source development partnership with kaltura.
+ * more info at http://kaltura.com & http://kaltura.org
+ *
+ * mv_sequencer.js
+ *      is a basic embeddeble sequencer.
+ *  extends the playlist with drag/drop/sortable/add/remove functionality
+ *  editing of annotative content (mostly for wiki)
+ *  enables more dynamic layouts
+ *  exports back out to json or inline format
+ */
+
+loadGM( {
+       "mwe-menu_clipedit" : "Edit media",
+       "mwe-menu_transition" : "Transitions and effects",
+       "mwe-menu_cliplib" : "Add media",
+       "mwe-menu_resource_overview" : "Resource overview",
+       "mwe-menu_options" : "Options",
+       "mwe-loading_timeline" : "Loading timeline ...",
+       "mwe-loading_user_rights" : "Loading user rights ...",
+       "mwe-no_edit_permissions" : "You do not have permissions to save changes to this sequence",
+       "mwe-edit_clip" : "Edit clip",
+       "mwe-edit_save" : "Save sequence changes",
+       "mwe-saving_wait" : "Save in progress (please wait)",
+       "mwe-save_done" : "Save complete",
+       "mwe-edit_cancel" : "Cancel sequence edit",
+       "mwe-edit_cancel_confirm" : "Are you sure you want to cancel your edit? Changes will be lost.",
+       "mwe-zoom_in" : "Zoom in",
+       "mwe-zoom_out" : "Zoom out",
+       "mwe-cut_clip" : "Cut clips",
+       "mwe-expand_track" : "Expand track",
+       "mwe-collapse_track" : "Collapse track",
+       "mwe-play_from_position" : "Play from playline position",
+       "mwe-pixle2sec" : "pixels to seconds",
+       "mwe-rmclip" : "Remove clip",
+       "mwe-clip_in" : "clip in",
+       "mwe-clip_out" : "clip out",
+       "mwe-welcome_to_sequencer" : "<h3>Welcome to the sequencer demo<\/h3> Very <b>limited<\/b> functionality right now. Not much documentation yet either.",
+       "mwe-no_selected_resource" : "<h3>No resource selected<\/h3> Select a clip to enable editing.",
+       "mwe-error_edit_multiple" : "<h3>Multiple resources selected<\/h3> Select a single clip to edit it.",
+       "mwe-editor_options" : "Editor options",
+       "mwe-editor_mode" : "Editor mode",
+       "mwe-simple_editor_desc" : "simple editor (iMovie style)",
+       "mwe-advanced_editor_desc" : "advanced editor (Final Cut style)",
+       "mwe-other_options" : "Other options",
+       "mwe-contextmenu_opt" : "Enable context menus",
+       "mwe-sequencer_credit_line" : "Developed by <a href=\"http:\/\/kaltura.com\">Kaltura, Inc.<\/a> in partnership with the <a href=\"http:\/\/wikimediafoundation.org\/wiki\/Home\">Wikimedia Foundation<\/a> (<a href=\"#\">more information<\/a>)."
+} );
+ // used to set default values and validate the passed init object
+var sequencerDefaultValues = {
+
+       instance_name:'mvSeq', // for now only one instance by name mvSeq is allowed
+
+       target_sequence_container:null,// text value (so that its a valid property)
+       target_form_text: null,
+
+       // what is our save mode:
+       // can save to 'api' url or 'form'
+       saveMode : 'api',
+
+       video_container_id:'mv_video_container',
+
+       video_width : 400,
+       video_height: 300,
+
+       sequence_tools_id:'mv_sequence_tools',
+       timeline_id:'mv_timeline',
+       plObj_id:'seq_pl',
+       plObj:'null',
+
+       // In pixel to second ratio ie 100pixles for every ~30seconds
+       timeline_scale:.06, 
+       
+       // Default timeline duration in seconds
+       timeline_duration:500, 
+       
+       playline_time:0,
+       track_thumb_height:60,
+       track_text_height:20,
+
+       // Default timeline mode: "story" (i-movie like) or "time" (finalCut like)
+       timeline_mode:'storyboard',
+
+       // How large are the i-movie type clips
+       track_clipThumb_height:80, 
+
+       // Default time to subtract or add when adjusting clips.
+       base_adj_duration:.5, 
+
+       // Default clipboard is empty:
+       clipboard:new Array(),
+       
+       // Stores the clipboard edit token (if user has rights to edit their User page)
+       clipboardEditToken:null,
+       
+       // Stores the sequence edit token (if user has rights to edit the current sequence)
+       sequenceEditToken:null,
+       
+       // The time the sequence was last touched (grabbed at time of startup)
+       sequenceTouchedTime:null,
+       
+       // the default config for the add media wizard
+       amw_conf: { },
+
+       
+       inline_playlist:'null',
+       inline_playlist_id:'null',
+       mv_pl_src:'null',
+       
+       // The edit stack (so that you can "undo" edits)
+       edit_stack:new Array(),
+       disp_menu_item:null,
+       
+       // Track Object 
+       tracks: { }
+}
+var mvSequencer = function( iObj ) {
+       return this.init( iObj );
+};
+// Set up the mvSequencer object
+mvSequencer.prototype = {
+       // The menu_items Object contains: default html, js setup/loader functions
+       menu_items : {
+               'clipedit': {
+                       'default':0,
+                       'html':'',
+                       'js': function( this_seq ) {
+                               this_seq.doEditSelectedClip();
+                       },
+                       'click_js':function( this_seq ) {
+                               this_seq.doEditSelectedClip();
+                       }
+               },
+               'transition': {
+                       'default':0,
+                       'html' : '<h3>' + gM( 'mwe-menu_transition' ) + '</h3>',
+                       'js':function( this_seq ) {
+                               this_seq.doEditTransitionSelectedClip();
+                       },
+                       'click_js':function( this_seq ) {
+                               // Highlight the transition of the selected clip:
+                               this_seq.doEditTransitionSelectedClip();
+                       }
+               },
+               'cliplib': {
+                       'default':0,
+                       'html': gM( 'mwe-loading_txt' ),
+                       'js':function( this_seq ) {
+                               // Load the search interface with sequence tool targets
+                               mvJsLoader.doLoad( [
+                                       'remoteSearchDriver',
+                                       'seqRemoteSearchDriver'
+                               ], function() {
+                                        this_seq.mySearch = new seqRemoteSearchDriver( this_seq );
+                                        this_seq.mySearch.createUI();
+                               } );
+                       }
+               },
+               'options': {
+                       'default':0,
+                       'html' : '<h3>' + gM( 'mwe-menu_options' ) + '</h3>' +
+                               gM( 'mwe-editor_mode' ) + '<br> ' +
+                               '<blockquote><input type="radio" value="simple_editor" name="opt_editor">' +
+                                               gM( 'mwe-simple_editor_desc' ) + ' </blockquote>' +
+                               '<blockquote><input type="radio" value="advanced_editor" name="opt_editor">' +
+                                               gM( 'mwe-advanced_editor_desc' ) + ' </blockquote>' +
+                               gM( 'mwe-other_options' ) + '<br>' +
+                               '<blockquote><input type="checkbox" value="contextmenu_opt" name="contextmenu_opt">' +
+                                               gM( 'mwe-contextmenu_opt' ) + ' </blockquote>',
+                       'js':function( this_seq ) {
+                               $j( '#options_ic input[value=\'simple_editor\']' ).attr( {
+                                       'checked':( this_seq.timeline_mode == 'storyboard' ) ? true:false
+                               } ).click( function() {
+                                       this_seq.doSimpleTl();
+                               } );
+                               $j( '#options_ic input[value=\'advanced_editor\']' ).attr( {
+                                       'checked':( this_seq.timeline_mode == 'time' ) ? true:false
+                               } ).click( function() {
+                                       this_seq.doAdvancedTl();
+                               } );
+                               // set up the options for context menus
+                       }
+               }
+       },
+
+       // set up initial key states:
+       key_shift_down:false,
+       key_ctrl_down:false,
+       inputFocus:false,
+
+       init:function( iObj ) {
+               // set up pointer to this_seq for current scope:
+               var this_seq = this;
+               // set the default values:
+               for ( var i in sequencerDefaultValues ) {
+                       this[ i ] = sequencerDefaultValues[i];
+               }
+               for ( var i in iObj ) {
+                       // js_log('on '+ i + ' :' + iObj[i]);
+                       if ( typeof sequencerDefaultValues[i] != 'undefined' ) { // make sure its a valid property
+                               this[i] = iObj[i];
+                       }
+               }
+
+               // check for sequence_container
+               if ( $j( this.target_sequence_container ).length === 0 ) {
+                       js_log( "Error: missing target_sequence_container" );
+                       return false;
+               }
+
+               // $j(this.target_sequence_container).css('position', 'relative');
+               this['base_width']  = $j( this.target_sequence_container ).width();
+               this['base_height'] = $j( this.target_sequence_container ).height();
+
+               // add the container divs (with basic layout ~universal~
+               $j( this.target_sequence_container ).html( '' +
+                       '<div id="' + this.video_container_id + '" style="position:absolute;right:0px;top:0px;' +
+                               'width:' + this.video_width + 'px;height:' + ( this.video_height + 54 ) + 'px;"/>' +
+                       '<div id="' + this.timeline_id + '" class="ui-widget ui-widget-content ui-corner-all" style="position:absolute;' +
+                               'left:0px;right:0px;top:' + ( this.video_height + 60 ) + 'px;bottom:20px;overflow:auto;">' +
+                                       gM( 'mwe-loading_timeline' ) + '</div>' +
+                       '<div class="seq_status" style="position:absolute;left:0px;width:300px;"></div>' +
+                       '<div class="seq_save_cancel" style="position:absolute;' +
+                               'left:5px;bottom:0px;height:15px;">' +
+                                       gM( 'mwe-loading_user_rights' ) +
+                       '</div>' +
+                       '<div class="about_editor" style="position:absolute;right:5px;bottom:0px;">' +
+                               gM( 'mwe-sequencer_credit_line' ) +
+                       '</div>' +
+                       '<div id="' + this.sequence_tools_id + '" style="position:absolute;' +
+                               'left:0px;right:' + ( this.video_width + 10 ) + 'px;top:0px;height:' + ( this.video_height + 47 ) + 'px;"/>'
+               ).css( {
+                       'min-width':'850px'
+               } );
+
+               /*js_log('set: '+this.target_sequence_container + ' html to:'+ "\n"+
+                       $j(this.target_sequence_container).html()
+               );*/
+               
+               // first check if we got a cloned PL object:
+               // (when the editor is invoked with the plalylist already on the page)
+               /*if( this.plObj != 'null' ){
+                       js_log('found plObj clone');
+                       //extend with mvSeqPlayList object:
+                       this.plObj = new mvSeqPlayList(this.plObj);
+                       js_log('mvSeqPlayList added: ' + this.plObj.org_control_height );
+                       $j('#'+this.video_container_id).get(0).attachNode( this.plObj );
+                       this.plObj.getHTML();
+                       this.checkReadyPlObj();
+                       return ;
+               }*/
+
+               // else check for source based sequence editor (a clean page load of the editor)
+               if ( this.mv_pl_src != 'null' ) {
+                       js_log( ' pl src:: ' + this.mv_pl_src );
+                       var src_attr = ' src="' + this.mv_pl_src + '" ';
+               } else {
+                       js_log( ' null playlist src .. (start empty) ' );
+                       var src_attr = '';
+               }
+               $j( '#' + this.video_container_id ).html( '<playlist ' + src_attr +
+                       ' style="width:' + this.video_width + 'px;height:' + this.video_height + 'px;" ' +
+                       ' sequencer="true" id="' + this.plObj_id + '" />' );
+               rewrite_by_id( this.plObj_id );
+               setTimeout( this.instance_name + '.checkReadyPlObj()', 25 );
+       },
+       updateSeqSaveButtons:function() {
+               var _this = this;
+               if ( this.sequenceEditToken ) {
+                       $j( this.target_sequence_container + ' .seq_save_cancel' ).html(
+                               $j.btnHtml( gM( 'mwe-edit_save' ), 'seq_edit_save', 'close' ) + ' ' +
+                               $j.btnHtml( gM( 'mwe-edit_cancel' ), 'seq_edit_cancel', 'close' )
+                       );
+               } else {
+                       $j( this.target_sequence_container + ' .seq_save_cancel' ).html( cancel_button + gM( 'mwe-no_edit_permissions' ) );
+               }
+               // assing bindings
+               $j( this.target_sequence_container + ' .seq_edit_cancel' ).unbind().click( function() {
+                       var x = window.confirm( gM( 'mwe-edit_cancel_confirm' ) );
+                       if ( x ) {
+                               _this.closeModEditor();
+                       } else {
+                               // close request canceled.
+                       }
+               } );
+               $j( this.target_sequence_container + ' .seq_edit_save' ).unbind().click( function() {
+                       // pop up progress dialog ~requesting edit line summary~
+                       // remove any other save dialog
+                       $j( '#seq_save_dialog' ).remove();
+                       $j( 'body' ).append( '<div id="seq_save_dialog" title="' + gM( 'mwe-edit_save' ) + '">' +
+                                               '<span class="mw-summary">' +
+                                                       '<label for="seq_save_summary">Edit summary: </label>' +
+                                               '</span>' +
+                                               '<input id="seq_save_summary" tabindex="1" maxlength="200" value="" size="30" name="seq_save_summary"/>' +
+                                       '</div>' );
+                       var bConf = { };
+                       bConf[ gM( 'mwe-cancel' ) ] = function() {
+                               $j( this ).dialog( 'close' );
+                       };
+                       bConf[ gM( 'mwe-edit_save' ) ] = function() {
+                               var saveReq = {
+                                       'action'        : 'edit',
+                                       'title'         : _this.plObj.mTitle,
+                                       // the text is the sequence XML + the description
+                                       'text'          : _this.getSeqOutputHLRDXML() + "\n" +
+                                                                 _this.plObj.wikiDesc,
+                                       'token'         : _this.sequenceEditToken,
+                                       'summary'       : $j( '#seq_save_summary' ).val()
+                               };
+                               // change to progress bar and save:
+                               $j( '#seq_save_dialog' ).html( '<div class="progress" /><br>' +
+                                       gM( 'mwe-saving_wait' )
+                               )
+                               $j( '#seq_save_dialog .progress' ).progressbar( {
+                                       value: 100
+                               } );
+                               // run the Seq Save Request:
+                               do_api_req( {
+                                       'data': saveReq,
+                                       'url' : _this.getLocalApiUrl()
+                               }, function( data ) {
+                                       $j( '#seq_save_dialog' ).html( gM( 'mwe-save_done' ) );
+                                       $j( '#seq_save_dialog' ).dialog( 'option',
+                                               'buttons', {
+                                                       "Done":function() {
+                                                               // refresh the page?
+                                                               window.location.reload();
+                                                       },
+                                                       "Do More Edits": function() {
+                                                               $j( this ).dialog( "close" );
+                                                       }
+                                       } );
+                               } );
+                       };
+                       // dialog:
+                       $j( '#seq_save_dialog' ).dialog( {
+                               bgiframe: true,
+                               autoOpen: true,
+                               modal: true,
+                               buttons: bConf
+                       } );
+               } )
+       },
+       // display a menu item (hide the rest)
+       disp:function( item, dispCall ) {
+               js_log( 'menu_item disp: ' + item );
+               this.disp_menu_item = item;
+               // update the display and item state:
+               if ( this.menu_items[item] ) {
+                       // update the tabs display:
+                       if ( !dispCall )
+                               $j( "#seq_menu" ).tabs( 'select', this.menu_items[item].inx );
+
+                       this.menu_items[item].default = 1;
+                       // do any click_js actions:getInsertControl
+                       if ( this.menu_items[item].click_js )
+                               this.menu_items[item].click_js( this );
+               }
+       },
+       // setup the menu items:
+       setupMenuItems:function() {
+               js_log( 'loadInitMenuItems' );
+               var this_seq = this;
+               // do all the menu_items setup:  @@we could defer this to once the menu item is requested
+               for ( var i in this.menu_items ) {
+                       if (    this.menu_items[i].js )
+                               this.menu_items[i].js( this );
+               }
+       },
+       renderTimeLine:function() {
+               // empty out the top level html:
+               $j( '#' + this.timeline_id ).html( '' );
+               // add html general for timeline
+               if ( this.timeline_mode == 'time' ) {
+                       $j( '#' + this.timeline_id ).html( '' +
+                               '<div id="' + this.timeline_id + '_left_cnt" class="mv_tl_left_cnt">' +
+                                       '<div id="' + this.timeline_id + '_head_control" style="position:absolute;top:0px;left:0px;right:0px;height:30px;">' +
+                                               '<a title="' + gM( 'mwe-play_from_position' ) + '" href="javascript:' + this.instance_name + '.play_jt()">' +
+                                                       '<img style="width:16px;height:16px;border:0" src="' + mv_embed_path + 'images/control_play_blue.png">' +
+                                               '</a>' +
+                                               '<a title="' + gM( 'mwe-zoom_in' ) + '" href="javascript:' + this.instance_name + '.zoom_in()">' +
+                                                       '<img style="width:16px;height:16px;border:0" src="' + mv_embed_path + 'images/zoom_in.png">' +
+                                               '</a>' +
+                                               '<a title="' + gM( 'mwe-zoom_out' ) + '" href="javascript:' + this.instance_name + '.zoom_out()">' +
+                                                       '<img style="width:16px;height:16px;border:0" src="' + mv_embed_path + 'images/zoom_out.png">' +
+                                               '</a>' +
+                                               '<a title="' + gM( 'mwe-cut_clip' ) + '" href="javascript:' + this.instance_name + '.cut_mode()">' +
+                                                       '<img style="width:16px;height:16px;border:0" src="' + mv_embed_path + 'images/cut.png">' +
+                                                       '</a>' +
+                                       '</div>' +
+                               '</div>' +
+                               '<div id="' + this.timeline_id + '_tracks" class="mv_seq_tracks">' +
+                                       '<div id="' + this.timeline_id + '_head_jump" class="mv_head_jump" style="position:absolute;top:0px;left:0px;height:20px;"></div>' +
+                                       '<div id="' + this.timeline_id + '_playline" class="mv_playline"></div>' +
+                               '</div>'
+                       );
+                       // add playlist hook to update timeline
+                       this.plObj.update_tl_hook = this.instance_name + '.update_tl_hook';
+                       var this_sq = this;
+                       var top_pos = 25;
+                       // add tracks:
+                       for ( var i in this.plObj.tracks ) {
+                               var track = this.plObj.tracks[i];
+                               // js_log("on track: "+ i + ' t:'+ $j('#'+this.timeline_id+'_left_cnt').html() );
+                               // set up track based on disp type
+                               switch( track.disp_mode ) {
+                                       case 'timeline_thumb':
+                                               var track_height = 60;
+                                               var exc_img = 'opened';
+                                               var exc_action = 'close';
+                                               var exc_msg = gM( 'mwe-collapse_track' );
+                                       break;
+                                       case 'text':
+                                               var track_height = 20;
+                                               var exc_img = 'closed';
+                                               var exc_action = 'open';
+                                               var exc_msg = gM( 'mwe-expand_track' );
+                                       break;
+                               }
+                               // add track name:
+                               $j( '#' + this.timeline_id + '_left_cnt' ).append(
+                                       '<div id="track_cnt_' + i + '" style="top:' + top_pos + 'px;height:' + track_height + 'px;" class="track_name">' +
+                                               '<a id="mv_exc_' + i + '" title="' + exc_msg + '" href="javascript:' + this_sq.instance_name + '.exc_track(' + i + ',\'' + exc_action + '\')">' +
+                                                       '<img id="' + this_sq.timeline_id + '_close_expand" style="width:16px;height:16px;border:0" ' +
+                                                               ' src="' + mv_embed_path + 'images/' + exc_img + '.png">' +
+                                               '</a>' +
+                                       track.title + '</div>'
+                               );
+                               // also render the clips in the trackset container: (thumb or text view)
+                               $j( '#' + this.timeline_id + '_tracks' ).append(
+                                       '<div id="container_track_' + i + '" style="top:' + top_pos + 'px;height:' + ( track_height + 2 ) + 'px;left:0px;right:0px;" class="container_track" />'
+                               );
+                               top_pos += track_height + 20;
+                       }
+               }
+               if ( this.timeline_mode == 'storyboard' ) {
+                       var top_pos = this.plObj.org_control_height;
+                       // debugger;
+                       for ( var i in this.plObj.tracks ) {
+                               var track_height = this.track_clipThumb_height;
+                               var timeline_id = this.timeline_id
+                               // add in play box and container tracks
+                               $j( '#' + timeline_id ).append( '' +
+                                       '<div id="interface_container_track_' + i + '" ' +
+                                       '       style="position:absolute;top:5px;height:' + ( track_height + 30 ) + 'px;left:10px;right:0px;"' +
+                                       '>' +
+                                               '<div id="container_track_' + i + '" style="position:relative;top:0px;' +
+                                                       'height:' + ( track_height + 30 ) + 'px;left:0px;right:0px;" class="container_track">' +
+                                               '</div>' +
+                                               '<div id="' + timeline_id + '_playline" class="mv_story_playline">' +
+                                                       '<div class="mv_playline_top"/>' +
+                                               '</div>' +
+                                       '</div>'
+                               );
+                               top_pos += track_height + 20;
+                       }
+               }
+       },
+       // once playlist is ready continue
+       checkReadyPlObj:function() {
+               // set up pointers from sequencer to pl obj
+               this.plObj = $j( '#' + this.plObj_id ).get( 0 );
+               // & from seq obj to sequencer
+               this.plObj.pSeq = this;
+
+               if ( this.plObj )
+                       if ( ! this.plObj.loading )
+                               this.plReadyInit();
+
+               // else keep checking for the playlist to be ready
+               if ( this.plObj.loading ) {
+                       if ( this.plReadyTimeout == 200 ) {
+                               js_error( 'error playlist never ready' );
+                       } else {
+                               this.plReadyTimeout++;
+                               setTimeout( this.instance_name + '.checkReadyPlObj()', 25 );
+                       }
+               }
+       },
+       getLocalApiUrl:function() {
+               return this.plObj.interface_url;
+       },
+       plReadyInit:function() {
+               var _this = this;
+               js_log( 'plReadyInit' );
+               js_log( this.plObj );
+               // give the playlist a pointer to its parent seq:
+               this.plObj['seqObj'] = this;
+
+               // update playlist (if its empty right now)
+               if ( this.plObj.getClipCount() == 0 ) {
+                       $j( '#' + this.plObj_id ).html( 'empty playlist' );
+               }
+
+               // propagate the edit tokens
+               // if on an edit page just grab from the form:
+               this.sequenceEditToken = $j( 'input[wpEditToken]' ).val();
+
+               if ( typeof this.sequenceEditToken == 'undefined' && this.getLocalApiUrl() != null ) {
+                       get_mw_token( _this.plObj.mTitle, _this.getLocalApiUrl(),
+                               function( token ) {
+                                       if ( token ) {
+                                               _this.sequenceEditToken = token;
+                                               _this.updateSeqSaveButtons();
+                                       }
+                               }
+                       );
+                       get_mw_token( _this.plObj.mTalk, _this.getLocalApiUrl(),
+                               function( token ) {
+                                       _this.clipboardEditToken = token;
+                               }
+                       );
+                       // also grab permissions for sending clipboard commands to the server
+
+                       // (calling the sequencer inline) try and get edit token via api call:
+                       // (somewhat fragile way to get at the api... should move to config
+                       /*var token_url = this.plObj.interface_url.replace(/index\.php/, 'api.php');
+                       token_url += '?action=query&format=xml&prop=info&intoken=edit&titles=';
+                       $j.ajax({
+                               type: "GET",
+                               url: token_url + this_seq.plObj.mTitle,
+                               success:function(data){
+                                       var pageElm = data.getElementsByTagName('page')[0];
+                                       if( $j(pageElm).attr('edittoken') ){
+                                               this_seq.sequenceEditToken = $j(pageElm).attr('edittoken');
+                                       }
+
+                               }
+                       });*/
+                       // also grab permissions for sending clipboard commands to the server
+                       /*$j.ajax({
+                               type:"GET",
+                               url: token_url + this_seq.plObj.mTalk,
+                               success:function(data){
+                                       var pageElm = data.getElementsByTagName('page')[0];
+                                       if( $j(pageElm).attr('edittoken') ){
+                                               this_seq.clipboardEditToken = $j(pageElm).attr('edittoken');
+                                       }
+                               }
+                       });*/
+               }
+
+
+               // Render the menu tabs::
+               var item_containers = '';
+               var inx = 0;
+               var selected_tab = 0;
+               var tabc = '';
+               var o = '<div id="seq_menu" style="width:100%;height:100%">';
+               o += '<ul>';
+               for ( var tab_id in this.menu_items ) {
+                       menu_item = this.menu_items[tab_id];
+                       menu_item.inx = inx;
+                       if ( menu_item.default ) {
+                               selected_tab = inx;
+                               _this.disp_menu_item = tab_id;
+                       }
+
+                       o += '<li>' +
+                                       '<a id="mv_menu_item_' + tab_id + '" href="#' + tab_id + '_ic">' + gM( 'mwe-menu_' + tab_id ) + '</a>' +
+                               '</li>';
+
+                       tabc += '<div id="' + tab_id + '_ic" style="overflow:auto;height:268px;" >';
+                               tabc += ( menu_item.html ) ? menu_item.html : '<h3>' + gM( 'mwe-menu_' + tab_id ) + '</h3>';
+                       tabc += '</div>';
+                       inx++;
+               };
+               o += '</ul>';
+               o += tabc;
+               $j( '#' + this.sequence_tools_id ).html( o );
+
+
+               $j( "#seq_menu" ).tabs( {
+                       selected:selected_tab,
+                       select: function( event, ui ) {
+                               _this.disp( $j( ui.tab ).attr( 'id' ).replace( 'mv_menu_item_', '' ), true );
+                       }
+               // Add sorting
+               } ).find( ".ui-tabs-nav" ).sortable( { axis : 'x' } );
+
+
+               // Render the timeline
+               this.renderTimeLine();
+               this.do_refresh_timeline();
+
+               // Load initial content into containers
+               this.setupMenuItems();
+
+               this.doFocusBindings();
+
+               // Set up key bidnings
+               $j( window ).keydown( function( e ) {
+                       js_log( 'pushed down on:' + e.which );
+                       if ( e.which == 16 )
+                               _this.key_shift_down = true;
+
+                       if ( e.which == 17 )
+                               _this.key_ctrl_down = true;
+
+                       if ( ( e.which == 67 && _this.key_ctrl_down ) && !_this.inputFocus )
+                               _this.copySelectedClips();
+
+                       if ( ( e.which == 88 && _this.key_ctrl_down ) && !_this.inputFocus )
+                               _this.cutSelectedClips();
+
+                       // Paste cips on v + ctrl while not focused on a text area:
+                       if ( ( e.which == 86 && _this.key_ctrl_down ) && !_this.inputFocus )
+                               _this.pasteClipBoardClips();
+
+               } );
+               $j( window ).keyup( function( e ) {
+                       js_log( 'key up on ' + e.which );
+                       // User let go of "shift" turn off multi-select
+                       if ( e.which == 16 )
+                               _this.key_shift_down = false;
+
+                       if ( e.which == 17 )
+                               _this.key_ctrl_down = false;
+
+                       // Escape key ( deselect )
+                       if ( e.which == 27 )
+                               _this.deselectClip();
+
+
+                       // Backspace or Delete key while not focused on a text area:
+                       if ( ( e.which == 8 || e.which == 46 ) && !_this.inputFocus )
+                               _this.removeSelectedClips();
+               } );
+       },
+       /**
+       * Check all text nodes for focus
+       */
+       doFocusBindings:function() {
+               var _this = this;
+               // if an input or text area has focus disable delete key binding
+               $j( "input,textarea" ).focus( function () {
+                       js_log( "inputFocus:true" );
+                       _this.inputFocus = true;
+               } );
+               $j( "input,textarea" ).blur( function () {
+                       js_log( "inputFocus:blur" );
+                       _this.inputFocus = false;
+               } )
+       },
+       /*
+       * Update the timeline hook
+       */
+       update_tl_hook:function( jh_time_ms ) {
+               // Put into seconds scale:
+               var jh_time_sec_float = jh_time_ms / 1000;
+               // Render playline at given time
+               $j( '#' + this.timeline_id + '_playline' )
+                       .css( 
+                               'left', 
+                               Math.round( jh_time_sec_float / this.timeline_scale ) + 'px' 
+                       );
+               // js_log('at time:'+ jh_time_sec + ' px:'+ Math.round(jh_time_sec_float/this.timeline_scale));
+       },
+       /*
+       * Returns a xml or json representation of the current sequence 
+       */
+       getSeqOutputJSON:function() {
+               js_log( 'json output:' );
+       },
+       /*
+       * Gets the Sequence as a formated high level resource description xml string
+       * @returns {xml} 
+       */
+       getSeqOutputHLRDXML:function() {
+               var o = '<sequence_hlrd>' + "\n";
+               o += "\t<head>\n";
+               // Get transitions
+               for ( var i in this.plObj.transitions ) {
+                       if ( this.plObj.transitions[i] ) {
+                               var tObj = this.plObj.transitions[i].getAttributeObj();
+                               o += "\t\t<transition ";
+                               for ( var j in tObj ) {
+                                       o += ' ' + j + '="' + tObj[j] + '"\n\t\t';
+                               }
+                               o += '/>' + "\n"; // transitions don't have children
+                       }
+               }
+               o += "\t</head>\n";
+
+               // Get clips
+               o += "\t<body>\n";
+               // Output each track:
+               for ( var i in this.plObj.tracks ) {
+                       var curTrack = this.plObj.tracks[i];
+                       o += "\t<seq";
+                               var tAttr = curTrack.getAttributeObj();
+                               for ( var j in  tAttr ) {
+                                       o += ' ' + j + '="' + tAttr[j] + '"\n\t\t\t';
+                               }
+                       o += ">\n";
+                       for ( var k in curTrack.clips ) {
+                               var curClip = curTrack.clips[k];
+                               o += "\t\t<ref ";
+                                       var cAttr = curClip.getAttributeObj();
+                                       var lt = '';
+                                       for ( var j in  cAttr ) {
+                                               var val =  ( j == 'transIn' || j == 'transOut' ) ? cAttr[j].id : cAttr[j];
+                                               o += lt + j + '="' + val + '"';
+                                               lt = "\n\t\t";
+                                       }
+                               o += ">\n" // close the clip
+                               for ( var pName in curClip.params ) {
+                                       var pVal = curClip.params[pName];
+                                       o += "\t\t\t" + '<param name="' + pName + '">' + pVal + '</param>' + "\n";
+                               }
+                               o += "\t\t</ref>\n\n";
+                       }
+                       o += "\n</seq>\n";
+               }
+               o += "\t</body>\n";
+               // Close the tag
+               o += '</sequence_hlrd>';
+
+               return o;
+       },
+       /**
+       * Takes a track index and a clip index, to get a clip Object.
+       * It then calls doEditClip with that clip Object. 
+       */
+       editClip:function( track_inx, clip_inx ) {
+               var cObj = this.plObj.tracks[ track_inx ].clips[ clip_inx ];
+               this.doEditClip( cObj );
+       },
+       /**
+       * Calls the doEditClip interface on the selected clip
+       * Handles cases where no clips are selected or multiple clips are selected.  
+       */
+       doEditSelectedClip:function() {
+               js_log( "f:doEditSelectedClip:" );
+               // And only one clip selected
+               if ( $j( '.mv_selected_clip' ).length == 1 ) {
+                       this.doEditClip( this.getClipFromSeqID( $j( '.mv_selected_clip' ).parent().attr( 'id' ) ) );
+               } else if ( $j( '.mv_selected_clip' ).length === 0 ) {
+                       // No clip selected warning:
+                       $j( '#clipedit_ic' ).html( gM( 'mwe-no_selected_resource' ) );
+               } else {
+                       // Multiple clip selected warning:
+                       $j( '#clipedit_ic' ).html( gM( 'mwe-error_edit_multiple' ) );
+               }
+       },
+       /**
+       * Pulls up the edit transition interface for the selected clip
+       */
+       doEditTransitionSelectedClip:function() {
+               var _this = this;
+               js_log( "f:doEditTransitionSelectedClip:" + $j( '.mv_selected_clip' ).length );
+               if ( $j( '.mv_selected_clip' ).length == 1 ) {
+                       _this.doEditTransition( _this.getClipFromSeqID( $j( '.mv_selected_clip' ).parent().attr( 'id' ) ) );
+               } else if ( $j( '.mv_selected_clip' ).length === 0 ) {
+                       // no clip selected warning:
+                       $j( '#transition_ic' ).html( gM( 'mwe-no_selected_resource' ) );
+               } else {
+                       // multiple clip selected warning:
+                       $j( '#transition_ic' ).html( gM( 'mwe-error_edit_multiple' ) );
+               }
+       },
+       /**
+       * Loads the transition edit javascript libs and 
+       * displays the transition edit interface. 
+       */
+       doEditTransition:function( cObj ) {
+               js_log( "sequence:doEditTransition" );
+               var _this = this;
+               // Add a loading image
+               mv_get_loading_img( '#transitions_ic' );
+               mvJsLoader.doLoad( [
+                       '$j.fn.ColorPicker',
+                       'mvTimedEffectsEdit'
+               ], function() {
+                       // For some reason we lose scope in the options passed to mvTimedEffectsEdit
+                       // so we re refrence the sequence here: 
+                       var localSeqRef = _this;
+                       _this.myEffectEdit = new mvTimedEffectsEdit( {
+                               'rObj'           : cObj,
+                               'control_ct' : 'transition_ic',
+                               'pSeq'   : localSeqRef
+                       } );
+               } )
+       },
+       /*
+       * Updates the clip details div if edit resource is set
+       */
+       doEditClip:function( cObj ) {
+               js_log( 'seq:doEditClip' );
+               var _this = this;
+
+               // Set default edit action
+               var edit_action = 'fileopts';
+
+               mv_get_loading_img( '#clipedit_ic' );
+               
+               // Load the clipEdit library if not already loaded:
+               mvJsLoader.doLoad( [
+                       'mvClipEdit'
+               ], function() {
+                       // Zero out the current editor:                         
+                       _this.myClipEditor = { };
+                       // Setup the cliploader options
+                       _this.myClipEditor = new mvClipEdit( {
+                               'rObj'                  : cObj,
+                               'control_ct'    : 'clipedit_ic',
+                               'clip_disp_ct'  : cObj.id,
+                               'edit_action'   : edit_action,
+                               'p_seqObj'              : _this,
+                               'profile'               : 'sequence'
+                       } );
+               } );
+       },
+       
+       /*
+       * Save new clip segment
+       * FIXME this is just a stub
+       */
+       saveClipEdit:function() {
+               // saves the clip updates
+       },
+       
+       /**
+       * Closes the sequence and dereferences the global instance. 
+       */ 
+       closeModEditor:function() {
+               // unset the sequencer
+               _global['mvSeq'] = null;
+               $j( this.target_sequence_container + ',.ui-widget-overlay' ).remove();
+       },
+       
+       /**
+       * Copies the selected clips to the server hosted "clipboard"
+       * 
+       * FIXME need to support local clipboard for stand alone editing.  
+       * FIXME this does not really work at all right now
+       */
+       copySelectedClips:function() {
+               var this_seq = this;
+               // set all the selected clips
+               this.clipboard = new Array();
+               $j( '.mv_selected_clip' ).each( function() {
+
+                       // Add each clip to the clip board:
+                       var cur_clip = this_seq.getClipFromSeqID( $j( this ).parent().attr( 'id' ) );
+                       this_seq.clipboard.push( cur_clip.getAttributeObj() );
+                       
+               } );
+               
+               // Upload clipboard to the server (if possible)
+               if ( mw.parseUri(  document.URL ).host != mw.parseUri( this_seq.plObj.interface_url ).host ) {
+                       js_log( 'error: presently we can\'t copy clips across domains' );
+               } else {
+                       // FIXME we need to add an api entry point to store a "clipboard"
+                       // right now this is dependent on a custom hook:                        
+                       if ( this_seq.clipboardEditToken && this_seq.plObj.interface_url ) {
+                               var req_url = this_seq.plObj.interface_url.replace( /api.php/, 'index.php' ) + '?action=ajax&rs=mv_seqtool_clipboard&rsargs[]=copy';
+                               $j.ajax( {
+                                       type: "POST",
+                                       url : req_url,
+                                       data: $j.param( {
+                                               "clipboard_data": $j.toJSON( this_seq.clipboard ),
+                                               "clipboardEditToken": this_seq.clipboardEditToken
+                                       } ),
+                                       success:function( data ) {
+                                               js_log( 'did clipboard push ' + $j.toJSON( this_seq.clipboard ) );
+                                       }
+                               } );
+                       } else {
+                               js_log( 'error: no clipboardEditToken to uplaod clipboard to server' );
+                       }
+               }
+       },
+       /*
+       * Paste the clipboard clips into the sequence
+       */
+       pasteClipBoardClips:function() {
+               js_log( 'f:pasteClipBoardClips' );
+               // @@todo query the server for updated clipboard
+               // paste before the "current clip"
+               this.addClips( this.clipboard, this.plObj.cur_clip.order );
+       },
+       
+       /** 
+       * Cut selected clips from the timeline
+       */
+       cutSelectedClips:function() {
+               this.copySelectedClips();
+               this.removeSelectedClips();
+       },
+       
+       /**
+       * Remove selected clips from the timeline
+       */ 
+       removeSelectedClips:function() {
+               var remove_clip_ary = new Array();
+               // Remove selected clips from display
+               $j( '.container_track .mv_selected_clip' ).each( function() {
+                       // grab the track index from the id (assumes track_#_clip_#
+                       remove_clip_ary.push ( $j( this ).parent().attr( 'id' ).replace( 'track_', '' ).replace( 'clip_', '' ).split( '_' ) );
+               } );
+               if ( remove_clip_ary.length != 0 )
+                       this.removeClips( remove_clip_ary );
+
+               // doEdit selected clips (updated selected resource)
+               // @@todo refresh menu of current
+               this.doEditSelectedClip();
+       },
+       /*
+       * Add a clip to the timeline
+       */      
+       addClip:function( clip, before_clip_pos, track_inx ) {
+               this.addClips( [clip],  before_clip_pos, track_inx )
+       },
+       /** 
+       * add a single or set of clips
+       * to a given position and track_inx
+       */
+       addClips:function( clipSet, before_clip_pos, track_inx ) {
+               this_seq = this;
+
+               if ( !track_inx )
+                       track_inx = this.plObj.default_track.inx;
+
+               if ( !before_clip_pos )
+                       before_clip_pos = this.plObj.default_track.getClipCount();
+
+               js_log( "seq: add clip: at: " + before_clip_pos + ' in track: ' + track_inx );
+               var cur_pos = before_clip_pos;
+
+               $j.each( clipSet, function( inx, clipInitDom ) {
+                       var mediaElement = document.createElement( 'ref' );
+                       for ( var i in clipInitDom ) {
+                               js_log( "set: " + i + ' to ' + clipInitDom[i] );
+                               if ( i != 'id' )
+                                       $j( mediaElement ).attr( i, clipInitDom[i] );
+                       }
+                       if ( this_seq.plObj.tryAddMedia(        mediaElement, cur_pos, track_inx ) )
+                               cur_pos++;
+               } );
+               // debugger;
+               this.do_refresh_timeline();
+       },
+       
+       /**
+       * Removes Clips listed in the remove_clip_ary paramater
+       */
+       removeClips:function( remove_clip_ary ) {
+               var this_seq = this;
+               var jselect = coma = '';
+               js_log( 'clip count before removal : ' + this_seq.plObj.default_track.clips.length + ' should remove ' + remove_clip_ary.length );
+               var afected_tracks = new Array();
+               // add order to track_clip before we start removing:
+               $j.each( remove_clip_ary, function( inx, track_clip ) {
+                       remove_clip_ary[inx]['order'] = this_seq.plObj.tracks[ track_clip[0] ].clips[ track_clip[1] ].order;
+               } );
+               $j.each( remove_clip_ary, function( inx, track_clip ) {
+                       var track_inx = track_clip[0];
+                       var clip_inx = track_clip[1];
+                       var clip_rm_order = track_clip['order'];
+                       js_log( 'remove t:' + track_inx + ' c:' + clip_inx + ' id:' + ' #track_' + track_inx + '_clip_' + clip_inx + ' order:' + clip_rm_order );
+                       // remove the clips from the base tracks
+                       for ( var i in this_seq.plObj.tracks[ track_inx ].clips ) {
+                               cur_clip = this_seq.plObj.tracks[ track_inx ].clips[i]
+                               if ( cur_clip.order == clip_rm_order ) {
+                                       this_seq.plObj.tracks[ track_clip[0] ].clips.splice( i, 1 );
+                               }
+                       }
+                       // add track to affected track list:
+                       afected_tracks[ track_inx ] = true;
+                       jselect += coma + '#track_' + track_inx + '_clip_' + clip_inx;
+                       coma = ',';
+               } );
+               // update/ reorder:
+               $j.each( afected_tracks, function( track_inx, affected ) {
+                       this_seq.plObj.tracks[track_inx].reOrderClips();
+               } );
+
+               js_log( 'clip count after removal : ' + this_seq.plObj.default_track.clips.length );
+               // animate the removal (@@todo should be able to call the resulting fadeOut only once without a flag)
+               var done_with_refresh = false;
+               $j( jselect ).fadeOut( "slow", function() {
+                       if ( !done_with_refresh )
+                               this_seq.do_refresh_timeline();
+                       done_with_refresh = true;
+               } ).empty(); // empty to remove any persistent bindings
+       },
+       doEdit:function( editObj ) {
+               // add the current editObj to the edit stack (should allow for "undo")
+               this.edit_stack.push( editObj );
+               // make the adjustments
+               this.makeAdjustment( editObj );
+       },
+       /*
+       * takes adjust ment object with options:
+       * track_inx, clip_inx, start, end delta
+       */
+       makeAdjustment:function( e ) {
+               switch( e.type ) {
+                       case 'resize_start':
+                               this.plObj.tracks[e.track_inx].clips[e.clip_inx].doAdjust( 'start', e.delta );
+                       break;
+                       case 'resize_end':
+                                this.plObj.tracks[e.track_inx].clips[e.clip_inx].doAdjust( 'end', e.delta );
+                       break;
+               }
+               js_log( 're render: ' + e.track_inx );
+               // refresh the playlist after adjustment
+               this.do_refresh_timeline();
+       },
+       // @@todo set up key bindings for undo
+       undoEdit:function() {
+               var editObj = this.edit_stack.pop();
+               // invert the delta
+
+       },
+       exc_track:function( inx, req ) {
+               this_seq = this;
+               if ( req == 'close' ) {
+                       $j( '#mv_exc_' + inx ).attr( 'href', 'javascript:' + this.instance_name + '.exc_track(' + inx + ',\'open\')' );
+                       $j( '#mv_exc_' + inx + ' > img' ).attr( 'src', mv_embed_path + 'images/closed.png' );
+                       $j( '#track_cnt_' + inx + ',#container_track_' + inx ).animate( { height:this.track_text_height }, "slow", '',
+                               function() {
+                                       this_seq.plObj.tracks[inx].disp_mode = 'text';
+                                       this_seq.render_tracks( inx );
+                               } );
+               } else if ( req == 'open' ) {
+                       $j( '#mv_exc_' + inx ).attr( 'href', 'javascript:' + this.instance_name + '.exc_track(' + inx + ',\'close\')' );
+                       $j( '#mv_exc_' + inx + ' > img' ).attr( 'src', mv_embed_path + 'images/opened.png' );
+                       $j( '#track_cnt_' + inx + ',#container_track_' + inx ).animate( { height:this.track_thumb_height }, "slow", '',
+                               function() {
+                                       this_seq.plObj.tracks[inx].disp_mode = 'timeline_thumb';
+                                       this_seq.render_tracks( inx );
+                               } );
+
+               }
+       },
+       // adds tracks
+       add_track:function( inx, track ) {
+
+       },
+       // toggle cut mode (change icon to cut)
+       cut_mode:function() {
+               js_log( 'do cut mode' );
+               // add cut layer ontop of clips
+       },
+       doAdvancedTl:function() {
+               this.timeline_mode = 'time';
+               this.renderTimeLine();
+               this.do_refresh_timeline();
+               return false;
+       },
+       doSimpleTl:function() {
+               this.timeline_mode = 'storyboard';
+               this.renderTimeLine();
+               this.do_refresh_timeline();
+               return false;
+       },
+       // renders updates the timeline based on the current scale
+       render_tracks:function( track_inx ) {
+               js_log( "f::render track: " + track_inx );
+               var this_seq = this;
+               // inject the tracks into the timeline (if not already there)
+               for ( var track_id in this.plObj.tracks ) {
+                       if ( track_inx == track_id || typeof track_inx == 'undefined' ) {
+                               // empty out the track container:
+                               // $j('#container_track_'+track_id).empty();
+                               var track_html = droppable_html = '';
+                               // set up per track vars:
+                               var track = this.plObj.tracks[track_id];
+                               var cur_clip_time = 0;
+
+                               // set up some constants for timeline_mode == storyboard:
+                               if ( this.timeline_mode == 'storyboard' ) {
+                                       var frame_width = Math.round( this.track_clipThumb_height * 1.3333333 );
+                                       var container_width = frame_width + 60;
+                               }
+
+                               // for each clip:
+                               for ( var j in track.clips ) {
+                                       clip = track.clips[j];
+                                       // var img = clip.getClipImg('icon');
+                                       if ( this.timeline_mode == 'storyboard' ) {
+                                               clip.left_px = j * container_width;
+                                               clip.width_px = container_width;
+                                               var base_id = 'track_' + track_id + '_clip_' + j;
+                                               track_html += '<span id="' + base_id + '" ' +
+                                                                               'class="mv_storyboard_container mv_clip_drag" ' +
+                                                                               'style="' +
+                                                                               'left:' + clip.left_px + 'px;' +
+                                                                               'height:' + ( this.track_clipThumb_height + 30 ) + 'px;' +
+                                                                               'width:' + ( container_width ) + 'px;" >';
+                                               track_html += clip.embed.renderTimelineThumbnail( {
+                                                                               'width' : frame_width,
+                                                                               'thumb_class' : 'mv_clip_thumb',
+                                                                               'height':this.track_clipThumb_height,
+                                                                               'time':0
+                                                                       } );
+                                               // render out edit button
+                                               /*track_html+='<div class="clip_edit_button clip_edit_base clip_control"/>';*/
+
+                                               // check if the clip has transitions
+                                               var imgHtml = '';
+                                               var imsrc = '';
+                                               var cat = clip;
+                                               if ( clip.transIn || clip.transOut ) {
+                                                       if ( clip.transIn && clip.transIn.getIconSrc )
+                                                               imsrc = clip.transIn.getIconSrc();
+                                                       // @@todo put transOut somewhere else
+                                                       if ( clip.transOut && clip.transOut.getIconSrc )
+                                                               imsrc = clip.transOut.getIconSrc();
+                                                       if ( imsrc != '' )
+                                                               imgHtml = '<img style="width:32px;height:32px" src="' + imsrc + '" />';
+                                               }
+                                               // render out transition edit box
+                                               track_html +=   '<div id="tb_' + base_id + '"  class="clip_trans_box">' +
+                                                                                       imgHtml +
+                                                                               '</div>'
+
+                                               // render out adjustment text
+                                               /*track_html+='<div id="' + base_id + '_adj' + '" class="mv_adj_text" style="top:'+ (this.track_clipThumb_height+10 )+'px;">'+
+                                                                               '<span class="mv_adjust_click" onClick="'+this.instance_name+'.adjClipDur(' + track_id + ',' + j + ',\'-\')" /> - </span>'+
+                                                                                 ( (clip.getDuration() > 60 )? seconds2npt(clip.getDuration()): clip.getDuration() )  +
+                                                                               '<span class="mv_adjust_click" onClick="'+this.instance_name+'.adjClipDur(' + track_id + ',' + j + ',\'+\')" /> + </span>'+
+                                                                       '</div>';
+                                               */
+                                               track_html += '</span>';
+
+                                       }
+                                       // do timeline_mode rendering:
+                                       if ( this.timeline_mode == 'time' ) {
+                                               clip.left_px = Math.round( cur_clip_time / this.timeline_scale );
+                                               clip.width_px = Math.round( Math.round( clip.getDuration() ) / this.timeline_scale );
+                                               clip.height_px = 60;
+                                               js_log( 'at time:' + cur_clip_time + ' left: ' + clip.left_px + ' clip dur: ' +  Math.round( clip.getDuration() ) + ' clip width:' + clip.width_px );
+
+                                               // for every clip_width pixle output image
+                                               if ( track.disp_mode == 'timeline_thumb' ) {
+                                                       track_html += '<span id="track_' + track_id + '_clip_' + j + '" ' +
+                                                                                       'class="mv_tl_clip mv_clip_drag" ' +
+                                                                                       'style="' +
+                                                                                               'left:' + clip.left_px + 'px;' +
+                                                                                               'width:' + clip.width_px + 'px;' +
+                                                                                               'height:' + clip.height_px + 'px" >';
+                                                       track_html += this.render_clip_frames( clip );
+                                               } else if ( track.disp_mode == 'text' ) {
+                                                       // '+left_px+
+                                                       track_html += '<span id="track_' + track_id + '_clip_' + j + '" style="left:' + clip.left_px + 'px;' +
+                                                               'width:' + clip.width_px + 'px;background:' + clip.getColor() +
+                                                                       '" class="mv_time_clip_text mv_clip_drag">' + clip.title;
+                                               }
+                                               // add in per clip controls
+                                               track_html += '<div title="' + gM( 'mwe-clip_in' ) + ' ' + clip.embed.start_ntp + '" class="ui-resizable-w ui-resizable-handle" style="width: 16px; height: 16px; left: 0px; top: 2px;background:url(\'' + mv_embed_path + 'images/application_side_contract.png\');" ></div>' + "\n";
+                                               track_html += '<div title="' + gM( 'mwe-clip_out' ) + ' ' + clip.embed.end_ntp + '" class="ui-resizable-e ui-resizable-handle" style="width: 16px; height: 16px; right: 0px; top: 2px;background:url(\'' + mv_embed_path + 'images/application_side_expand.png\');" ></div>' + "\n";
+                                               track_html += '<div title="' + gM( 'mwe-rmclip' ) + '" onClick="' + this.instance_name + '.removeClips(new Array([' + track_id + ',' + j + ']))" style="position:absolute;cursor:pointer;width: 16px; height: 16px; left: 0px; bottom:2px;background:url(\'' + mv_embed_path + 'images/delete.png\');"></div>' + "\n";
+                                               track_html += '<span style="display:none;" class="mv_clip_stats"></span>';
+
+                                               track_html += '</span>';
+                                               // droppable_html+='<div id="dropBefore_'+i+'_c_'+j+'" class="mv_droppable" style="height:'+this.track_thumb_height+'px;left:'+clip.left_px+'px;width:'+Math.round(clip.width_px/2)+'px"></div>';
+                                               // droppable_html+='<div id="dropAfter_'+i+'_c_'+j+'" class="mv_droppable" style="height:'+this.track_thumb_height+'px;left:'+(clip.left_px+Math.round(clip.width_px/2))+'px;width:'+(clip.width_px/2)+'px"></div>';
+                                               cur_clip_time += Math.round( clip.getDuration() ); // increment cur_clip_time
+                                       }
+
+                               }
+
+                               // js_log("new htmL for track i: "+track_id + ' html:'+track_html);
+                               $j( '#container_track_' + track_id ).html( track_html );
+
+                               // apply transition click action
+                               $j( '.clip_trans_box' ).click( function() {
+                                       if ( $j( this ).hasClass( 'mv_selected_transition' ) ) {
+                                               $j( this ).removeClass( 'mv_selected_transition' );
+                                               this_seq.deselectClip( $j( this ).siblings( '.mv_clip_thumb' ).get( 0 ) );
+                                       } else {
+                                               // deselect others
+                                               this_seq.deselectClip();
+                                               $j( '.clip_trans_box' ).removeClass( 'mv_selected_transition' );
+                                               $j( this ).addClass( "mv_selected_transition" );
+                                               $j( this ).siblings( '.mv_clip_thumb' ).addClass( "mv_selected_clip" );
+                                               var sClipObj = this_seq.getClipFromSeqID( $j( this ).parent().attr( 'id' ) );
+                                               // jump to the current clip
+                                               this_seq.plObj.updateCurrentClip( sClipObj  );
+                                               // display the transition edit tab:
+                                               this_seq.disp( 'transition' );
+                                       }
+                               } );
+
+                               // apply edit button mouse over effect:
+                               $j( '.clip_edit_button' ).hover( function() {
+                                       $j( this ).removeClass( "clip_edit_base" ).addClass( "clip_edit_over" );
+                               }, function() {
+                                       $j( this ).removeClass( "clip_edit_over" ).addClass( "clip_edit_base" );
+                               } ).click( function() {
+                                       // deselect everything else:
+                                       $j( '.mv_selected_clip' ).each( function( inx, selected_clip ) {
+                                               this_seq.deselectClip( this );
+                                       } );
+
+                                       var sClipObj = this_seq.getClipFromSeqID( $j( this ).parent().attr( 'id' ) );
+                                       this_seq.plObj.updateCurrentClip( sClipObj  );
+                                       // get the clip (siblings with mv_clip_thumb class)
+                                       var cur_clip_elm =  $j( this ).siblings( '.mv_clip_thumb' );
+                                       // select the clip (add mv_selected_clip if not already selected)
+                                       if ( ! $j( cur_clip_elm ).hasClass( "mv_selected_clip" ) ) {
+                                               $j( cur_clip_elm ).addClass( 'mv_selected_clip' );
+                                               $j( '#' + $j( cur_clip_elm ).parent().attr( "id" ) + '_adj' ).fadeIn( "fast" );
+                                       }
+                                       // display the edit tab:
+                                       this_seq.disp( 'clipedit' );
+                                       // display edit dialog:
+                                       this_seq.doEditClip( sClipObj );
+                               } );
+
+                               // apply onClick edit controls:
+                               $j( '.mv_clip_thumb' ).click( function() {
+                                       var cur_clip_click = this;
+                                       // if not in multi select mode remove all existing selections
+                                       // (except for the current click which is handled down below)
+                                       js_log( ' ks: ' + this_seq.key_shift_down + '  ctrl_down:' + this_seq.key_ctrl_down );
+                                       if ( ! this_seq.key_shift_down && ! this_seq.key_ctrl_down ) {
+                                               $j( '.mv_selected_clip' ).each( function( inx, selected_clip ) {
+                                                       if ( $j( this ).parent().attr( 'id' ) != $j( cur_clip_click ).parent().attr( 'id' )
+                                                               || ( $j( '.mv_selected_clip' ).length > 1 ) ) {
+                                                                       this_seq.deselectClip( this );
+                                                       }
+                                               } );
+                                       }
+
+                                       // jump to clip time
+                                       var sClipObj = this_seq.getClipFromSeqID( $j( this ).parent().attr( 'id' ) );
+                                       this_seq.plObj.updateCurrentClip( sClipObj  );
+                                       if ( $j( this ).hasClass( "mv_selected_clip" ) ) {
+                                               $j( this ).removeClass( "mv_selected_clip" );
+                                               $j( '#' + $j( this ).parent().attr( "id" ) + '_adj' ).fadeOut( "fast" );
+                                       } else {
+                                               $j( this ).addClass( 'mv_selected_clip' );
+                                               $j( '#' + $j( this ).parent().attr( "id" ) + '_adj' ).fadeIn( "fast" );
+                                       }
+                                       // if shift select is down select the in-between clips
+                                       if ( this_seq.key_shift_down ) {
+                                               // get the min max of current selection (within the current track)
+                                               var max_order = 0;
+                                               var min_order = 999999999;
+                                               $j( '.mv_selected_clip' ).each( function() {
+                                                       var cur_clip = this_seq.getClipFromSeqID( $j( this ).parent().attr( 'id' ) );
+                                                       // get min max
+                                                       if ( cur_clip.order < min_order )
+                                                               min_order = cur_clip.order;
+                                                       if ( cur_clip.order > max_order )
+                                                               max_order = cur_clip.order;
+                                               } );
+                                               // select all non-selected between max or min
+                                               js_log( 'sOrder: ' + sClipObj.order + ' min:' + min_order + ' max:' + max_order );
+                                               if ( sClipObj.order <= min_order ) {
+                                                       for ( var i = sClipObj.order; i <= max_order; i++ ) {
+                                                               $j( '#track_' + track_id + '_clip_' + i + ' > .mv_clip_thumb' ).addClass( 'mv_selected_clip' );
+                                                       }
+                                               }
+                                               if ( sClipObj.order >= max_order ) {
+                                                       for ( var i = min_order; i <= max_order; i++ ) {
+                                                               $j( '#track_' + track_id + '_clip_' + i + ' > .mv_clip_thumb' ).addClass( 'mv_selected_clip' );
+                                                       }
+                                               }
+                                       }
+                                       this_seq.doEditSelectedClip();
+                               } );
+                               // add in control for time based display
+                               // debugger;
+                               if ( this.timeline_mode == 'time' ) {
+                                       $j( '.ui-resizable-handle' ).mousedown( function() {
+                                               js_log( 'hid: ' +  $j( this ).attr( 'class' ) );
+                                               this_seq.resize_mode = ( $j( this ).attr( 'class' ).indexOf( 'ui-resizable-e' ) != -1 ) ?
+                                                                               'resize_end':'resize_start';
+                                       } );
+                               }
+                               var insert_key = 'na';
+                               // drag hooks:
+                               // @@todo support multiple clips
+                               for ( var j in track.clips ) {
+                                       $j( '#track_' + track_id + '_clip_' + j ).draggable( {
+                                               axis:'x',
+                                               containment:'#container_track_' + track_id,
+                                               opacity:50,
+                                               handle: ":not(.clip_control)",
+                                               scroll:true,
+                                               drag:function( e, ui ) {
+                                                       // debugger;
+                                                       insert_key = this_seq.clipDragUpdate( ui, this );
+                                               },
+                                               start:function( e, ui ) {
+                                                       js_log( 'start drag:' + this.id );
+                                                       // make sure we are ontop
+                                                       $j( this ).css( { top:'0px', zindex:10 } );
+                                               },
+                                               stop:function( e, ui ) {
+                                                       $j( this ).css( { top:'0px', zindex:0 } );
+
+                                                       var id_parts = this.id.split( '_' );
+                                                       var track_inx = id_parts[1];
+                                                       var clip_inx = id_parts[3];
+                                                       var clips = this_seq.plObj.tracks[track_inx].clips;
+                                                       var cur_drag_clip = clips[clip_inx];
+
+                                                       if ( insert_key != 'na' && insert_key != 'end' ) {
+                                                               cur_drag_clip.order = insert_key - .5;
+                                                       } else if ( insert_key == 'end' ) {
+                                                               cur_drag_clip.order = clips.length;
+                                                       }
+                                                       // reorder array based on new order
+                                                       clips.sort( sort_func );
+                                                       function sort_func( a, b ) {
+                                                               return a.order - b.order;
+                                                       }
+                                                       // assign keys back to order:
+                                                       this_seq.plObj.tracks[track_inx].reOrderClips();
+                                                       // redraw:
+                                                       this_seq.do_refresh_timeline();
+                                               }
+                                       } );
+                                       // add in resize hook if in time mode:
+                                       if ( this.timeline_mode == 'time' ) {
+                                               $j( '#track_' + track_id + '_clip_' + j ).resizable( {
+                                                       minWidth:10,
+                                                       maxWidth:6000,
+                                                       start: function( e, ui ) {
+                                                               // set border to red
+                                                               $j( this ).css( { 'border':'solid thin red' } );
+                                                               // fade In Time stats (end or start based on handle)
+                                                               // dragging east (adjusting end time)
+                                                               js_log( 'append to: ' + this.id );
+                                                               $j( '#' + this.id + ' > .mv_clip_stats' ).fadeIn( "fast" );
+                                                       },
+                                                       stop: function( e, ui ) {
+                                                               js_log( 'stop resize' );
+                                                               // restore border
+                                                               $j( this ).css( 'border', 'solid thin white' );
+                                                               // remove stats
+                                                               var clip_drag = this;
+                                                               $j( '#' + this.id + ' > .mv_clip_stats' ).fadeOut( "fast", function() {
+                                                                       var id_parts = clip_drag.id.split( '_' );
+                                                                       var track_inx = id_parts[1];
+                                                                       var clip_inx = id_parts[3];
+                                                                       // update clip
+                                                                       this_seq.doEdit( {
+                                                                               type:this_seq.resize_mode,
+                                                                               delta:this_seq.edit_delta,
+                                                                               track_inx:track_inx,
+                                                                               clip_inx:clip_inx } )
+                                                                       } );
+                                                       },
+                                                       resize: function( e, ui ) {
+                                                               // update time stats & render images:
+                                                               this_seq.update_clip_resize( this );
+                                                       }
+                                               } );
+                                       }
+                               }
+                               $j( '#container_track_' + track_id ).width( Math.round( this.timeline_duration / this.timeline_scale ) );
+                       }
+                       // debugger;
+               }
+       },
+       clipDragUpdate:function( ui, clipElm ) {
+               var this_seq = this;
+
+               var insert_key = 'na';
+               // animate re-arrange by left position:
+               // js_log('left: '+ui.position.left);
+               // locate clip (based on clip duration not animate)
+               var id_parts = clipElm.id.split( '_' );
+               var track_inx = id_parts[1];
+               var clip_inx = id_parts[3];
+               var clips = this_seq.plObj.tracks[track_inx].clips;
+               var cur_drag_clip = clips[clip_inx];
+               var return_org = true;
+               $j( clipElm ).css( 'zindex', 10 );
+               // find out where we are inserting and set left border to solid red thick
+               for ( var k in clips ) {
+                       if (    ui.position.left > clips[k].left_px &&
+                               ui.position.left < ( clips[k].left_px + clips[k].width_px ) ) {
+                               if ( clip_inx != k ) {
+                                       // also make sure we are not where we started
+                                       if ( k - 1 != clip_inx ) {
+                                               $j( '#track_' + track_inx + '_clip_' + k ).css( 'border-left', 'solid thick red' );
+                                               insert_key = k;
+                                       } else {
+                                               insert_key = 'na';
+                                       }
+                               } else {
+                                       insert_key = 'na';
+                               }
+                       } else {
+                               $j( '#track_' + track_inx + '_clip_' + k ).css( 'border-left', 'solid thin white' );
+                       }
+               }
+               // if greater than the last k insert after
+               if ( ui.position.left > ( clips[k].left_px + clips[k].width_px ) &&
+                       k != clip_inx ) {
+                               $j( '#track_' + track_inx + '_clip_' + k ).css( 'border-right', 'solid thick red' );
+                               insert_key = 'end';
+               } else {
+                       $j( '#track_' + track_inx + '_clip_' + k ).css( 'border-right', 'solid thin white' );
+               }
+               return insert_key;
+       },
+       deselectClip:function( clipElm ) {
+               if ( !clipElm ) {
+                       $j( '.mv_selected_clip' ).removeClass( "mv_selected_clip" );
+               } else {
+                       $j( clipElm ).removeClass( "mv_selected_clip" );
+                       // make sure the transition sibling is removed:
+                       $j( clipElm ).siblings( '.clip_trans_box' ).removeClass( 'mv_selected_transition' );
+                       $j( '#' + $j( clipElm ).parent().attr( "id" ) + '_adj' ).fadeOut( "fast" );
+               }
+       },
+       getClipFromSeqID:function( clip_seq_id ) {
+               js_log( 'get id from: ' + clip_seq_id );
+               var ct = clip_seq_id.replace( 'track_', '' ).replace( 'clip_', '' ).split( '_' );
+               return this.plObj.tracks[ ct[0] ].clips[ ct[1] ];
+       },
+       // renders clip frames
+       render_clip_frames:function( clip, frame_offset_count ) {
+               js_log( 'f:render_clip_frames: ' + clip.id + ' foc:' + frame_offset_count );
+               var clip_frames_html = '';
+               var frame_width = Math.round( this.track_thumb_height * 1.3333333 );
+
+               var pint = ( frame_offset_count == null ) ? 0:frame_offset_count * frame_width;
+
+               // js_log("pinit: "+ pint+ ' < '+clip.width_px+' ++'+frame_width);
+               for ( var p = pint; p < clip.width_px; p += frame_width ) {
+                       var clip_time = ( p == 0 ) ? 0:Math.round( p * this.timeline_scale );
+                       js_log( 'rendering clip frames: p:' + p + ' pts:' + ( p * this.timeline_scale ) + ' time:' + clip_time + ' height:' + this.track_thumb_height );
+                       clip_frames_html += clip.embed.renderTimelineThumbnail( {
+                               'width':  frame_width,
+                               'thumb_class':'mv_tl_thumb',
+                               'height': this.track_thumb_height,
+                               'size' : "icon", // set size to "icon" preset
+                               'time':   clip_time
+                       } );
+               }
+               js_log( 'render_clip_frames:' + clip_frames_html );
+               return clip_frames_html;
+       },
+       update_clip_resize:function( clip_element ) {
+               // js_log('update_clip_resize');
+               var this_seq = this;
+               var id_parts = clip_element.id.split( '_' );
+               track_inx = id_parts[1];
+               clip_inx = id_parts[3];
+               // set clip:
+               var clip = this.plObj.tracks[ track_inx ].clips[ clip_inx ];
+               var clip_desc = '';
+               // would be nice if getting the width did not flicker the border
+               // @@todo do a work around e in resize function has some screen based offset values
+               clip.width_px = $j( clip_element ).width();
+               var width_dif = clip.width_px - Math.round( Math.round( clip.getDuration() ) / this.timeline_scale );
+               // var left_px = $j(clip_element).css('left');
+
+               var new_clip_dur = Math.round( clip.width_px * this.timeline_scale );
+               var clip_dif = ( new_clip_dur - clip.getDuration() );
+               var clip_dif_str = ( clip_dif > 0 ) ? '+' + clip_dif:clip_dif;
+               // set the edit global delta
+               this.edit_delta = clip_dif;
+
+               // get new length:
+               clip_desc += 'length: ' + seconds2npt( new_clip_dur ) + '(' + clip_dif_str + ')';
+               if ( this_seq.resize_mode == 'resize_end' ) {
+                       // expanding right
+                       var new_end = seconds2npt( npt2seconds( clip.embed.end_ntp ) + clip_dif );
+                       clip_desc += '<br>end time: ' + new_end;
+                       // also shift all the other clips (after the current)
+                       // js_log("track_inx: " + track_inx + ' clip inx:'+clip_inx);
+                       // $j('#container_track_'+track_inx+' > .mv_clip_drag :gt('+clip_inx+')').each(function(){
+                       $j( '#container_track_' + track_inx + ' > :gt(' + clip_inx + ')' ).each( function() {
+                               var move_id_parts = this.id.split( '_' );
+                               var move_clip = this_seq.plObj.tracks[move_id_parts[1]].clips[move_id_parts[3]];
+                               // js_log('should move:'+ this.id);
+                               $j( this ).css( 'left', move_clip.left_px + width_dif );
+                       } );
+               } else {
+                       // expanding left (resize_start)
+                       var new_start = seconds2npt( npt2seconds( clip.embed.start_ntp ) + clip_dif );
+                       clip_desc += '<br>start time: ' + new_start;
+               }
+
+               // update clip stats:
+               $j( '#' + clip_element.id + ' > .mv_clip_stats' ).html( clip_desc );
+               var frame_width = Math.round( this.track_thumb_height * 1.3333333 );
+               // check if we need to append some images:
+               var frame_count = $j( '#' + clip_element.id + ' > img' ).length;
+               if ( clip.width_px > ( frame_count *  frame_width ) ) {
+                       // if dragging left append
+                       js_log( 'width_px:' + clip.width_px + ' framecount:' + frame_count + ' Xcw=' + ( frame_count *  frame_width ) );
+                       $j( '#' + clip_element.id ).append( this.render_clip_frames( clip, frame_count ) );
+               }
+       },
+       // renders cnt_time
+       render_playheadhead_seeker:function() {
+               js_log( 'render_playheadhead_seeker' );
+               // render out time stamps and time "jump" links
+               // first get total width
+
+               // remove the old one if its still there
+               $j( '#' + this.timeline_id + '_pl_control' ).remove();
+               // render out a playlist clip wide and all the way to the right (only playhead and play button) (outside of timeline)
+               $j( this.target_sequence_container ).append( '<div id="' + this.timeline_id + '_pl_control"' +
+                       ' style="position:absolute;top:' + ( this.plObj.height ) + 'px;' +
+                       'right:1px;width:' + this.plObj.width + 'px;height:' + this.plObj.org_control_height + '" ' +
+                       'class="' + this.plObj.ctrlBuilder.pClass + '"><div class="ui-widget ui-corner-bottom ui-state-default control-bar">' +
+                                        this.plObj.getControlsHTML() +
+                                '</div>' +
+                       '</div>' );
+               // update time and render out clip dividers .. should be used to show load progress
+               this.plObj.updateBaseStatus();
+
+               // once the controls are in the DOM add hooks:
+               this.plObj.ctrlBuilder.addControlHooks( $j( '#' + this.timeline_id + '_pl_control' ) );
+
+               // render out the "jump" div
+               if ( this.timeline_mode == 'time' ) {
+                       /*$j('#'+this.timeline_id+'_head_jump').width(pixle_length);
+                       //output times every 50pixles
+                       var out='';
+                       //output time-desc every 50pixles and jump links every 10 pixles
+                       var n=0;
+                       for(i=0;i<pixle_length;i+=10){
+                               out+='<div onclick="'+this.instance_name+'.jt('+i*this.timeline_scale+');"' +
+                                               ' style="z-index:2;position:absolute;left:'+i+'px;width:10px;height:20px;top:0px;"></div>';
+                               if(n==0)
+                                       out+='<span style="position:absolute;left:'+i+'px;">|'+seconds2npt(Math.round(i*this.timeline_scale))+'</span>';
+                               n++;
+                               if(n==10)n=0;
+                       }*/
+
+               }
+       },
+       jt:function( jh_time ) {
+               js_log( 'jt:' + jh_time );
+               var this_seq = this;
+               this.playline_time = jh_time;
+               js_log( 'time: ' + seconds2npt( jh_time ) + ' ' + Math.round( jh_time / this.timeline_scale ) );
+               // render playline at given time
+               $j( '#' + this.timeline_id + '_playline' ).css( 'left', Math.round( jh_time / this.timeline_scale ) + 'px' );
+               cur_pl_time = 0;
+               // update the thumb with the requested time:
+               this.plObj.updateThumbTime( jh_time );
+       },
+       // adjusts the current scale
+       zoom_in:function() {
+               this.timeline_scale = this.timeline_scale * .75;
+               this.do_refresh_timeline();
+               js_log( 'zoomed in:' + this.timeline_scale );
+       },
+       zoom_out:function() {
+               this.timeline_scale = this.timeline_scale * ( 1 + ( 1 / 3 ) );
+               this.do_refresh_timeline();
+               js_log( 'zoom out: ' + this.timeline_scale );
+       },
+       do_refresh_timeline:function( preserve_selection ) {
+               js_log( 'Sequencer:do_refresh_timeline()' );
+               // @@todo should "lock" interface while refreshing timeline
+               var pSelClips = [];
+               if ( preserve_selection ) {
+                       $j( '.mv_selected_clip' ).each( function() {
+                               pSelClips.push( $j( this ).parent().attr( 'id' ) );
+                       } );
+               }
+               // regen duration
+               this.plObj.getDuration( true );
+               // refresh player:
+               this.plObj.getHTML();
+
+               // this.render_playheadhead_seeker();
+               this.render_tracks();
+               this.jt( this.playline_time );
+
+               if ( preserve_selection ) {
+                       for ( var i = 0; i < pSelClips.length; i++ ) {
+                               $j( '#' + pSelClips[i] + ' .mv_clip_thumb' ).addClass( 'mv_selected_clip' );
+                       }
+               }
+       }
+
+}
+/* extension to mvPlayList to support sequencer features properties */
+var mvSeqPlayList = function( element ) {
+       return this.init( element );
+}
+mvSeqPlayList.prototype = {
+       init:function( element ) {
+               var myPlObj = new mvPlayList( element );
+
+               // inherit mvClip
+               for ( var method in myPlObj ) {
+                       if ( typeof this[method] != 'undefined' ) {
+                               this[ 'parent_' + method ] = myPlObj[method];
+                       } else {
+                               this[method] = myPlObj[method];
+                       }
+               }
+
+               this.org_control_height = this.pl_layout.control_height;
+               // do specific mods:(controls and title are managed by the sequencer)
+               this.pl_layout.title_bar_height = 0;
+               this.pl_layout.control_height = 0;
+       },
+       setSliderValue:function( perc ) {
+               js_log( 'setSliderValue::' + perc );
+               // get the track_clipThumb_height from parent mvSequencer
+               var frame_width = Math.round( this.pSeq.track_clipThumb_height * 1.3333333 );
+               var container_width = frame_width + 60;
+
+               var perc_clip = this.cur_clip.embed.currentTime / this.cur_clip.getDuration();
+
+               var left_px = parseInt( ( this.cur_clip.order * container_width ) + ( frame_width * perc_clip ) ) + 'px';
+               js_log( "set " + perc + ' of cur_clip: ' + this.cur_clip.order + ' lp:' + left_px );
+
+
+               // update the timeline playhead and
+               $j( '#' + this.seqObj.timeline_id + '_playline' ).css( 'left', left_px );
+
+               // pass update request to parent:
+               this.parent_setSliderValue( perc );
+       },
+       getControlsHTML:function() {
+               // get controls from current clip add some playlist specific controls:
+               this.cur_clip.embed.supports['prev_next'] = true;
+               this.cur_clip.embed.supports['options']   = false;
+               return ctrlBuilder.getControls( this.cur_clip.embed );
+       },
+       // override renderDisplay
+       renderDisplay:function() {
+               js_log( 'mvSequence:renderDisplay' );
+               // setup layout for title and dc_ clip container
+               $j( this ).html( '<div id="dc_' + this.id + '" style="width:' + this.width + 'px;' +
+                               'height:' + ( this.height ) + 'px;position:relative;" />' );
+
+               this.setupClipDisplay();
+       }
+};
diff --git a/js2/mwEmbed/libSequencer/mvTimedEffectsEdit.js b/js2/mwEmbed/libSequencer/mvTimedEffectsEdit.js
new file mode 100644 (file)
index 0000000..0edb752
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+* mvTimedEffectsEdit
+*
+* for now just simple single stack transition control
+*
+*/
+
+// add our local msgs
+loadGM( {
+       "mwe-transition_in" : "Transition in",
+       "mwe-transition_out" : "Transition out",
+       "mwe-effects" : "Effects stack",
+       "mwe-remove_transition" : "Remove transition",
+       "mwe-edit_transin" : "Edit transition into clip",
+       "mwe-edit_transout" : "Edit transition out of clip",
+       "mwe-add-transition" : "Add a transition"
+} );
+
+var default_timed_effect_values = {
+       'rObj': null,            // the resource object
+       'clip_disp_ct':null, // target clip disp
+       'control_ct':null,       // control container
+
+       'parent_ct': null,       // parent container
+       'pSeq': null,    // parent sequence Object
+
+       'edit_action': null, // the requested edit action
+};
+
+var mvTimedEffectsEdit = function( iObj ) {
+       return this.init( iObj );
+};
+// set up the mvSequencer object
+mvTimedEffectsEdit.prototype = {
+       // the menu_items Object contains: default html, js setup/loader functions
+       menu_items : {
+               'transin': {
+                       'title':gM( 'mwe-transition_in' ),
+                       'clip_attr':'transIn',
+                       'doEdit':function( _this ) {
+                               _this.doTransitionDisplayEdit( 'transin' );
+                       }
+               },
+               'transout': {
+                       'title':gM( 'mwe-transition_out' ),
+                       'clip_attr':'transOut',
+                       'doEdit':function( _this ) {
+                               _this.doTransitionDisplayEdit( 'transout' );
+                       }
+               },
+               'effects': {
+                       'title':gM( 'mwe-effects' ),
+                       'clip_attr':'Effects',
+                       'doEdit':function( _this ) {
+                               // display
+                               _this.doEditEffectDisplayEdit();
+                       }
+               }
+       },
+       init:function( iObj ) {
+               // init object:
+               for ( var i in default_timed_effect_values ) {
+                       if ( iObj[i] ) {
+                               this[i] = iObj[i];
+                       }
+               }
+               this.doEditMenu();
+       },
+       doEditMenu:function() {
+               js_log( 'mvTimedEffects : doEditMenu::' );
+               var _this = this;
+               // add in subMenus if set
+               // check for submenu and add to item container
+
+               // update the default edit display (if we have a target)
+               var tTarget = 'transin';
+               if ( this.rObj.transOut )
+                       tTarget = 'transout';
+               if ( this.rObj.effects )
+                       tTarget = 'effects';
+
+               var o = '';
+               var tabc = '';
+               o += '<div id="mv_submenu_timedeffect">';
+               o += '<ul>';
+               var inx = 0;
+               var selected_tab = 0;
+               $j.each( this.menu_items, function( sInx, mItem ) {
+                       if ( sInx == tTarget ) {
+                               selected_tab = inx;
+                       }
+                       // check if the given editType is valid for our given media type
+                       o +=    '<li>' +
+                                       '<a id="mv_te_' + sInx + '" href="#te_' + sInx + '">' + mItem.title + '</a>' +
+                               '</li>';
+                       tabc += '<div id="te_' + sInx + '" style="overflow:auto;" ></div>';
+                       inx++;
+               } );
+               o += '</ul>' + tabc;
+               o += '</div>';
+               // add sub menu container with menu html:
+               $j( '#' + this.control_ct ).html( o ) ;
+               js_log( 'should have set: #' + this.control_ct + ' to: ' + o );
+               // set up bindins:
+               $j( '#mv_submenu_timedeffect' ).tabs( {
+                       selected: selected_tab,
+                       select: function( event, ui ) {
+                               _this.doDisplayEdit( $j( ui.tab ).attr( 'id' ).replace( 'mv_te_', '' ) );
+                       }
+               } ).addClass( 'ui-tabs-vertical ui-helper-clearfix' );
+               // close left:
+               $j( "#mv_submenu_clipedit li" ).removeClass( 'ui-corner-top' ).addClass( 'ui-corner-left' );
+               _this.doDisplayEdit( tTarget );
+       },
+       doDisplayEdit:function( tab_id ) {
+               // @@todo fix the double display of doDisplayEdit
+               js_log( "doDisplayEdit::" );
+               if ( !this.menu_items[ tab_id ] ) {
+                       js_log( 'error: doDisplayEdit missing item:' + tab_id );
+               } else {
+                       // use the menu_item config to map to function display
+                       this.menu_items[tab_id].doEdit( this );
+               }
+       },
+       doEditEffectDisplayEdit:function() {
+               var _this = this;
+               var appendTarget = '#te_effects';
+               js_log( 'type:' + _this.rObj['type'] );
+               $j( appendTarget ).html( gM( 'mwe-loading_txt' ) );
+               // @@todo integrate into core and loading system:
+               loadExternalJs( mv_embed_path + 'libClipEdit/pixastic-editor/editor.js?' + getMwReqParam() );
+               loadExternalJs( mv_embed_path + 'libClipEdit/pixastic-editor/pixastic.all.js?' + getMwReqParam() );
+               loadExternalJs( mv_embed_path + 'libClipEdit/pixastic-editor/ui.js?' + getMwReqParam() );
+               loadExternalJs( mv_embed_path + 'libClipEdit/pixastic-editor/uidata.js?' + getMwReqParam() );
+               loadExternalCss( mv_embed_path + 'libClipEdit/pixastic-editor/pixastic.all.js?' + getMwReqParam() );
+
+               var isPixasticReady = function() {
+                       if ( typeof PixasticEditor != 'undefined' ) {
+                               $j( appendTarget ).html( '<a href="#" class="run_effect_demo">Run Pixastic Editor Demo</a> (not yet fully integrated/ super alpha)<br> best to view <a href="http://www.pixastic.com/editor-test/">stand alone</a>' );
+                               $j( appendTarget + ' .run_effect_demo' ).click( function() {
+                                       var cat = _this;
+                                       var imgElm = $j( '.clip_container:visible  img' ).get( 0 );
+                                       PixasticEditor.load( imgElm );
+                               } );
+                       } else {
+                               setTimeout( isPixasticReady, 100 )
+                       }
+               }
+               isPixasticReady();
+       },
+       doTransitionDisplayEdit:function( target_item ) {
+               var _this = this;
+               js_log( "doTransitionDisplayEdit: " + target_item );
+               var apendTarget = '#te_' + target_item;
+               // check if we have a transition of type clip_attr
+               if ( !this.rObj[ this.menu_items[ target_item ].clip_attr ] ) {
+                       // empty append the transition list:
+                       this.getTransitionListControl( apendTarget );
+                       return ;
+               }
+               var cTran = this.rObj[ this.menu_items[ target_item ].clip_attr ];
+               var o = '<h3>' + gM( 'mwe-edit_' + target_item ) + '</h3>';
+               o += 'Type: ' +
+                       '<select class="te_select_type">';
+               for ( var typeKey in mvTransLib.type ) {
+                       var selAttr = ( cTran.type == typeKey ) ? ' selected':'';
+                       o += '<option   value="' + typeKey + '"' + selAttr + '>' + typeKey + '</option>';
+               }
+               o += '</select><br>';
+               o += '<span class="te_subtype_container"></span>';
+
+               // add html and select bindings
+               $j( apendTarget ).html( o ).children( '.te_select_type' )
+                       .change( function() {
+                               var selectedType = $j( this ).val();
+                               // update subtype listing:
+                               _this.getSubTypeControl( target_item, selectedType, apendTarget + ' .te_subtype_container' );
+                       } );
+               // add subtype control
+               _this.getSubTypeControl( target_item, cTran.type, apendTarget + ' .te_subtype_container' );
+
+               // add remove transition button:
+               $j( apendTarget ).append( '<br><br>' + $j.btnHtml( gM( 'mwe-remove_transition' ), 'te_remove_transition', 'close'  ) )
+                       .children( '.te_remove_transition' )
+                       .click( function() {
+                               // remove the transtion from the playlist
+                               _this.pSeq.plObj.transitions[cTran.id] = null;
+                               // remove the transtion from the clip:
+                               _this.rObj[ _this.menu_items[ target_item ].clip_attr ] = null;
+                               // update the interface:
+                               _this.doTransitionDisplayEdit( target_item );
+                               // update the sequence
+                               _this.pSeq.do_refresh_timeline();
+                       } );
+       },
+       getSubTypeControl:function( target_item, transition_type, htmlTarget ) {
+               var _this = this;
+               var cTran = this.rObj[ this.menu_items[ target_item ].clip_attr ];
+               var o = 'Sub Type:<select class="te_subtype_select">';
+               for ( var subTypeKey in mvTransLib.type[ transition_type ] ) {
+                       var selAttr = ( cTran.subtype == subTypeKey ) ? ' selected' : '';
+                       o += '<option   value="' + subTypeKey + '"' + selAttr + '>' + subTypeKey + '</option>';
+               }
+               o += '</select><br>';
+               $j( htmlTarget ).html( o )
+                       .children( '.te_subtype_select' )
+                       .change( function() {
+                               // update the property
+                               cTran.subtype = $j( this ).val();
+                               // re-gen timeline / playlist
+                               _this.pSeq.do_refresh_timeline();
+                               // (re-select self?)
+                               _this.getSubTypeControl( target_item, transition_type, htmlTarget );
+               } );
+               var o = '';
+               // check for extra properties control:
+               for ( var i = 0; i < mvTransLib.type[ transition_type ][ cTran.subtype ].attr.length; i++ ) {
+                       var tAttr = mvTransLib.type[ transition_type ][ cTran.subtype ].attr[i]
+                       switch( tAttr ) {
+                               case 'fadeColor':
+                                       var cColor = ( cTran['fadeColor'] ) ? cTran['fadeColor']:'';
+                                       $j( htmlTarget ).append( 'Select Color: <div class="colorSelector"><div class="colorIndicator" style="background-color: ' + cColor + '"></div></div>' );
+                                       js_log( 'cs target: ' + htmlTarget + ' .colorSelector' );
+
+
+                                       $j( htmlTarget + ' .colorSelector' ).ColorPicker( {
+                                               color: cColor,
+                                               onShow: function ( colpkr ) {
+                                                       // make sure its ontop:
+                                                       $j( colpkr ).css( "zIndex", "12" );
+                                                       $j( colpkr ).fadeIn( 500 );
+                                                       return false;
+                                               },
+                                               onHide: function ( colpkr ) {
+                                                       $j( colpkr ).fadeOut( 500 );
+                                                       _this.pSeq.plObj.setCurrentTime( 0, function() {
+                                                               js_log( "render ready" );
+                                                       } );
+                                                       return false;
+                                               },
+                                               onChange: function ( hsb, hex, rgb ) {
+                                                       $j( htmlTarget + ' .colorIndicator' ).css( 'backgroundColor', '#' + hex );
+                                                       // update the transition
+                                                       cTran['fadeColor'] =  '#' + hex;
+                                               }
+                                       } )
+                               break;
+                       }
+               }
+               // and finally add effect timeline scruber (for timed effects this also stores keyframes)
+
+       },
+       getTransitionListControl : function( target_out ) {
+               js_log( "getTransitionListControl" );
+               var o = '<h3>' + gM( 'mwe-add-transition' ) + '</h3>';
+               for ( var type in mvTransLib['type'] ) {
+                       js_log( 'on tran type: ' + i );
+                       var base_trans_name = i;
+                       var tLibSet = mvTransLib['type'][ type ];
+                       for ( var subtype in tLibSet ) {
+                               o += '<img style="float:left;padding:10px;" ' +
+                                       'src="' + mvTransLib.getTransitionIcon( type, subtype ) + '">';
+                       }
+               }
+               $j( target_out ).html( o );
+       }
+};
diff --git a/js2/mwEmbed/libSequencer/seqRemoteSearchDriver.js b/js2/mwEmbed/libSequencer/seqRemoteSearchDriver.js
new file mode 100644 (file)
index 0000000..25aa0c2
--- /dev/null
@@ -0,0 +1,184 @@
+/*the sequence remote search driver
+        extends the base remote search driver with sequence specific stuff
+*/
+
+var seqRemoteSearchDriver = function( iObj ) {
+       return this.init( iObj )
+}
+seqRemoteSearchDriver.prototype = {
+       sequence_add_target:false,
+       init:function( this_seq ) {
+               var _this = this;
+               js_log( "init:seqRemoteSearchDriver" );
+               // setup remote search driver with a seq parent:
+               this.pSeq = this_seq;
+               var iObj = {
+                       'target_container'      : '#cliplib_ic',
+                       'local_wiki_api_url': this_seq.getLocalApiUrl(),
+                       'instance_name'         : this_seq.instance_name + '.mySearch',
+                       'default_query'         : this.pSeq.plObj.title
+               }
+               if ( typeof this_seq.amw_conf != 'undefined' )
+                       $j.extend( iObj,  this_seq.amw_conf );
+                       
+       
+               // inherit the remoteSearchDriver properties:n
+               var tmpRSD = new remoteSearchDriver( iObj );
+               for ( var i in tmpRSD ) {
+                       if ( this[i] ) {
+                               this['parent_' + i] = tmpRSD[i];
+                       } else {
+                               this[i] = tmpRSD[i];
+                       }
+               }
+               // extend parent_do_refresh_timeline actions:
+               if ( !this.pSeq.parent_do_refresh_timeline ) {
+                       this.pSeq.parent_do_refresh_timeline = this.pSeq.do_refresh_timeline;
+                       this.pSeq.do_refresh_timeline = function() {
+                               js_log( "seqRemoteSearchDriver::" + _this.pSeq.disp_menu_item );
+                               // call the parent
+                               _this.pSeq.parent_do_refresh_timeline();
+                               // add our local bindings
+                               _this.addResultBindings();
+                               return true;
+                       }
+               }
+       },
+       resourceEdit:function() {
+               var _this = this;
+
+       },
+       addResultBindings:function() {
+               // set up seq:
+               var _this = this;
+               // setup parent bindings:
+               this.parent_addResultBindings();
+
+               // Add an additional click binding
+               $j( '.rsd_res_item' ).click( function() {
+                       js_log( 'SeqRemoteSearch: rsd_res_item: click (remove sequence_add_target)' );
+                       _this.sequence_add_target = false;
+               } );
+
+               // Add an additional drag binding
+               $j( '.rsd_res_item' ).draggable( 'destroy' ).draggable( {
+                       helper:function() {
+                               return $j( this ). clone ().appendTo( 'body' ).css( { 'z-index':9999 } ).get( 0 );
+                       },
+                       revert:'invalid',
+                       start:function() {
+                               js_log( 'start drag' );
+                       }
+               } );
+               $j( ".mv_clip_drag" ).droppable( 'destroy' ).droppable( {
+                       accept: '.rsd_res_item',
+                       over:function( event, ui ) {
+                               // js_log("over : mv_clip_drag: " + $j(this).attr('id') );
+                               $j( this ).css( 'border-right', 'solid thick red' );
+                       },
+                       out:function( event, ui ) {
+                               $j( this ).css( 'border-right', 'solid thin white' );
+                       },
+                       drop: function( event, ui ) {
+                               $j( this ).css( 'border-right', 'solid thin white' );
+                               js_log( "Droped: " + $j( ui.draggable ).attr( 'id' ) + ' on ' +  $j( this ).attr( 'id' ) );
+                               _this.sequence_add_target =  $j( this ).attr( 'id' );
+                               // load the orginal draged item
+                               var rObj = _this.getResourceFromId( $j( ui.draggable ).attr( 'id' ) );
+                               _this.resourceEdit( rObj, ui.draggable );
+                       }
+               } );
+
+       },
+       insertResource:function( rObj ) {
+               var _this = this;
+               js_log( "SEQ insert resource after:" + _this.sequence_add_target  + ' of type: ' + rObj.mime );
+               if ( _this.sequence_add_target ) {
+                       var tClip = _this.pSeq.getClipFromSeqID( _this.sequence_add_target );
+                       var target_order = false;
+                       if ( tClip )
+                               var target_order = tClip.order;
+               }
+               // @@todo show watting of sorts.
+
+               // get target order:
+               var cat = rObj;
+               // check for target insert path
+               this.checkImportResource( rObj, function() {
+
+                       var clipConfig = {
+                               'type'   : rObj.mime,
+                               'uri'    : _this.fileNS + ':' + rObj.target_resource_title,
+                               'title'  : rObj.title
+                       };
+                       // Set via local properties if available 
+                       clipConfig['src'] = ( rObj.local_src ) ? rObj.local_src : rObj.src;
+                       clipConfig['poster'] = ( rObj.local_poster ) ? rObj.local_poster : rObj.poster;
+
+                       if ( rObj.start_time && rObj.end_time ) {
+                               clipConfig['dur'] = npt2seconds( rObj.end_time ) - npt2seconds( rObj.start_time );
+                       } else {
+                               // Provide a default duration if none set
+                               clipConfig['dur'] = 4;
+                       }
+
+                       // Create the media element (target order+1 (since we insert (after)
+                       _this.pSeq.plObj.tryAddMediaObj( clipConfig, ( parseInt( target_order ) + 1 ) );
+                       
+                       // Refresh the timeline:
+                       _this.pSeq.do_refresh_timeline();
+                       js_log( "run close all: " );
+                       _this.closeAll();
+               } );
+       },
+       getClipEditControlActions:function() {
+               var _this = this;
+               return {
+                       'insert_seq':function( rObj ) {
+                               _this.insertResource( rObj )
+                       },
+                       'cancel':function( rObj ) {
+                               _this.cancelClipEditCB( rObj )
+                       }
+               };
+       },
+       resourceEdit:function( rObj, rsdElement ) {
+               var _this = this;
+               // don't resize to default (full screen behavior)
+               _this.dmodalCss = { };
+               // open up a new target_contaienr:
+               if ( $j( '#seq_resource_import' ).length == 0 )
+                       $j( 'body' ).append( '<div id="seq_resource_import" style="position:relative"></div>' );
+               var bConf = { };
+               bConf[ gM( 'mwe-cancel' ) ] = function() {
+                       $j( this ).dialog( "close" );
+               }
+               $j( '#seq_resource_import' ).dialog( 'destroy' ).dialog( {
+                       bgiframe: true,
+                       width:750,
+                       height:480,
+                       modal: true,
+                       buttons: bConf
+               } );
+               _this.target_container = '#seq_resource_import';
+               // do parent resource edit (with updated target)
+               this.parent_resourceEdit( rObj, rsdElement );
+       },
+       closeAll:function() {
+               js_log( 'should close: seq_resource_import' );
+               $j( '#seq_resource_import' ).dialog( 'close' ).dialog( 'destroy' ).remove();
+               this.parent_closeAll();
+       },
+       getEditToken:function( callback ) {
+               if ( this.pSeq.sequenceEditToken ) {
+                       callback( this.pSeq.sequenceEditToken )
+               } else {
+                       this.parent_getEditToken( callback );
+               }
+       },
+       cancelClipEditCB:function() {
+               js_log( 'seqRSD:cancelClipEditCB' );
+               $j( '#seq_resource_import' ).dialog( 'close' ).dialog( 'destroy' ).remove();
+       }
+};
+
diff --git a/js2/mwEmbed/libTimedText/mvTextInterface.js b/js2/mwEmbed/libTimedText/mvTextInterface.js
new file mode 100644 (file)
index 0000000..7326c47
--- /dev/null
@@ -0,0 +1,695 @@
+loadGM( {
+       "mwe-select_transcript_set" : "Select subtitles",
+       "mwe-auto_scroll" : "auto scroll",
+       "mwe-close" : "close",
+       "mwe-improve_transcript" : "Improve",
+       "mwe-no_text_tracks_found" : "No text subtitles found",
+       "mwe-add-edit-subs"     : "Add/edit subtitles"
+} )
+// text interface object (for inline display captions)
+var mvTextInterface = function( parentEmbed ) {
+       return this.init( parentEmbed );
+}
+mvTextInterface.prototype = {
+       text_lookahead_time:0,
+       body_ready:false,
+       default_time_range: "source", // by default just use the source don't get a time-range
+       transcript_set:null,
+       autoscroll:true,
+       add_to_end_on_this_pass:false,
+       scrollTimerId:0,
+       editlink: '',
+       suportedMime: {
+           'srt': 'text/x-srt',
+           'cmml': 'text/cmml'
+       },
+       init:function( parentEmbed ) {
+               // init a new availableTracks obj:
+               this.availableTracks = new Array();
+               // set the parent embed object:
+               this.pe = parentEmbed;
+               // parse roe if not already done:
+               this.getTextTracks();
+       },
+       // @@todo separate out data loader & data display
+       getTextTracks:function() {
+               // js_log("load timed text from roe: "+ this.pe.roe);
+               var _this = this;
+               // if roe not yet loaded do load it:
+               if ( this.pe.roe || _this.pe.wikiTitleKey ) {
+                       if ( !this.pe.media_element.addedROEData ) {
+                               $j( '#mv_txt_load_' + _this.pe.id ).show(); // show the loading icon
+                               if ( _this.pe.roe ) {
+                                       do_request( _this.pe.roe, function( data )
+                                       {
+                                               _this.pe.media_element.addROE( data );
+                                               _this.getParseTimedText_rowReady();
+                                       } );
+                               } else if ( _this.pe.wikiTitleKey ) {
+                                       // check for a clear namespace key:
+                                       _this.getTextTracksWikiTitle()
+                               }
+                       } else {
+                               js_log( 'row data ready (no roe request)' );
+                               _this.getParseTimedText_rowReady();
+                       }
+               } else {
+                       if ( this.pe.media_element.timedTextSources() ) {
+                               _this.getParseTimedText_rowReady();
+                       } else {
+                               js_log( 'no roe data or timed text sources' );
+                       }
+               }
+       },
+       getTextTracksWikiTitle:function() {
+               var apiUrl = mw.getLocalApiUrl();
+               var _this = this;
+               
+               var timedtext_ns = 102;
+               if ( typeof wgNamespaceIds != 'undefined' && wgNamespaceIds['timedtext'] ) {
+                       timedtext_ns = wgNamespaceIds['timedtext'];
+               }
+               do_api_req( {
+                               'url' : apiUrl,
+                               'data': {
+                                       'list' : 'allpages',
+                                       'apprefix' : _this.pe.wikiTitleKey,
+                                       'apnamespace' : timedtext_ns,
+                                       'prop':'revisions'
+                               }
+               }, function( subData ) {
+                       if (    subData.error && subData.error.code == 'apunknown_apnamespace' ) {
+                               do_api_req( {
+                                       'url' : apiUrl,
+                                       'data': {
+                                               'list' : 'allpages',
+                                               'apprefix' : 'TimedText:' + _this.pe.wikiTitleKey,
+                                       }
+                               }, function( subData ) {
+                                       _this.doProcSubPages( subData, wgServer + wgScriptPath );
+                               } );
+                       } else {
+                               _this.doProcSubPages( subData, wgServer + wgScriptPath );
+                       }
+               } );
+       },
+       doProcSubPages: function( subData, hostPath ) {
+               var _this = this;
+               // look for text tracks:
+               var foundTextTracks = false;
+               
+               // get all the known languages:
+               do_api_req( {
+                       'url':  hostPath + '/api.php',
+                       'data': {
+                               'meta' : 'siteinfo',
+                               'siprop' : 'languages'
+                       }
+               }, function( langDataRaw ) {
+                               var langData = { };
+                               var lagRaw = langDataRaw.query.languages;
+                               for ( var j in lagRaw ) {
+                                       langData[ lagRaw[j].code ] = lagRaw[j]['*'];
+                               }
+                               for ( var i in subData.query.allpages ) {
+                                       var subPage = subData.query.allpages[i];
+                                       var langKey = subPage.title.split( '.' );
+                                       var extension = langKey.pop();
+                                       langKey = langKey.pop();
+                                       if ( ! _this.suportedMime[ extension ] ) {
+                                               js_log( 'Error: unknown extension:' + extension );
+                                               continue;
+                                       }
+
+                                       if ( !langData[ langKey] ) {
+                                               js_log( 'Error: langkey:' + langKey + ' not found' );
+                                       } else {
+                                               var textElm = document.createElement( 'text' );
+                                               $j( textElm ).attr( {
+                                                       'category' : 'SUB',
+                                                       'lang'  : langKey,
+                                                       'type'  : _this.suportedMime[ extension ],
+                                                       'title' : langData[ langKey]
+                                               } );
+                                               // We use the api since ?action raw on the real title has cache issues 
+                                               $j( textElm ).attr( {
+                                                       'apisrc'        : hostPath + '/api.php',
+                                                       'titleKey'      : subPage.title
+                                               } );
+                                               _this.pe.media_element.tryAddSource( textElm );
+                                               foundTextTracks = true;
+                                       }
+                               }
+                               // after all text loaded (or we have allready checked commons
+                               if ( foundTextTracks || hostPath.indexOf( 'commons.wikimedia' ) !== -1 ) {
+                                       // alert('calling                       getParseTimedText_rowReady ');          
+                                       _this.getParseTimedText_rowReady();
+                               } else {
+                                       _this.checkSharedRepo();
+                               }
+                       } );    // do_api_req({
+       },
+       checkSharedRepo:function() {
+               var _this = this;
+               js_log( 'checking for shared value of image' );
+               // check if its a shared repo
+               do_api_req( {
+                       'data': {
+                               'action':'query',
+                               'titles': 'File:' + _this.pe.wikiTitleKey,
+                               'prop' : 'imageinfo'
+                       }
+               }, function( data ) {
+                       if ( data.query.pages && data.query.pages['-1'] && data.query.pages['-1'].imagerepository == 'shared' ) {
+                               js_log( 'image is shared checking commons for subtitles' );
+                               // found shared repo assume commons: 
+                               do_api_req( {
+                                       'url': mw.commons_api_url,
+                                       'data': {
+                                               'list' : 'allpages',
+                                               'apprefix' : _this.pe.wikiTitleKey,
+                                               'apnamespace' : 102
+                                       }
+                               }, function( data ) {
+                                       _this.editlink = 'http://commons.wikimedia.org/wiki/TimedText:' +  _this.pe.wikiTitleKey + '.' + wgUserLanguage + '.srt';
+                                       _this.doProcSubPages( data, 'http://commons.wikimedia.org/w/' );
+                               } );
+                       } else {
+                               // no shared repo do normal proc
+                               _this.getParseTimedText_rowReady();
+                       }
+               } );
+       },
+       getParseTimedText_rowReady: function () {
+               var _this = this;
+               var found_tracks = false;
+               // create timedTextObj          
+               js_log( "mv_txt_load_:SHOW mv_txt_load_" );
+               $j( '#mv_txt_load_' + _this.pe.id ).show(); // show the loading icon
+
+               // setup edit link: 
+               if ( _this.editlink == '' ) {
+                       if ( this.pe.media_element.linkback ) {
+                               _this.editlink = this.pe.media_element.linkback;
+                       } else if ( this.pe.wikiTitleKey && wgServer && wgScript ) { // check for wikiTitleKey (for edit linkback)
+                               // only local:
+                               _this.editlink = wgServer + wgScript + '?title=TimedText:' + this.pe.wikiTitleKey + '.' + wgUserLanguage + '.srt&action=edit';
+                       }
+               }
+               $j.each( this.pe.media_element.sources, function( inx, source ) {
+                       if ( typeof source.id == 'undefined' || source.id == null ) {
+                               source.id = 'text_' + inx;
+                       }
+                       var tObj = new timedTextObj( source );
+                       // make sure its a valid timed text format (we have not loaded or parsed yet) : (
+                       if ( tObj.lib != null ) {
+                               _this.availableTracks.push( tObj );
+                               // display requested language if we can know that: 
+                               if ( ( typeof wgUserLanguage != 'undefined' && source['lang'] == wgUserLanguage ) || source['default'] == "true" ) {
+                                       // we did set at least one track by default tag
+                                       found_tracks = true;
+                                       _this.loadAndDisplay( _this.availableTracks.length - 1 );
+                               } else {
+                                       // don't load the track and don't display                                       
+                               }
+                       }
+               } );
+               
+               // no default clip found take the userLanguage key if set:
+               if ( !found_tracks ) {
+                       $j.each( _this.availableTracks, function( inx, source ) {
+                               _this.loadAndDisplay( inx );
+                               found_tracks = true;
+                               // return after loading first available
+                               return false;
+                       } );
+               }
+               
+           // if nothing found anywhere give the not found msg: 
+               if ( !found_tracks ) {
+                       $j( '#metaBox_' + _this.pe.id ).html( '' +
+                               '<h3>' + gM( 'mwe-no_text_tracks_found' ) + '</h3>' +
+                               '<a href="' + _this.editlink + '">' + gM( 'mwe-add-edit-subs' ) + '</a>'
+                       );
+               }
+       },
+       loadAndDisplay: function ( track_id ) {
+               var _this = this;
+               $j( '#mv_txt_load_' + _this.pe.id ).show();// show the loading icon
+               _this.availableTracks[ track_id ].load( _this.default_time_range, function() {
+                       $j( '#mv_txt_load_' + _this.pe.id ).hide();
+                       _this.addTrack( track_id );
+               } );
+       },
+       addTrack: function( track_id ) {
+               js_log( 'f:displayTrack:' + track_id );
+               var _this = this;
+               // set the display flag to true:
+               _this.availableTracks[ track_id ].display = true;
+               // setup the layout:
+               this.setup_layout();
+               js_log( "SHOULD ADD: track:" + track_id + ' count:' +  _this.availableTracks[ track_id ].textNodes.length );
+
+               // a flag to avoid checking all clips if we know we are adding to the end:
+               _this.add_to_end_on_this_pass = false;
+
+               // run clip adding on a timed interval to not lock the browser on large srt file merges (should use worker threads)
+               var i = 0;
+               var track_id = track_id;
+               var addNextClip = function() {
+                       var text_clip = _this.availableTracks[ track_id ].textNodes[i];
+                       if (    text_clip ) {
+                               _this.add_merge_text_clip( text_clip, track_id );
+                               i++;
+                               if ( i < _this.availableTracks[ track_id ].textNodes.length ) {
+                                       setTimeout( addNextClip, 1 );
+                               }
+                       }
+               }
+               addNextClip();
+       },
+       add_merge_text_clip: function( text_clip, track_id ) {
+               var _this = this;
+               // make sure the clip does not already exist:
+               if ( $j( '#tc_' + text_clip.id ).length == 0 ) {
+                       var inserted = false;
+                       var text_clip_start_time = npt2seconds( text_clip.start );
+
+                       var insertHTML = '<div id="tc_' + text_clip.id + '" ' +
+                               'start_sec="' + text_clip_start_time + '" ' +
+                               'start="' + text_clip.start + '" end="' + text_clip.end + '" ' +
+                               'class="mvtt track_' + track_id + '">' +
+                                       '<div class="mvttseek" style="top:0px;left:0px;right:0px;height:20px;font-size:small">' +
+                                               text_clip.start + ' to ' + text_clip.end +
+                                       '</div>' +
+                                       text_clip.body +
+                       '</div>';
+                       if ( !_this.add_to_end_on_this_pass ) {
+                               $j( '#mmbody_' + this.pe.id + ' .mvtt' ).each( function() {
+                                       if ( !inserted ) {
+                                               if ( $j( this ).attr( 'start_sec' ) > text_clip_start_time ) {
+                                                       inserted = true;
+                                                       $j( this ).before( insertHTML );
+                                               }
+                                       } else {
+                                               _this.add_to_end = true;
+                                       }
+                               } );
+                       }
+                       // js_log('should just add to end: '+insertHTML);
+                       if ( !inserted ) {
+                               $j( '#mmbody_' + this.pe.id ).append( insertHTML );
+                       }
+
+                       // apply the mouse over transcript seek/click functions:
+                       $j( ".mvttseek" ).click( function() {
+                               _this.pe.doSeek( $j( this ).parent().attr( "start_sec" ) / _this.pe.getDuration() );
+                       } );
+                       $j( ".mvttseek" ).hoverIntent( {
+                               interval:200, // polling interval
+                               timeout:200, // delay before onMouseOut
+                               over:function () {
+                                         js_log( 'mvttseek: over' );
+                                         $j( this ).parent().addClass( 'tt_highlight' );
+                                       // do section highlight
+                                       _this.pe.highlightPlaySection( {
+                                               'start' : $j( this ).parent().attr( "start" ),
+                                               'end'   : $j( this ).parent().attr( "end" )
+                                       } );
+                               },
+                               out:function () {
+                                         js_log( 'mvttseek: out' );
+                                         $j( this ).parent().removeClass( 'tt_highlight' );
+                                         // de highlight section
+                                       _this.pe.hideHighlight();
+                               }
+                         }
+                       );
+               }
+       },
+       setup_layout:function() {
+               var _this = this;
+               // check if we have already loaded the menu/body:
+               if ( $j( '#tt_mmenu_' + this.pe.id ).length == 0 ) {
+                       // alert( this.availableTracks.length );
+                       if ( this.availableTracks.length != 0 ) {
+                               $j( '#metaBox_' + this.pe.id ).html(
+                                       this.getMenu() +
+                                       this.getBody()
+                               );
+                               this.doMenuBindings();
+                       }
+               }
+       },
+       show:function() {
+               // setup layout if not already done:
+               this.setup_layout();
+               // display the interface if not already displayed:
+               $j( '#metaBox_' + this.pe.id ).fadeIn( "fast" );
+               // start the autoscroll timer:
+               if ( this.autoscroll )
+                       this.setAutoScroll();
+       },
+       close:function() {
+               // the meta box:
+               $j( '#metaBox_' + this.pe.id ).fadeOut( 'fast' );
+               // the icon link:
+               $j( '#metaButton_' + this.pe.id ).fadeIn( 'fast' );
+       },
+       getBody:function() {
+               return '<div id="mmbody_' + this.pe.id + '" ' +
+                               'style="position:absolute;top:30px;left:0px;' +
+                               'right:0px;bottom:0px;' +
+                               'height:' + ( this.pe.height - 30 ) +
+                               'px;overflow:auto;"><span style="display:none;" id="mv_txt_load_' + this.pe.id + '">' +
+                                       mv_get_loading_img() + '</span>' +
+                               '</div>';
+       },
+       getTsSelect:function() {
+               var _this = this;
+               js_log( 'getTsSelect' );
+               var selHTML = '<div id="mvtsel_' + this.pe.id + '" style="position:absolute;background:#FFF;top:30px;left:0px;right:0px;bottom:0px;overflow:auto;">';
+               selHTML += '<b>' + gM( 'mwe-select_transcript_set' ) + '</b><ul>';
+               // debugger;
+               for ( var i in _this.availableTracks ) { // for in loop ok on object
+                       var checked = ( _this.availableTracks[i].display ) ? 'checked' : '';
+                       selHTML += '<li><input name="language" value="' + i + '" class="mvTsSelect" type="radio" ' + checked + '>' +
+                               _this.availableTracks[i].getTitle() + '</li>';
+               }
+               selHTML += '</ul>' +
+                                '</div>';
+               $j( '#metaBox_' + _this.pe.id ).append( selHTML );
+               $j( '.mvTsSelect' ).click( function() {
+                       _this.applyTsSelect();
+               } );
+       },
+       applyTsSelect:function() {
+               var _this = this;
+               // update availableTracks
+               $j( '#mvtsel_' + this.pe.id + ' .mvTsSelect' ).each( function() {
+                       var track_id = $j( this ).val();
+                       if ( this.checked ) {
+                               // if not yet loaded now would be a good time
+                               if ( ! _this.availableTracks[ track_id ].loaded ) {
+                                       _this.loadAndDisplay( track_id );
+                               } else {
+                                       _this.availableTracks[track_id].display = true;
+                                       // display the named class:
+                                       $j( '#mmbody_' + _this.pe.id + ' .track_' + track_id ).show();
+                               }
+                       } else {
+                               if ( _this.availableTracks[track_id].display ) {
+                                       _this.availableTracks[track_id].display = false;
+                                       // hide unchecked                               
+                                       $j( '#mmbody_' + _this.pe.id + ' .track_' + track_id ).hide();
+                               }
+                       }
+               } );
+               $j( '#mvtsel_' + _this.pe.id ).fadeOut( "fast" ).remove();
+       },
+       monitor:function() {
+               _this = this;
+               // grab the time from the video object
+               var cur_time = this.pe.currentTime ;
+               if ( cur_time != 0 ) {
+                       var search_for_range = true;
+                       // check if the current transcript is already where we want:
+                       if ( $j( '#mmbody_' + this.pe.id + ' .tt_scroll_highlight' ).length != 0 ) {
+                               var curhl = $j( '#mmbody_' + this.pe.id + ' .tt_scroll_highlight' ).get( 0 );
+                               if ( npt2seconds( $j( curhl ).attr( 'start' ) ) < cur_time &&
+                                  npt2seconds( $j( curhl ).attr( 'end' ) ) > cur_time ) {
+                                       /*js_log('in range of current hl: ' +
+                                               npt2seconds($j(curhl).attr('start')) +  ' to ' +  npt2seconds($j(curhl).attr('end')));
+                                       */
+                                       search_for_range = false;
+                               } else {
+                                       search_for_range = true;
+                                       // remove the highlight from all:
+                                       $j( '#mmbody_' + this.pe.id + ' .tt_scroll_highlight' ).removeClass( 'tt_scroll_highlight' );
+                               }
+                       };
+                       /*js_log('search_for_range:'+search_for_range +  ' for: '+ cur_time);*/
+                       if ( search_for_range ) {
+                               // search for current time: add tt_scroll_highlight to clip
+                               // optimize:
+                               //  should do binnary search not iterative
+                               //  avoid jquery function calls do native loops
+                               $j( '#mmbody_' + this.pe.id + ' .mvtt' ).each( function() {
+                                       if ( npt2seconds( $j( this ).attr( 'start' ) ) < cur_time &&
+                                          npt2seconds( $j( this ).attr( 'end' ) ) > cur_time ) {
+                                               _this.prevTimeScroll = cur_time;
+                                               $j( '#mmbody_' + _this.pe.id ).animate( {
+                                                       scrollTop: $j( this ).get( 0 ).offsetTop
+                                               }, 'slow' );
+                                               $j( this ).addClass( 'tt_scroll_highlight' );
+                                               // js_log('should add class to: ' + $j(this).attr('id'));
+                                               // done with loop
+                                               return false;
+                                       }
+                               } );
+                       }
+               }
+       },
+       setAutoScroll:function( timer ) {
+               var _this = this;
+               this.autoscroll = ( typeof timer == 'undefined' ) ? this.autoscroll:timer;
+               if ( this.autoscroll ) {
+                       // start the timer if its not already running
+                       if ( !this.scrollTimerId ) {
+                               var mvElm = $j('#' + _this.id ).get(0);
+                               if( mvElm )
+                                       this.scrollTimerId = setInterval( mvElm.textInterface.monitor(), 500 );
+                       }
+                       // jump to the current position:
+                       var cur_time = parseInt ( this.pe.currentTime );
+                       js_log( 'cur time: ' + cur_time );
+
+                       _this = this;
+                       var scroll_to_id = '';
+                       $j( '#mmbody_' + this.pe.id + ' .mvtt' ).each( function() {
+                               if ( cur_time > npt2seconds( $j( this ).attr( 'start' ) )  ) {
+                                       _this.prevTimeScroll = cur_time;
+                                       if ( $j( this ).attr( 'id' ) )
+                                               scroll_to_id = $j( this ).attr( 'id' );
+                               }
+                       } );
+                       if ( scroll_to_id != '' )
+                               $j( '#mmbody_' + _this.pe.id ).animate( { scrollTop: $j( '#' + scroll_to_id ).position().top } , 'slow' );
+               } else {
+                       // stop the timer
+                       clearInterval( this.scrollTimerId );
+                       this.scrollTimerId = 0;
+               }
+       },
+       getMenu:function() {
+               var out = '';
+               var _this = this;
+               // add in loading icon:
+               var as_checked = ( this.autoscroll ) ? 'checked':'';
+               out += '<div id="tt_mmenu_' + this.pe.id + '" class="ui-widget-header" style="font-size:.6em;position:absolute;top:0;height:30px;left:0px;right:0px;">';
+               out += $j.btnHtml( gM( 'mwe-select_transcript_set' ), 'tt-select', 'shuffle' );
+                               
+               if ( _this.editlink != '' )
+                       out += ' ' + $j.btnHtml( gM( 'mwe-improve_transcript' ), 'tt-improve' );
+               
+               out += '<input class="tt-scroll" type="checkbox" ' + as_checked + '>' + gM( 'mwe-auto_scroll' );
+               
+               out += ' ' + $j.btnHtml( gM( 'mwe-close' ), 'tt-close', 'circle-close' );
+               
+               out += '</div>';
+               return out;
+       },
+       doMenuBindings:function() {
+           var _this = this;
+           var mt = '#tt_mmenu_' + _this.pe.id;
+           $j( mt + ' .tt-close' ).unbind().btnBind().click( function() {
+              $j( '#' + _this.pe.id ).get( 0 ).closeTextInterface();
+              return false;
+           } );
+           $j( mt + ' .tt-select' ).unbind().btnBind().click( function() {
+              $j( '#' +  _this.pe.id ).get( 0 ).textInterface.getTsSelect();
+              return false;
+           } );
+           $j( mt + ' .tt-scroll' ).click( function() {
+               _this.setAutoScroll( this.checked );
+            } );
+           $j( mt + ' .tt-improve' ).unbind().btnBind().click( function() {
+               document.location.href =  _this.editlink;
+           } );
+       }
+}
+
+/* text format objects
+*  @@todo allow loading from external lib set
+*/
+var timedTextObj = function( source ) {
+       // @@todo in the future we could support timed text in oggs if they can be accessed via javascript
+       // we should be able to do a HEAD request to see if we can read transcripts from the file.
+       switch( source.mime_type ) {
+               case 'text/cmml':
+                       this.lib = 'CMML';
+               break;
+               case 'text/srt':
+               case 'text/x-srt':
+                       this.lib = 'SRT';
+               break;
+               default:
+                       js_log( source.mime_type + ' is not suported timed text fromat' );
+                       return ;
+               break;
+       }
+       // extend with the per-mime type lib:
+       eval( 'var tObj = timedText' + this.lib + ';' );
+       for ( var i in tObj ) {
+               this[ i ] = tObj[i];
+       }
+       return this.init( source );
+}
+
+// base timedText object
+timedTextObj.prototype = {
+       loaded: false,
+       lib:null,
+       display: false,
+       textNodes:new Array(),
+       init: function( source ) {
+               // copy source properties
+               this.source = source;
+               this.id = source.id;
+       },
+       getTitle:function() {
+               return this.source.title;
+       },
+       getSRC:function() {
+               return this.source.src;
+       }
+}
+
+// Specific Timed Text formats:
+
+timedTextCMML = {
+       load: function( range, callback ) {
+               var _this = this;
+               js_log( 'textCMML: loading track: ' + this.src );
+
+               // :: Load transcript range ::
+               var pcurl =  mw.parseUri( _this.getSRC() );
+               // check for urls without time keys:
+               if ( typeof pcurl.queryKey['t'] == 'undefined' ) {
+                       // in which case just get the full time req:
+                       do_request( this.getSRC(), function( data ) {
+                               _this.doParse( data );
+                               _this.loaded = true;
+                               callback();
+                       } );
+                       return ;
+               }
+               // temporal urls: 
+               var req_time = pcurl.queryKey['t'].split( '/' );
+               req_time[0] = npt2seconds( req_time[0] );
+               req_time[1] = npt2seconds( req_time[1] );
+               if ( req_time[1] - req_time[0] > _this.request_length ) {
+                       // longer than 5 min will only issue a (request 5 min)
+                       req_time[1] = req_time[0] + _this.request_length;
+               }
+               // set up request url:
+               url = pcurl.protocol + '://' + pcurl.authority + pcurl.path + '?';
+               $j.each( pcurl.queryKey, function( key, val ) {
+                       if ( key != 't' ) {
+                               url += key + '=' + val + '&';
+                       } else {
+                               url += 't=' + seconds2npt( req_time[0] ) + '/' + seconds2npt( req_time[1] ) + '&';
+                       }
+               } );
+               do_request( url, function( data ) {
+                       js_log( "load track clip count:" + data.getElementsByTagName( 'clip' ).length );
+                       _this.doParse( data );
+                       _this.loaded = true;
+                       callback();
+               } );
+       },
+       doParse: function( data ) {
+               var _this = this;
+               $j.each( data.getElementsByTagName( 'clip' ), function( inx, clip ) {
+                       // js_log(' on clip ' + clip.id);
+                       var text_clip = {
+                               start: $j( clip ).attr( 'start' ).replace( 'npt:', '' ),
+                               end: $j( clip ).attr( 'end' ).replace( 'npt:', '' ),
+                               type_id: _this.id,
+                               id: $j( clip ).attr( 'id' )
+                       }
+                       $j.each( clip.getElementsByTagName( 'body' ), function( binx, bn ) {
+                               if ( bn.textContent ) {
+                                       text_clip.body = bn.textContent;
+                               } else if ( bn.text ) {
+                                       text_clip.body = bn.text;
+                               }
+                       } );
+                       _this.textNodes.push( text_clip );
+               } );
+       }
+}
+timedTextSRT = {
+       load: function( range, callback ) {
+               var _this = this;
+               js_log( 'textSRT: loading : ' + _this.getSRC() );
+               if ( _this.getSRC() ) {
+                       do_request( _this.getSRC() , function( data ) {
+                               _this.doParse( data );
+                               _this.loaded = true;
+                               callback();
+                       } );
+               } else if ( _this.source.apisrc ) {
+                       do_api_req( {
+                               'url' : _this.source.apisrc,
+                               'data': {
+                                       'titles': _this.source.titleKey,
+                                       'prop':'revisions',
+                                       'rvprop':'content'
+                               }
+                       }, function( data ) {
+                               if ( data && data.query && data.query.pages ) {
+                                       for ( var i in data.query.pages ) {
+                                               var page = data.query.pages[i];
+                                               if ( page.revisions ) {
+                                                       for ( var j in page.revisions ) {
+                                                               if ( page.revisions[j]['*'] ) {
+                                                                       _this.doParse( page.revisions[j]['*'] );
+                                                                       _this.loaded = true;
+                                                                       callback();
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                       } );
+               }
+       },
+       doParse:function( data ) {
+               // split up the transcript chunks:
+               // strip any \r's
+               var tc = data.split( /[\r]?\n[\r]?\n/ );
+               // pushing can take time
+               for ( var s = 0; s < tc.length ; s++ ) {
+                       var st = tc[s].split( '\n' );
+                       if ( st.length >= 2 ) {
+                               var n = st[0];
+                               var i = st[1].split( ' --> ' )[0].replace( /^\s+|\s+$/g, "" );
+                               var o = st[1].split( ' --> ' )[1].replace( /^\s+|\s+$/g, "" );
+                               var t = st[2];
+                               if ( st.length > 2 ) {
+                                       for ( j = 3; j < st.length; j++ )
+                                               t += '\n' + st[j];
+                               }
+                               var text_clip = {
+                                       "start": i,
+                                       "end": o,
+                                       "type_id": this.id,
+                                       "id": this.id + '_' + n,
+                                       "body": t
+                               }
+                               this.textNodes.push( text_clip );
+                        }
+               }
+       }
+};
diff --git a/js2/mwEmbed/libTimedText/mvTimeTextEdit.js b/js2/mwEmbed/libTimedText/mvTimeTextEdit.js
new file mode 100644 (file)
index 0000000..8916bfe
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * JS2-style mvTimedTextEdit.js
+ */
+
+// Setup configuration vars (if not set already)
+if ( !mwAddMediaConfig )
+  var mwAddMediaConfig = { };
+
+var mvTimeTextEdit = { };
+
+loadGM( {
+  "mwe-upload-subs-file" : "Upload subtitle",
+  "mwe-add-subs-file-title" : "Select subtitle to upload",
+  "mwe-error-only-srt" : "You can only upload srt files.",
+  "mwe-watch-video" : "Watch video",
+  "mwe-select-other-language" : "Select another language",
+  "mwe-saving" : "saving..."
+} )
+
+
+js2AddOnloadHook( function() {
+  function getSubtitle( f ) {
+      var name = f.files[0].name;
+      var srtData = f.files[0].getAsBinary();
+      srtData = srtData.replace( '\r\n', '\n' );
+      return srtData;
+  }
+  function getVideoTitle() {
+    var videoTitle = wgPageName.split( '.' );
+    videoTitle.pop();
+    videoTitle.pop();
+    videoTitle = videoTitle.join( '.' ).replace( 'TimedText:', 'File:' );
+    return videoTitle;
+  }
+  function uploadSubtitles() {
+    do_api_req( {
+      'data': {
+        'meta' : 'siteinfo',
+        'siprop' : 'languages'
+      }
+      }, function( langDataRaw ) {
+        var apprefix = wgTitle.split( '.' );
+        apprefix.pop();
+        apprefix.pop();
+        apprefix = apprefix.join( '.' );
+                         do_api_req( {
+                                         'data': {
+                                                 'list' : 'allpages',
+                                                 'apprefix' : apprefix
+                                         }
+                         }, function( subData ) {
+                           var availableSubtitles = { };
+                                       for ( var i in subData.query.allpages ) {
+                                               var subPage = subData.query.allpages[i];
+                                               var langKey = subPage.title.split( '.' );
+                                               var extension = langKey.pop();
+                                               langKey = langKey.pop();
+                                               availableSubtitles[langKey] = subPage.title;
+          }
+          var langData = { };
+          var languageSelect = '<select id="timed_text_language">';
+
+          var lagRaw = langDataRaw.query.languages;
+          for ( var j in lagRaw ) {
+            var code = lagRaw[j].code;
+            var language = lagRaw[j]['*'];
+            langData[ code ] = language;
+            languageSelect += '<option value="' + code + '">';
+            if ( availableSubtitles[code] ) {
+              languageSelect += language + '(' + code + ') +';
+            } else {
+              languageSelect += language + '(' + code + ') -';
+            }
+            languageSelect += '</option>';
+          }
+          languageSelect += '/</select>';
+          var cBtn = { };
+          cBtn[ gM( 'mwe-cancel' ) ] = function() {
+            $j( this ).dialog( 'close' );
+          }
+          cBtn[ gM( 'mwe-ok' ) ] = function() {
+               // get language from form
+            langKey = $j( '#timed_text_language' ).val();
+            var title = wgPageName.split( '.' );
+            title.pop();
+            title.pop();
+            title = title.join( '.' ) + '.' + langKey + '.srt';
+            
+            var file = $j( '#timed_text_file_upload' );
+            if ( !file[0].files[0] ) {
+               // no file to upload just jump to the lang key: 
+               document.location.href = wgArticlePath.replace( '/$1', '?title=' + title + '&action=edit' );
+               return ;
+            }
+            var langKey = file[0].files[0].name.split( '.' );
+            var extension = langKey.pop();
+            langKey = langKey.pop();
+            var mimeTypes = {
+                'srt': 'text/x-srt',
+                'cmml': 'text/cmml'
+            }
+            if ( !mimeTypes[ extension ] ) {
+              js_log( 'Error: unknown extension:' + extension );
+            }
+            
+
+            if ( extension == "srt" ) {
+              var srt = getSubtitle( file[0] );
+              $j( this ).text( gM( 'mwe-saving' ) );
+              $j( '.ui-dialog-buttonpane' ).remove();
+
+              var editToken = $j( 'input[name=wpEditToken]' ).val();
+            
+              do_api_req( {
+                'data': {
+                  'action' : 'edit',
+                  'title' : title,
+                  'text' : srt,
+                  'token': editToken
+                }
+              }, function( dialog ) {
+                  return function( result ) {
+                    document.location.href = wgArticlePath.replace( '/$1', '?title=' + title + '&action=edit' );
+                    $j( dialog ).dialog( 'close' );
+                 } }( this )
+              );
+            } else {
+              $j( this ).html( gM( "mwe-error-only-srt" ) );
+            }
+          }
+          $j.addDialog( gM( "mwe-add-subs-file-title" ),
+             '<input type="file" id="timed_text_file_upload"></input><br />' + languageSelect,
+             cBtn );
+          $j( '#timed_text_file_upload' ).change( function( ev ) {
+               if ( this.files[0] ) {
+                   var langKey = this.files[0].name.split( '.' );
+                   var extension = langKey.pop();
+                   langKey = langKey.pop();
+                   $j( '#timed_text_language' ).val( langKey );
+            }
+          } );
+      } );
+    } );
+  }
+  var tselect = ( $j( '#wikiEditor-ui-top' ).length != 0 ) ? '#wikiEditor-ui-top':'#toolbar';
+  $j( tselect ).hide();
+  var ttoolbar = $j( '<div>' );
+  $j( tselect ).after( ttoolbar );
+
+  var button = $j( '<button>' );
+         button.click( uploadSubtitles )
+         button.text( gM( "mwe-upload-subs-file" ) );
+         ttoolbar.append( button );
+  ttoolbar.append( ' ' );
+
+  var button = $j( '<button>' );
+         button.click( function() { document.location.href = wgArticlePath.replace( '$1', getVideoTitle() ); } )
+         button.text( gM( "mwe-watch-video" ) );
+  ttoolbar.append( button );
+
+} );
+
diff --git a/js2/mwEmbed/mv_embed.js b/js2/mwEmbed/mv_embed.js
new file mode 100644 (file)
index 0000000..81b4ec2
--- /dev/null
@@ -0,0 +1,2107 @@
+/*
+ * ~mv_embed ~
+ * For details see: http://metavid.org/wiki/index.php/Mv_embed
+ *
+ * All Metavid Wiki code is released under the GPL2.
+ * For more information visit http://metavid.org/wiki/Code
+ *
+ * @url http://metavid.org
+ *
+ * mw.parseUri:
+ * http://stevenlevithan.com/demo/parseuri/js/
+ *
+ * Config values: you can manually set the location of the mv_embed folder here
+ * (in cases where media will be hosted in a different place than the embedding page)
+ *
+ */
+
+/**
+ * AutoLoader paths 
+ * @path The path to the file (or set of files) with ending slash
+ * @gClasses The set of classes
+ *             if it's an array, $j.className becomes jquery.className.js
+ *             if it's an associative object then key => value pairs are used
+ */
+if ( typeof mvAutoLoadClasses == 'undefined' )
+       mvAutoLoadClasses = { };
+
+// The script that loads the class set
+function lcPaths( classSet ) {
+       for ( var i in classSet ) {
+               mvAutoLoadClasses[i] = classSet[i];
+       }
+}
+
+function mvGetClassPath( k ) {
+       if ( mvAutoLoadClasses[k] ) {
+               // js_log('got class path:' + k +  ' : '+ mvClassPaths[k]);
+               return mvAutoLoadClasses[k];
+       } else {
+               js_log( 'Error:: Could not find path for requested class ' + k );
+               return false;
+       }
+}
+
+if ( typeof mvCssPaths == 'undefined' )
+       mvCssPaths = { };
+
+function lcCssPath( cssSet ) {
+       for ( var i in cssSet ) {
+               mvCssPaths[i] = cssSet[i];
+       }
+}
+
+/*
+ * --  Load Class Paths --
+ *
+ * MUST BE VALID JSON (NOT JS)
+ * This is used by the script loader to auto-load classes (so we only define
+ * this once for PHP & JavaScript)
+ *
+ * Right now the PHP AutoLoader only reads this mv_embed.js file.
+ * In the future we could have multiple lcPath calls that PHP reads
+ * (if our autoloading class list becomes too long) 
+ * or 
+ * we could support direct file requests to the script loader instead 
+ * of shared class names read from a central location.
+ */
+lcPaths( {
+       "mv_embed"                      : "mv_embed.js",
+       "window.jQuery"         : "jquery/jquery-1.3.2.js",
+       "$j.fn.pngFix"          : "jquery/plugins/jquery.pngFix.js",
+       "$j.fn.autocomplete": "jquery/plugins/jquery.autocomplete.js",
+       "$j.fn.hoverIntent"     : "jquery/plugins/jquery.hoverIntent.js",
+       "$j.fn.datePicker"      : "jquery/plugins/jquery.datePicker.js",
+       "$j.ui"                         : "jquery/jquery.ui/ui/ui.core.js",
+       "$j.fn.ColorPicker"     : "libClipEdit/colorpicker/js/colorpicker.js",
+       "$j.Jcrop"                      : "libClipEdit/Jcrop/js/jquery.Jcrop.js",
+       "$j.fn.simpleUploadForm" : "libAddMedia/simpleUploadForm.js",
+       
+       "mw.proxy"              : "libMwApi/mw.proxy.js",
+       
+       "mw.testLang"   :  "tests/testLang.js",
+       
+       "ctrlBuilder"   : "skins/ctrlBuilder.js",
+       "kskinConfig"   : "skins/kskin/kskin.js",
+       "mvpcfConfig"   : "skins/mvpcf/mvpcf.js",
+
+       "JSON"                          : "libMwApi/json2.js",
+       "$j.cookie"                     : "jquery/plugins/jquery.cookie.js",
+       "$j.contextMenu"        : "jquery/plugins/jquery.contextMenu.js",
+       "$j.fn.suggestions"     : "jquery/plugins/jquery.suggestions.js",
+       "$j.fn.textSelection"   : "jquery/plugins/jquery.textSelection.js",
+
+       "$j.effects.blind"              : "jquery/jquery.ui/ui/effects.blind.js",
+       "$j.effects.drop"               : "jquery/jquery.ui/ui/effects.drop.js",
+       "$j.effects.pulsate"    : "jquery/jquery.ui/ui/effects.pulsate.js",
+       "$j.effects.transfer"   : "jquery/jquery.ui/ui/effects.transfer.js",
+       "$j.ui.droppable"               : "jquery/jquery.ui/ui/ui.droppable.js",
+       "$j.ui.slider"                  : "jquery/jquery.ui/ui/ui.slider.js",
+       "$j.effects.bounce"             : "jquery/jquery.ui/ui/effects.bounce.js",
+       "$j.effects.explode"    : "jquery/jquery.ui/ui/effects.explode.js",
+       "$j.effects.scale"              : "jquery/jquery.ui/ui/effects.scale.js",
+       "$j.ui.datepicker"              : "jquery/jquery.ui/ui/ui.datepicker.js",
+       "$j.ui.progressbar"             : "jquery/jquery.ui/ui/ui.progressbar.js",
+       "$j.ui.sortable"                : "jquery/jquery.ui/ui/ui.sortable.js",
+       "$j.effects.clip"               : "jquery/jquery.ui/ui/effects.clip.js",
+       "$j.effects.fold"               : "jquery/jquery.ui/ui/effects.fold.js",
+       "$j.effects.shake"              : "jquery/jquery.ui/ui/effects.shake.js",
+       "$j.ui.dialog"                  : "jquery/jquery.ui/ui/ui.dialog.js",
+       "$j.ui.resizable"               : "jquery/jquery.ui/ui/ui.resizable.js",
+       "$j.ui.tabs"                    : "jquery/jquery.ui/ui/ui.tabs.js",
+       "$j.effects.core"               : "jquery/jquery.ui/ui/effects.core.js",
+       "$j.effects.highlight"  : "jquery/jquery.ui/ui/effects.highlight.js",
+       "$j.effects.slide"              : "jquery/jquery.ui/ui/effects.slide.js",
+       "$j.ui.accordion"               : "jquery/jquery.ui/ui/ui.accordion.js",
+       "$j.ui.draggable"               : "jquery/jquery.ui/ui/ui.draggable.js",
+       "$j.ui.selectable"              : "jquery/jquery.ui/ui/ui.selectable.js",
+
+       "$j.fn.dragDropFile"            : "libAddMedia/dragDropFile.js",
+       "mvFirefogg"                    : "libAddMedia/mvFirefogg.js",
+       "mvAdvFirefogg"                 : "libAddMedia/mvAdvFirefogg.js",
+       "mvBaseUploadInterface" : "libAddMedia/mvBaseUploadInterface.js",
+       "remoteSearchDriver"    : "libAddMedia/remoteSearchDriver.js",
+       "seqRemoteSearchDriver" : "libSequencer/seqRemoteSearchDriver.js",
+
+       "baseRemoteSearch"              : "libAddMedia/searchLibs/baseRemoteSearch.js",
+       "mediaWikiSearch"               : "libAddMedia/searchLibs/mediaWikiSearch.js",
+       "metavidSearch"                 : "libAddMedia/searchLibs/metavidSearch.js",
+       "archiveOrgSearch"              : "libAddMedia/searchLibs/archiveOrgSearch.js",
+       "flickrSearch"                  : "libAddMedia/searchLibs/flickrSearch.js",
+       "baseRemoteSearch"              : "libAddMedia/searchLibs/baseRemoteSearch.js",
+
+       "mvClipEdit"                    : "libClipEdit/mvClipEdit.js",
+
+       "embedVideo"            : "libEmbedVideo/embedVideo.js",
+       "flowplayerEmbed"       : "libEmbedVideo/flowplayerEmbed.js",
+       "kplayerEmbed"          : "libEmbedVideo/kplayerEmbed.js",
+       "genericEmbed"          : "libEmbedVideo/genericEmbed.js",
+       "htmlEmbed"                     : "libEmbedVideo/htmlEmbed.js",
+       "javaEmbed"                     : "libEmbedVideo/javaEmbed.js",
+       "nativeEmbed"           : "libEmbedVideo/nativeEmbed.js",
+       "quicktimeEmbed"        : "libEmbedVideo/quicktimeEmbed.js",
+       "vlcEmbed"                      : "libEmbedVideo/vlcEmbed.js",
+
+       "mvPlayList"            : "libSequencer/mvPlayList.js",
+       "mvSequencer"           : "libSequencer/mvSequencer.js",
+       "mvFirefoggRender"      : "libSequencer/mvFirefoggRender.js",
+       "mvTimedEffectsEdit": "libSequencer/mvTimedEffectsEdit.js",
+
+       "mvTextInterface"       : "libTimedText/mvTextInterface.js",
+       "mvTimeTextEdit"        : "libTimedText/mvTimeTextEdit.js"
+} );
+
+// Dependency mapping for CSS files for self-contained included plugins:
+lcCssPath( {
+       '$j.Jcrop'                      : 'libClipEdit/Jcrop/css/jquery.Jcrop.css',
+       '$j.fn.ColorPicker'     : 'libClipEdit/colorpicker/css/colorpicker.css'
+})
+
+// For use when mv_embed with script-loader is in the root MediaWiki path
+var mediaWiki_mvEmbed_path = 'js2/mwEmbed/';
+
+// The global scope: will be depreciated once we get everything into mw
+var _global = this;
+
+/*
+* setup the empty global mw object
+* will ensure all our functions and variables are properly namespaced
+* reducing chance of conflicts
+*/
+if ( !window['mw'] ) {
+       window['mw'] = { }
+}
+
+
+// Inherit the default global config
+var mwDefaultConf = {
+       'skin_name' : 'mvpcf',
+       'jui_skin' : 'redmond',
+       'video_size' : '400x300',
+       'k_attribution' : true          
+}
+if( !mw.conf )
+       mw.conf = { }
+       
+for(var i in mwDefaultConf){
+       if( typeof mw.conf[ i ] == 'undefined' )
+               mw.conf[ i ] = mwDefaultConf[ i ];
+}
+
+
+// @@todo move these into mw
+var global_req_cb = new Array(); // The global request callback array
+
+/**
+* The global mw object:
+*
+* Any global functions/classes that are not jQuery plugins should make
+* there way into the mw namespace
+*/
+( function( $ ) {      
+       // list valid skins here:
+       $.valid_skins = ['mvpcf', 'kskin'];
+       // the version of mwEmbed
+       $.version = '1.0r21';
+       
+       // special case of commons api url 
+       // (used for default subtitles server for media with a "wikiTitleKey" atm)
+       // (@@todo eventually we should have  wikiTitleKey be namespaced with interwiki ns
+       $.commons_api_url = 'http://commons.wikimedia.org/w/api.php';
+       /*
+       * some global containers flags 
+       */
+       $.skin_list = new Array();
+       $.init_done = false;
+       $.cb_count = 0;
+       $.player_list = new Array(), // The global player list per page
+       $.req_cb = new Array() // The global request callback array     
+
+       /*
+       * Language classes mw.lang
+       *
+       * Localized Language support attempts to mirror the functionality of Language.php in MediaWiki
+       * It contains methods for loading and transforming msg text
+       *
+       */
+       $.lang = { };
+       /**
+       * Setup the lang object
+       */
+       var gMsg = { };
+       var gRuleSet = { };
+
+       /**
+       * loadGM function
+       * Loads a set of json messages into the lng object.
+       *
+       * @param json msgSet The set of msgs to be loaded
+       */
+       $.lang.loadGM = function( msgSet ) {
+               for ( var i in msgSet ) {
+                       gMsg[ i ] = msgSet[i];
+               }
+       }
+
+       /**
+       * loadRS function
+       * Loads a ruleset by given template key ie PLURAL : { //ruleSetObj }
+       *
+       * @param json ruleSet The ruleset object ( extends  gRuleSet )
+       */
+       $.lang.loadRS = function( ruleSet ) {
+               for ( var i in ruleSet ) {
+                       gRuleSet[ i ] = ruleSet[ i ];
+               }
+       }
+
+       /**
+        * Returns a transformed msg string
+        *
+        * it take a msg key and array of replacement values of form
+        * $1, $2 and does relevant msgkey transformation returning
+        * the user msg.
+        *
+        * @param string key The msg key as set by loadGm
+        * @param [mixed] args  An array of replacement strings
+        * @return string
+        */
+       $.lang.gM = function( key , args ) {
+               if ( ! gMsg[ key ] )
+                       return '&lt;' + key + '&gt;';// Missing key placeholder
+
+               // swap in the arg values
+               var ms =  $.lang.gMsgSwap( key, args );                         
+               
+               // a quick check to see if we need to send the msg via the 'parser'
+               // (we can add more detailed check once we support more wiki syntax)
+               if ( ms.indexOf( '{{' ) === -1 && ms.indexOf( '[' ) === -1 ) {
+                       return ms;
+               }
+
+               // make sure we have the lagMagic setup:
+               // @@todo move to init
+               $.lang.magicSetup();
+               // send the msg key through the parser
+               var pObj = $.parser.pNew( ms );
+               // return the transformed msg
+               return pObj.getHTML();
+       }
+       /**
+       * gMsgSwap
+       *
+       * @param string key The msg key as set by loadGm
+       * @param [mixed] args  An array or string to be replaced
+       * @return string
+       */
+       $.lang.gMsgSwap = function( key , args ) {
+               if ( ! gMsg[ key ] )
+                       return '&lt;' + key + '&gt;';// Missing key placeholder
+               // get the message string:
+               var ms = gMsg[ key ];
+               
+               // replace values
+               if ( typeof args == 'object' || typeof args == 'array' ) {
+                       for ( var v in args ) {
+                               // Message test replace arguments start at 1 instead of zero:
+                               var rep = new RegExp( '\\$' + ( parseInt( v ) + 1 ), 'g' );
+                               ms = ms.replace( rep, args[v] );
+                       }
+               } else if ( typeof args == 'string' || typeof args == 'number' ) {
+                       ms = ms.replace( /\$1/g, args );
+               }
+               return ms;
+       }
+
+       /**
+       * gMsgNoTrans
+       *
+       * @returns string The msg key without transforming it
+       */
+       $.lang.gMsgNoTrans = function( key ) {
+               if ( gMsg[ key ] )
+                       return gMsg[ key ]
+
+               // Missing key placeholder
+               return '&lt;' + key + '&gt;';
+       }
+       /**
+       * Add Supported Magic Words to parser
+       */
+       // Set the setupflag to false:
+       $.lang.doneSetup = false;
+       $.lang.magicSetup = function() {
+               if ( !$.lang.doneSetup ) {
+                       $.parser.addMagic ( {
+                               'PLURAL' : $.lang.procPLURAL
+                       } )
+
+                       $.lang.doneSetup = true;
+               }
+
+       }
+       /**
+       * Process the PLURAL special language template key:
+       */
+       $.lang.procPLURAL = function( tObj ) {
+               // setup shortcuts
+               // (gRuleSet is loaded from script-loader to contains local ruleset)
+               var rs = gRuleSet['PLURAL'];
+
+               /*
+                * Plural matchRuleTest
+                */
+               function matchRuleTest( cRule, val ) {
+                       js_log("matchRuleTest:: " + typeof cRule + ' ' + cRule + ' == ' + val );
+                       function checkValue( compare, val ) {
+                               if ( typeof compare == 'string' ) {
+                                       range = compare.split( '-' );
+                                       if ( range.length >= 1 ) {
+                                               if ( val >= range[0] &&  val <= range[1] )
+                                                       return true;
+                                       }
+                               }
+                               // else do a direct compare
+                               if ( compare == val ) {
+                                       return true;
+                               }
+                               return false;
+                       }
+                       // check for simple cRule type:
+                       if ( typeof cRule == 'number' ) {
+                               return ( parseInt( val ) == parseInt( cRule ) );
+                       } else if ( typeof cRule == 'object' ) {
+                               var cmatch = { };
+                               // if a list we need to match all for rule match
+                               for ( var i in  cRule ) {
+                                       var cr = cRule[i];
+                                       // set cr type
+                                       var crType =  '';
+                                       for ( var j in cr ) {
+                                               if ( j == 'mod' )
+                                                       crType = 'mod'
+                                       }
+                                       switch( crType ) {
+                                               case 'mod':
+                                                       if ( cr ['is'] ) {
+                                                               if ( checkValue( val % cr['mod'], cr ['is'] ) )
+                                                                       cmatch[i] = true;
+                                                       } else if ( cr['not'] ) {
+                                                               if ( ! checkValue( val % cr['mod'], cr ['not'] ) )
+                                                                       cmatch[i] = true;
+                                                       }
+                                               break;
+                                       }
+                               }
+                               // check all the matches (taking into consideration "or" order)
+                               for ( var i in cRule ) {
+                                       if ( ! cmatch[i] )
+                                               return false;
+                               }
+                               return true;
+
+                       }
+               }
+               /**
+                * Maps a given rule Index to template params:
+                *
+                * if index is out of range return last param
+                * @param
+                */
+               function getTempParamFromRuleInx( tObj, ruleInx ) {
+                       // js_log('getTempParamFromRuleInx: ruleInx: ' + ruleInx + ' tempParamLength ' + tObj.param.length );
+                       if ( ruleInx    >= tObj.param.length )
+                               return  tObj.param[  tObj.param.length - 1 ];
+                       // else return the requested index:
+                       return tObj.param[ ruleInx ];
+               }
+               var rCount = 0
+               // run the actual rule lookup:
+               for ( var ruleInx in rs ) {
+                       cRule = rs[ruleInx];
+                       if ( matchRuleTest( cRule, tObj.arg ) ) {
+                               js_log("matched rule: " + ruleInx );
+                               return getTempParamFromRuleInx( tObj, rCount );
+                       }
+                       rCount ++;
+               }
+               js_log('no match found for: ' + tObj.arg + ' using last/other : ' +  tObj.param [ tObj.param.length -1 ] );
+               //debugger;
+               // return the last /"other" template param
+               return tObj.param [ tObj.param.length - 1 ];
+       }
+
+       /**
+        * gMsgLoadRemote loads remote msg strings
+        *
+        * @param mixed msgSet the set of msg to load remotely
+        * @param function callback  the callback to issue once string is ready
+        */
+       $.lang.gMsgLoadRemote = function( msgSet, callback ) {
+               var ammessages = '';
+               if ( typeof msgSet == 'object' ) {
+                       for ( var i in msgSet ) {
+                               ammessages += msgSet[i] + '|';
+                       }
+               } else if ( typeof msgSet == 'string' ) {
+                       ammessages += msgSet;
+               }
+               if ( ammessages == '' ) {
+                       js_log( 'gMsgLoadRemote: no message set requested' );
+                       return false;
+               }
+               do_api_req( {
+                       'data': {
+                               'meta': 'allmessages',
+                               'ammessages': ammessages
+                       }
+               }, function( data ) {
+                       if ( data.query.allmessages ) {
+                               var msgs = data.query.allmessages;
+                               for ( var i in msgs ) {
+                                       var ld = { };
+                                       ld[ msgs[i]['name'] ] = msgs[i]['*'];
+                                       loadGM( ld );
+                               }
+                       }
+                       callback();
+               } );
+       }
+       /**
+        * Format a size in bytes for output, using an appropriate
+        * unit (B, KB, MB or GB) according to the magnitude in question
+        *
+        * @param size Size to format
+        * @return string Plain text (not HTML)
+        */
+       $.lang.formatSize = function ( size ) {
+               // For small sizes no decimal places are necessary
+               var round = 0;
+               var msg = '';
+               if ( size > 1024 ) {
+                       size = size / 1024;
+                       if ( size > 1024 ) {
+                               size = size / 1024;
+                               // For MB and bigger two decimal places are smarter
+                               round = 2;
+                               if ( size > 1024 ) {
+                                       size = size / 1024;
+                                       msg = 'mwe-size-gigabytes';
+                               } else {
+                                       msg = 'mwe-size-megabytes';
+                               }
+                       } else {
+                               msg = 'mwe-size-kilobytes';
+                       }
+               } else {
+                       msg = 'mwe-size-bytes';
+               }
+               // JavaScript does not let you choose the precision when rounding
+               var p = Math.pow( 10, round );
+               var size = Math.round( size * p ) / p;
+               return gM( msg , size );
+       };
+       
+       $.lang.formatNumber = function( num ) {
+               /*
+               *       addSeparatorsNF
+               * @param Str: The number to be formatted, as a string or number.                
+               * @param outD: The decimal character for the output, such as ',' for the number 100,2
+               * @param sep: The separator character for the output, such as ',' for the number 1,000.2
+               */
+               function addSeparatorsNF( nStr, outD, sep ) {
+                       nStr += '';
+                       var dpos = nStr.indexOf( '.' );
+                       var nStrEnd = '';
+                       if ( dpos != -1 ) {
+                               nStrEnd = outD + nStr.substring( dpos + 1, nStr.length );
+                               nStr = nStr.substring( 0, dpos );
+                       }
+                       var rgx = /(\d+)(\d{3})/;
+                       while ( rgx.test( nStr ) ) {
+                               nStr = nStr.replace( rgx, '$1' + sep + '$2' );
+                       }
+                       return nStr + nStrEnd;
+               }
+               // @@todo read language code and give periods or comas: 
+               return addSeparatorsNF( num, '.', ',' );
+       }
+       
+       
+       
+       /**
+       * MediaWiki wikitext "Parser"
+       *
+       * This is not feature complete but we need a way to get at template properties
+       *
+       *
+       * @param {String} wikiText the wikitext to be parsed
+       * @return {Object} parserObj returns a parser object that has methods for getting at
+       * things you would want
+       */
+       $.parser = { };
+       var pMagicSet = { };
+       /**
+        * parser addMagic
+        *
+        * Lets you add a set of magic keys and associated callback functions
+        *
+        * @param object magicSet key:callback
+        */
+       $.parser.addMagic = function( magicSet ) {
+               for ( var i in magicSet )
+                       pMagicSet[ i ] = magicSet[i];
+       }
+
+       // actual parse call (returns parser object)
+       $.parser.pNew = function( wikiText, opt ) {
+               var parseObj = function( wikiText, opt ) {
+                       return this.init( wikiText, opt )
+               }
+               parseObj.prototype = {
+                       // the wikiText "DOM"... stores the parsed wikiText structure
+                       // wtDOM : {}, (not yet supported )
+
+                       pOut : '', // the parser output string container
+                       init  :function( wikiText ) {
+                               this.wikiText = wikiText;
+                       },
+                       updateText : function( wikiText ) {
+                               this.wikiText = wikiText;
+                               // invalidate the output (will force a re-parse )
+                               this.pOut = '';
+                       },
+                       parse : function() {
+                               /*
+                                * quickly recursive / parse out templates:
+                                */
+
+                               // ~ probably a better algorithm out there / should mirror php parser flow ~
+                               //       (we are already running white-space issues ie php parse strips whitespace differently)
+                               // or at least expose something similar to: http://www.mediawiki.org/wiki/Extension:Page_Object_Model
+
+                               // ... but I am having fun with recursion so here it is...
+                               function rdpp ( txt , cn ) {
+                                       var node = { };
+                                       // inspect each char
+                                       for ( var a = 0; a < txt.length; a++ ) {
+                                               if ( txt[a] == '{' && txt[a + 1] == '{' ) {
+                                                       a = a + 2;
+                                                       node['p'] = node;
+                                                       if ( !node['c'] )
+                                                               node['c'] = new Array();
+
+                                                       node['c'].push( rdpp( txt.substr( a ), true ) );
+                                               } else if ( txt[a] == '}' && txt[a + 1] == '}' ) {
+                                                       a = a + 2;
+                                                       if ( !node['p'] ) {
+                                                               return node;
+                                                       }
+                                                       node = node['p'];
+                                               }
+                                               if ( !node['t'] )
+                                                       node['t'] = '';
+                                               // don't put closures into output:
+                                               if ( txt[a] &&  txt[a] != '}' )
+                                                               node['t'] += txt[a];
+                                                               
+                                       }
+                                       return node;
+                               }
+                               /**
+                                * parse template text as template name and named params
+                                */
+                               function parseTmplTxt( ts ) {
+                                       var tObj = { };
+                                       // Get template name:
+                                       tname = ts.split( '\|' ).shift() ;
+                                       tname = tname.split( '\{' ).shift() ;
+                                       tname = tname.replace( /^\s+|\s+$/g, "" ); //trim
+
+                                       // check for arguments:
+                                       if ( tname.split( ':' ).length == 1 ) {
+                                               tObj["name"] = tname;
+                                       } else {
+                                               tObj["name"] = tname.split( ':' ).shift();
+                                               tObj["arg"] = tname.split( ':' ).pop();
+                                       }
+                                                                               
+                                       var pSet = ts.split( '\|' );
+                                       pSet.splice( 0, 1 );
+                                       if ( pSet.length ) {
+                                               tObj.param = new Array();
+                                               for ( var pInx in pSet ) {
+                                                       var tStr = pSet[ pInx ];
+                                                       // check for empty param
+                                                       if ( tStr == '' ) {
+                                                               tObj.param[ pInx ] = '';
+                                                               continue;
+                                                       }
+                                                       for ( var b = 0 ; b < tStr.length ; b++ ) {
+                                                               if ( tStr[b] == '=' && b > 0 && b < tStr.length && tStr[b - 1] != '\\' ) {
+                                                                       // named param
+                                                                       tObj.param[ tStr.split( '=' ).shift() ] =       tStr.split( '=' ).pop();
+                                                               } else {
+                                                                       // indexed param
+                                                                       tObj.param[ pInx ] = tStr;
+                                                               }
+                                                       }
+                                               }
+                                       }
+                                       return tObj;
+                               }
+                               function getMagicTxtFromTempNode( node ) {
+                                       node.tObj = parseTmplTxt ( node.t );
+                                       // do magic swap if template key found in pMagicSet
+                                       if ( node.tObj.name in pMagicSet ) {
+                                               var nt = pMagicSet[ node.tObj.name ]( node.tObj );
+                                               return nt;
+                                       } else {
+                                               // don't swap just return text
+                                               return node.t;
+                                       }
+                               }
+                               /**
+                                * recurse_magic_swap
+                                *
+                                * go last child first swap upward: (could probably be integrated above somehow)
+                                */
+                               var pNode = null;
+                               function recurse_magic_swap( node ) {
+                                       if ( !pNode )
+                                               pNode = node;
+
+                                       if ( node['c'] ) {
+                                               // swap all the kids:
+                                               for ( var i in node['c'] ) {
+                                                       var nt = recurse_magic_swap( node['c'][i] );
+                                                       // swap it into current
+                                                       if ( node.t ) {
+                                                               node.t = node.t.replace( node['c'][i].t, nt );
+                                                       }
+                                                       // swap into parent
+                                                       pNode.t  = pNode.t.replace( node['c'][i].t, nt );
+                                               }
+                                               // do the current node:
+                                               var nt = getMagicTxtFromTempNode( node );
+                                               pNode.t = pNode.t.replace( node.t , nt );
+                                               // run the swap for the outer most node
+                                               return node.t;
+                                       } else {
+                                               // node.t = getMagicFromTempObj( node.t )
+                                               return getMagicTxtFromTempNode( node );
+                                       }
+                               }
+                               // parse out the template node structure:
+                               this.pNode = rdpp ( this.wikiText );
+                               // strip out the parent from the root   
+                               this.pNode['p'] = null;
+                               
+                               // do the recursive magic swap text:
+                               this.pOut = recurse_magic_swap( this.pNode );
+
+                       },                      
+                       /*
+                        * parsed template api ~loosely based off of ~POM~
+                        * http://www.mediawiki.org/wiki/Extension:Page_Object_Model
+                        */
+                       
+                       /**
+                        * templates
+                        * 
+                        * gets a requested template from the wikitext (if available)
+                        *  
+                        */
+                       templates: function( tname ) {
+                               this.parse();
+                               var tmplSet = new Array();
+                               function getMatchingTmpl( node ) {
+                                       if ( node['c'] ) {
+                                               for ( var i in node['c'] ) {
+                                                       getMatchingTmpl( node['c'] );
+                                               }
+                                       }
+                                       if ( tname && node.tObj ) {
+                                               if ( node.tObj['name'] == tname )
+                                                       tmplSet.push( node.tObj );
+                                       } else if ( node.tObj ) {
+                                               tmplSet.push( node.tObj );
+                                       }
+                               }
+                               getMatchingTmpl( this.pNode );
+                               return tmplSet;
+                       },
+                       /**
+                        * Returns the transformed wikitext
+                        * 
+                        * Build output from swapable index 
+                        *              (all transforms must be expanded in parse stage and linearly rebuilt)  
+                        * Alternatively we could build output using a place-holder & replace system 
+                        *              (this lets us be slightly more sloppy with ordering and indexes, but probably slower)
+                        * 
+                        * Ideal: we build a 'wiki DOM' 
+                        *              When editing you update the data structure directly
+                        *              Then in output time you just go DOM->html-ish output without re-parsing anything                           
+                        */
+                       getHTML : function() {
+                               // wikiText updates should invalidate pOut
+                               if ( this.pOut == '' ) {
+                                       this.parse();
+                               }
+                               return this.pOut;
+                       }
+               };
+               // return the parserObj
+               return new parseObj( wikiText, opt ) ;
+       }
+               
+       /* 
+       * API and request functions
+       */
+       $.getLocalApiUrl = function() {
+               if ( typeof wgServer != 'undefined' && typeof wgScriptPath  != 'undefined' ) {
+                       return wgServer + wgScriptPath + '/api.php';
+               }
+               return false;
+       }
+       
+       /**
+       * Utility Functions
+       */
+               
+       
+       /**
+       * parseUri 1.2.2
+       * (c) Steven Levithan <stevenlevithan.com>
+       *  MIT License
+       */              
+       $.parseUri = function (str) {
+               var     o   = $.parseUri.options,
+                       m   = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
+                       uri = {},
+                       i   = 14;
+       
+               while (i--) uri[o.key[i]] = m[i] || "";
+       
+               uri[o.q.name] = {};
+               uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
+                       if ($1) uri[o.q.name][$1] = $2;
+               });
+       
+               return uri;
+       };
+       $.parseUri.options = {
+               strictMode: false,
+               key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],
+               q:   {
+                       name:   "queryKey",
+                       parser: /(?:^|&)([^&=]*)=?([^&]*)/g
+               },
+               parser: {
+                       strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
+                       loose:  /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
+               }
+       };      
+       
+       /**
+       * getAbsoluteUrl takes a src and returns the absolute location given the document.URL
+       * @param {String} src path or url
+       */
+       $.absoluteUrl = function( src, contextUrl ){
+               var pSrc =  mw.parseUri( src );
+               if( pSrc.protocol != '')
+                       return src;                             
+               
+               // Get parent Url location the context URL      
+               if( contextUrl){        
+                       var pUrl = mw.parseUri( contextUrl );                   
+               } else {
+                       var pUrl = mw.parseUri( document.URL );
+               }
+               // If a leading slash:  
+               if( src.indexOf( '/' ) == 1 ){
+                       return pUrl.protocol + '://' + pUrl.authority + src;
+               }else{
+                       return pUrl.protocol + '://' + pUrl.authority + pUrl.directory + src;
+               }
+       };
+       /**
+       * Takes in a string returns an xml dom object 
+       */
+       $.parseXML = function ( str ){
+               if ( $j.browser.msie ) {
+                       // Attempt to parse as XML for IE
+                       var xmldata = new ActiveXObject( "Microsoft.XMLDOM" );
+                       xmldata.async = "false";
+                       try{
+                               xmldata.loadXML( str );
+                               return xmldata;
+                       } catch (e){
+                               js_log( 'XML parse ERROR: ' + e.message );
+                               return false;
+                       }
+               }
+               
+               // For others (Firefox, Safari etc, older browsers 
+               // Some don't have native DOMParser either fallback defined bellow.
+               try {
+                       var xmldata = ( new DOMParser() ).parseFromString( str, "text/xml" );
+               } catch ( e ) {
+                       js_log( 'XML parse ERROR: ' + e.message );
+                       return false;
+               }               
+               return xmldata;
+       }       
+} )( window.mw );
+
+// Get the mv_embed location if it has not been set
+if ( !mv_embed_path ) {
+       var mv_embed_path = getMvEmbedPath();
+}
+
+// load in js2 stopgap into proper location: 
+if ( typeof gMsg != 'undefined' ) {
+       mw.lang.loadGM( gMsg )
+}
+
+// setup legacy global shortcuts:
+var loadGM = mw.lang.loadGM;
+var loadRS = mw.lang.loadRS;
+var gM = mw.lang.gM;
+
+// All default messages in [English] should be overwritten by the CMS language message system.
+mw.lang.loadGM( {
+       "mwe-loading_txt" : "Loading ...",
+       "mwe-size-gigabytes" : "$1 GB",
+       "mwe-size-megabytes" : "$1 MB",
+       "mwe-size-kilobytes" : "$1 K",
+       "mwe-size-bytes" : "$1 B",
+       "mwe-error_load_lib" : "Error: JavaScript $1 was not retrievable or does not define $2",
+       "mwe-loading-add-media-wiz" : "Loading add media wizard",
+       "mwe-apiproxy-setup" : "Setting up API proxy",
+       "mwe-load-drag-item" : "Loading dragged item",
+       "mwe-ok" : "OK",
+       "mwe-cancel" : "Cancel"
+} );
+
+
+// Get the loading image
+function mv_get_loading_img( style, class_attr ) {
+       var style_txt = ( style ) ? style:'';
+       var class_attr = ( class_attr ) ? 'class="' + class_attr + '"' : 'class="mv_loading_img"';
+       return '<div ' + class_attr + ' style="' + style + '"></div>';
+}
+
+function mv_set_loading( target, load_id ) {
+       var id_attr = ( load_id ) ? ' id="' + load_id + '" ':'';
+       $j( target ).append( '<div ' + id_attr + ' style="position:absolute;top:0px;left:0px;height:100%;width:100%;' +
+               'background-color:#FFF;">' +
+                       mv_get_loading_img( 'top:30px;left:30px' ) +
+               '</div>' );
+}
+
+/**
+* mvJsLoader class handles initialization and js file loads
+*/
+var mvJsLoader = {
+       libreq : { },
+       libs : { },
+
+       // Base lib flags
+       onReadyEvents: new Array(),
+       doneReadyEvents: false,
+       jQuerySetupFlag: false,
+
+       // To keep consistency across threads
+       ptime: 0,
+       ctime: 0,
+
+       load_error: false, // Load error flag (false by default)
+       load_time: 0,
+       callbacks: new Array(),
+       cur_path: null,
+       missing_path : null,
+       doLoad: function( loadLibs, callback ) {
+               this.ctime++;
+               if ( loadLibs && loadLibs.length != 0 ) {
+                       // js_log("doLoad setup::" + JSON.stringify( loadLibs ) );
+                       // Set up this.libs
+                       // First check if we already have this library loaded
+                       var all_libs_loaded = true;
+                       for ( var i = 0; i < loadLibs.length; i++ ) {
+                               // Check if the library is already loaded
+                               if ( ! this.checkObjPath( loadLibs[i] ) ) {
+                                       all_libs_loaded = false;
+                               }
+                       }
+                       if ( all_libs_loaded ) {
+                               js_log( 'Libraries ( ' + loadLibs  +  ') already loaded... skipping load request' );
+                               callback();
+                               return;
+                       }
+                       
+                       // Do a check for any CSS we may need and get it
+                       for ( var i = 0; i < loadLibs.length; i++ ) {
+                               if ( typeof mvCssPaths[ loadLibs[i] ] != 'undefined' ) {
+                                       loadExternalCss( mv_embed_path + mvCssPaths[ loadLibs[i] ] );
+                               }
+                       }
+
+                       // Check if we should use the script loader to combine all the requests into one
+                       // ( the scriptloader defines the mwSlScript global )
+                       if ( typeof mwSlScript != 'undefined' ) {
+                               var class_set = '';
+                               var last_class = '';
+                               var coma = '';
+                               for ( var i = 0; i < loadLibs.length; i++ ) {
+                                       var curLib = loadLibs[i];
+                                       // Only add if not included yet:
+                                       if ( ! this.checkObjPath( curLib ) ) {
+                                               class_set += coma + curLib;
+                                               last_class = curLib;
+                                               coma = ',';
+                                       }
+                               }
+                               // Build the url to the scriptServer striping its request parameters:
+                               var puri = mw.parseUri( getMvEmbedURL() );
+                               if ( ( getMvEmbedURL().indexOf( '://' ) != -1 )
+                                       && puri.host != mw.parseUri( document.URL ).host )
+                               {
+                                       var scriptPath = puri.protocol + '://' + puri.authority + puri.path;
+                               } else {
+                                       var scriptPath = puri.path;
+                               }
+                               // js_log('scriptServer Path is: ' + scriptPath + "\n host script path:" + getMvEmbedURL() );                           
+                               this.libs[ last_class ] = scriptPath + '?class=' + class_set +
+                                       '&' + getMwReqParam();
+
+                       } else {
+                               // Do many requests
+                               for ( var i = 0; i < loadLibs.length; i++ ) {
+                                       var curLib = loadLibs[i];
+                                       if ( curLib ) {
+                                               var libLoc = mvGetClassPath( curLib );
+                                               // Do a direct load of the file (pass along unique request id from
+                                               // request or mv_embed Version )
+                                               var qmark = ( libLoc.indexOf( '?' ) !== true ) ? '?' : '&';
+                                               this.libs[curLib] = mv_embed_path + libLoc + qmark + getMwReqParam();
+                                       }
+                               }
+                       }
+               }
+               
+               if ( callback ) {
+                       this.callbacks.push( callback );
+               }
+               if ( this.checkLoading() ) {
+                       // @@todo we should check the <script> Element .onLoad property to
+                       // make sure its just not a very slow connection
+                       // (even though the class is not loaded)
+                       if ( this.load_time++ > 4000 ) { // Time out after ~80 seconds
+                               js_log( gM( 'mwe-error_load_lib', [mvGetClassPath( this.missing_path ),  this.missing_path] ) );
+                               this.load_error = true;
+                       } else {
+                               setTimeout( 'mvJsLoader.doLoad()', 20 );
+                       }
+               } else {
+                       // js_log('checkLoading passed. Running callbacks...');
+                       // Only do callbacks if we are in the same instance (weird concurrency issue)
+                       var cb_count = 0;
+                       for ( var i = 0; i < this.callbacks.length; i++ )
+                               cb_count++;
+                       // js_log('RESET LIBS: loading is: '+ loading + ' callback count: '+cb_count +
+                       //      ' p:'+ this.ptime +' c:'+ this.ctime);
+
+                       // Reset the libs
+                       this.libs = { };
+                       // js_log('done loading, do call: ' + this.callbacks[0] );
+                       while ( this.callbacks.length != 0 ) {
+                               if ( this.ptime == this.ctime - 1 ) { // Enforce thread consistency
+                                       this.callbacks.pop()();
+                                       // func = this.callbacks.pop();
+                                       // js_log(' run: '+this.ctime+ ' p: ' + this.ptime + ' ' +loading+ ' :'+ func);
+                                       // func();
+                               } else {
+                                       // Re-issue doLoad ( ptime will be set to ctime so we should catch up)
+                                       setTimeout( 'mvJsLoader.doLoad()', 25 );
+                                       break;
+                               }
+                       }
+               }
+               this.ptime = this.ctime;
+       },
+       doLoadDepMode: function( loadChain, callback ) {
+               // Firefox executes JS in the order in which it is included, so just directly issue the request
+               if ( $j.browser.firefox ) {
+                       var loadSet = [];
+                       for ( var i = 0; i < loadChain.length; i++ ) {
+                               for ( var j = 0; j < loadChain[i].length; j++ ) {
+                                       loadSet.push( loadChain[i][j] );
+                               }
+                       }
+                       mvJsLoader.doLoad( loadSet, callback );
+               } else {
+                       // Safari and IE tend to execute out of order so load with dependency checks
+                       mvJsLoader.doLoad( loadChain.shift(), function() {
+                               if ( loadChain.length != 0 ) {
+                                       mvJsLoader.doLoadDepMode( loadChain, callback );
+                               } else {
+                                       callback();
+                               }
+                       } );
+               }
+       },
+       checkLoading: function() {
+               var loading = 0;
+               var i = null;
+               for ( var i in this.libs ) { // for/in loop is OK on an object
+                       if ( !this.checkObjPath( i ) ) {
+                               if ( !this.libreq[i] ) {
+                                       loadExternalJs( this.libs[i] );
+                               }
+                               this.libreq[i] = 1;
+                               // js_log("has not yet loaded: " + i);
+                               loading = 1;
+                       }
+               }
+               return loading;
+       },
+       checkObjPath: function( libVar ) {
+               if ( !libVar )
+                       return false;
+               var objPath = libVar.split( '.' )
+               var cur_path = '';
+               for ( var p = 0; p < objPath.length; p++ ) {
+                       cur_path = ( cur_path == '' ) ? cur_path + objPath[p] : cur_path + '.' + objPath[p];
+                       eval( 'var ptest = typeof ( ' + cur_path + ' ); ' );
+                       if ( ptest == 'undefined' ) {
+                               this.missing_path = cur_path;
+                               return false;
+                       }
+               }
+               this.cur_path = cur_path;
+               return true;
+       },
+       /**
+        * checks for jQuery and adds the $j noConflict var
+        */
+       jQueryCheck: function( callback ) {
+               // js_log( 'jQueryCheck::' + this.jQuerySetupFlag);
+               var _this = this;
+               if ( _global['$j'] && _this.jQuerySetupFlag ) {                 
+                       callback(); // call the callback now                    
+               }
+               // Load jQuery
+               _this.doLoad( [
+                       'window.jQuery'
+               ], function() {
+                       // only do the $j setup once:
+                       if ( !_global['$j'] ) {
+                               _global['$j'] = jQuery.noConflict();
+                       }
+                       if ( _this.jQuerySetupFlag == false ) {
+                               // js_log('setup mv_embed jQuery bindings');
+                               // Setup our global settings using the (jQuery helper)
+
+                               // Set up the skin path
+                               _global['mv_jquery_skin_path'] = mv_embed_path + 'jquery/jquery.ui/themes/' + mw.conf['jui_skin'] + '/';
+                               _global['mv_skin_img_path'] = mv_embed_path + 'skins/' + mw.conf['skin_name'] + '/images/';
+                               _global['mv_default_thumb_url'] = mv_skin_img_path + 'vid_default_thumb.jpg';
+
+                               // Make sure the skin/style sheets are always available:
+                               loadExternalCss( mv_jquery_skin_path + 'jquery-ui-1.7.1.custom.css' );
+                               loadExternalCss( mv_embed_path + 'skins/' + mw.conf['skin_name'] + '/styles.css' );
+
+                               // Set up AJAX to not send dynamic URLs for loading scripts (we control that with
+                               // the scriptLoader)
+                               $j.ajaxSetup( {
+                                       cache: true
+                               } );
+
+                               js_log( 'jQuery loaded into $j' );
+                               // Set up mvEmbed jQuery bindings and config based dependencies
+                               mv_jqueryBindings();
+                               _this.jQuerySetupFlag = true;
+                               
+                               // js_log('should run callback: ' + callback);
+                               // Run the callback if not already run above
+                               if ( callback ) {
+                                       callback();
+                               }
+                       }
+               } );
+       },
+       embedVideoCheck:function( callback ) {
+               var _this = this;
+               js_log( 'embedVideoCheck:' );
+               // Make sure we have jQuery
+               _this.jQueryCheck( function() {
+                       // set class videonojs to loading
+                       $j( '.videonojs' ).html( gM( 'mwe-loading_txt' ) );
+                       // Set up the embed video player class request: (include the skin js as well)
+                       var depReq = [
+                               [
+                                       '$j.ui',
+                                       'embedVideo',
+                                       'ctrlBuilder',
+                                       '$j.cookie'
+                               ],
+                               [
+                                       '$j.ui.slider'
+                               ]
+                       ];
+                       
+                       // add any requested skins (supports multiple skins per single page)
+                       if ( mw.skin_list ) {
+                               for ( var i in mw.skin_list  ) {
+                                       depReq[0].push( mw.skin_list[i] + 'Config' );
+                               }
+                       }
+
+                       // Add PNG fix if needed:
+                       if ( $j.browser.msie || $j.browser.version < 7 )
+                               depReq[0].push( '$j.fn.pngFix' );
+
+                       // load the video libs:
+                       _this.doLoadDepMode( depReq, function() {
+                               embedTypes.init();
+                               callback();
+                               $j( '.videonojs' ).remove();
+                       } );
+               } );
+       },
+       addLoadEvent: function( fn ) {
+               // js_log('add ready event: ' + fn );
+               this.onReadyEvents.push( fn );
+       },
+       // Check the jQuery flag. This way, when remote embedding, we don't load jQuery
+       // unless js2AddOnloadHook was used or there is video on the page.
+       runQueuedFunctions: function() {
+               js_log( "runQueuedFunctions" );
+               var _this = this;
+               this.jQueryCheck( function() {
+                       _this.runReadyEvents();
+                       _this.doneReadyEvents = true;
+               } );
+       },
+       runReadyEvents: function() {
+               js_log( "runReadyEvents" +  this.onReadyEvents.length );
+               while ( this.onReadyEvents.length ) {
+                       var func = this.onReadyEvents.shift();
+                       // js_log('run onReady:: ' + func );
+                       func();
+               }
+       }
+}
+
+// Shortcut ( @@todo consolidate shortcuts & re-factor mvJsLoader )
+function mwLoad( loadSet, callback ) {
+       mvJsLoader.doLoad( loadSet, callback );
+}
+// mw.shortcut
+mw.load = mwLoad;
+
+// Load an external JS file. Similar to jquery .require plugin,
+// but checks for object availability rather than load state.
+
+/*********** INITIALIZATION CODE *************
+ * This will get called when the DOM is ready
+ *********************************************/
+/* jQuery .ready does not work when jQuery is loaded dynamically.
+ * For an example of the problem see: 1.1.3 working: http://pastie.caboo.se/92588
+ * and >= 1.1.4 not working: http://pastie.caboo.se/92595
+ * $j(document).ready( function(){ */
+function mwdomReady( force ) {
+       js_log( 'f:mwdomReady:' );
+       if ( !force && mw.init_done ) {
+               js_log( "mw done, do nothing..." );
+               return false;
+       }
+       mw.init_done = true;
+       // Handle the execution of queued functions with jQuery "ready"
+
+       // Check if this page has a video, audio or playlist tag
+       var e = [
+               document.getElementsByTagName( "video" ),
+               document.getElementsByTagName( "audio" ),
+               document.getElementsByTagName( "playlist" )
+       ];
+       if ( e[0].length != 0 || e[1].length != 0 || e[2].length != 0 ) {
+               // look for any skin classes we have to load: 
+               for ( var j in e ) {
+                       for ( var k in e[j] ) {
+                               if ( e[j][k] && typeof( e[j][k] ) == 'object' ) {
+                                       var     sn = e[j][k].getAttribute( 'class' );
+                                       // Try "className" for good old IE                              
+                                       if( !sn ){
+                                               var     sn = e[j][k].getAttribute( 'className' );
+                                       }                                       
+                                       if ( sn && sn != '' ) {
+                                               for ( var n = 0; n < mw.valid_skins.length; n++ ) {
+                                                       if ( sn.indexOf( mw.valid_skins[n] ) !== -1 ) {
+                                                               mw.skin_list.push( mw.valid_skins[n] );
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+               // Load libs and process videos
+               mvJsLoader.embedVideoCheck( function() {
+                       // Run any queued global events:
+                       mv_video_embed( function() {
+                               mvJsLoader.runQueuedFunctions();
+                       } );
+               } );
+       } else {
+               mvJsLoader.runQueuedFunctions();
+       }
+}
+
+// js2AddOnloadHook: ensure jQuery and the DOM are ready
+function js2AddOnloadHook( func ) {
+       // js_log('js2AddOnloadHook:: jquery:' +func);  
+       // If we are ready run directly else add load event: 
+       if ( mvJsLoader.doneReadyEvents ) {
+               //js_log( 'run queued event: ' + func );
+               func();
+       } else {
+               //js_log( 'add to load event: ' + func );
+               mvJsLoader.addLoadEvent( func );
+       }
+}
+// Deprecated mwAddOnloadHook in favour of js2 naming (for clear separation of js2 code from old MW code
+var mwAddOnloadHook = js2AddOnloadHook;
+/*
+ * This function allows for targeted rewriting
+ */
+function rewrite_by_id( vid_id, ready_callback ) {
+       js_log( 'f:rewrite_by_id: ' + vid_id );
+       // Force a re-check of the DOM for playlist or video elements:
+       mvJsLoader.embedVideoCheck( function() {
+               mv_video_embed( ready_callback, vid_id );
+       } );
+}
+
+
+/*********** INITIALIZATION CODE *************
+ * set DOM-ready callback to init_mv_embed
+ *********************************************/
+// for Mozilla / modern browsers
+if ( document.addEventListener ) {
+       document.addEventListener( "DOMContentLoaded", mwdomReady, false );
+}
+var temp_f;
+if ( window.onload ) {
+    temp_f = window.onload;
+}
+// Use the onload method as a backup
+window.onload = function () {
+    if ( temp_f )
+        temp_f();
+       mwdomReady();
+}
+
+/*
+ * Store all the mwEmbed jQuery-specific bindings
+ * (set up after jQuery is available).
+ *
+ * These functions are generally are loaders that do the dynamic mapping of
+ * dependencies for a given component
+ * 
+ *
+ */
+function mv_jqueryBindings() {
+       js_log( 'mv_jqueryBindings' );
+       ( function( $ ) {
+               /*
+               * dragDrop file loader 
+               */
+               $.fn.dragFileUpload = function ( conf ) {
+                       if ( this.selector ) {
+                               var _this = this;
+                               // load the dragger and "setup"
+                               mw.load( ['$j.fn.dragDropFile'], function() {
+                                       $j( _this.selector ).dragDropFile();
+                               } );
+                       }
+               }
+               /*
+                * apiProxy Loader loader:
+                * 
+                * @param mode is either 'server' or 'client'
+                */
+               $.apiProxy = function( mode, pConf, callback ) {
+                       js_log( 'do apiProxy setup' );
+                       mvJsLoader.doLoad( [
+                               'mw.proxy',
+                               'JSON'
+                       ], function() {
+                               // do the proxy setup or 
+                               if ( mode == 'client' ) {
+                                       // just do the setup (no callbcak for client setup) 
+                                       mw.proxy.client( pConf );
+                                       if ( callback )
+                                               callback();
+                               } else if ( mode == 'server' ) {
+                                       // do the request with the callback
+                                       mw.proxy.server( pConf , callback );
+                               }
+                       } );
+               }
+               
+               // non selector based add-media-wizard direct invocation with loader
+               $.addMediaWiz = function( iObj, callback ) {
+                       js_log( ".addMediaWiz call" );
+                       // check if already loaded:
+                       if ( _global['rsdMVRS'] ) {
+                               _global['rsdMVRS'].showDialog();
+                               if ( callback )
+                                       callback( _global['rsdMVRS'] );
+                               return ;
+                       }
+                       // display a loader: 
+                       $.addLoaderDialog( gM( 'mwe-loading-add-media-wiz' ) );
+                       // load the addMedia wizard without a target: 
+                       $.fn.addMediaWiz ( iObj, function( amwObj ) {
+                               // close the dialog
+                               $.closeLoaderDialog();
+                               // do the add-media-wizard display
+                               amwObj.createUI();
+                               // call the parent callback:
+                               if ( callback )
+                                       callback( _global['rsdMVRS'] );
+                       } );
+               }
+               $.fn.addMediaWiz = function( iObj, callback ) {
+                       if ( this.selector ) {
+                               // First set the cursor for the button to "loading"
+                               $j( this.selector ).css( 'cursor', 'wait' ).attr( 'title', gM( 'mwe-loading_txt' ) );
+                               // set the target: 
+                               iObj['target_invoke_button'] = this.selector;
+                       }
+
+                       // Load the mv_embed_base skin:
+                       loadExternalCss( mv_jquery_skin_path + 'jquery-ui-1.7.1.custom.css' );
+                       loadExternalCss( mv_embed_path + 'skins/' + mw.conf['skin_name'] + '/styles.css' );
+                       // Load all the required libs:
+                       mvJsLoader.jQueryCheck( function() {
+                               // Load with staged dependencies (for IE that does not execute in order)
+                               mvJsLoader.doLoadDepMode( [
+                                       [       'remoteSearchDriver',
+                                               '$j.cookie',
+                                               '$j.fn.textSelection',
+                                               '$j.ui'
+                                       ], [
+                                               '$j.ui.resizable',
+                                               '$j.ui.draggable',
+                                               '$j.ui.dialog',
+                                               '$j.ui.tabs',
+                                               '$j.ui.sortable'
+                                       ]
+                               ], function() {
+                                       iObj['instance_name'] = 'rsdMVRS';
+                                       if ( ! _global['rsdMVRS'] )
+                                               _global['rsdMVRS'] = new remoteSearchDriver( iObj );
+                                       if ( callback ) {
+                                               callback( _global['rsdMVRS'] );
+                                       }
+                               } );
+                       } );
+               }
+               /*
+               * Sequencer loader
+               */
+               $.fn.sequencer = function( iObj, callback ) {
+                       // Debugger
+                       iObj['target_sequence_container'] = this.selector;
+                       // Issue a request to get the CSS file (if not already included):
+                       loadExternalCss( mv_jquery_skin_path + 'jquery-ui-1.7.1.custom.css' );
+                       loadExternalCss( mv_embed_path + 'skins/' + mw.conf['skin_name'] + '/mv_sequence.css' );
+                       // Make sure we have the required mv_embed libs (they are not loaded when no video
+                       // element is on the page)
+                       mvJsLoader.embedVideoCheck( function() {
+                               // Load the playlist object and then the jQuery UI stuff:
+                               mvJsLoader.doLoadDepMode( [
+                                       [
+                                               'mvPlayList',
+                                               '$j.ui',
+                                               '$j.contextMenu',
+                                               'JSON',
+                                               'mvSequencer'
+                                       ],
+                                       [
+                                               '$j.ui.accordion',
+                                               '$j.ui.dialog',
+                                               '$j.ui.droppable',
+                                               '$j.ui.draggable',
+                                               '$j.ui.progressbar',
+                                               '$j.ui.sortable',
+                                               '$j.ui.resizable',
+                                               '$j.ui.slider',
+                                               '$j.ui.tabs'
+                                       ]
+                               ], function() {
+                                       js_log( 'calling new mvSequencer' );
+                                       // Initialise the sequence object (it will take over from there)
+                                       // No more than one mvSeq obj for now:
+                                       if ( !_global['mvSeq'] ) {
+                                               _global['mvSeq'] = new mvSequencer( iObj );
+                                       } else {
+                                               js_log( 'mvSeq already init' );
+                                       }
+                               } );
+                       } );
+               }
+               /*
+                * The Firefogg jQuery function:
+                * @@note This Firefogg invocation could be made to work more like real jQuery plugins
+                */
+               var queuedFirefoggConf = { };
+               $.fn.firefogg = function( iObj, callback ) {
+                       if ( !iObj )
+                               iObj = { };
+                       // Add the base theme CSS:
+                       loadExternalCss( mv_jquery_skin_path + 'jquery-ui-1.7.1.custom.css' );
+                       loadExternalCss( mv_embed_path + 'skins/' + mw.conf['skin_name'] + '/styles.css' );
+
+                       // Check if we already have Firefogg loaded (the call just updates the element's
+                       // properties)
+                       var sElm = $j( this.selector ).get( 0 );
+                       if ( sElm['firefogg'] ) {
+                               if ( sElm['firefogg'] == 'loading' ) {
+                                       js_log( "Queued firefogg operations ( firefogg " +
+                                               "not done loading ) " );
+                                       $j.extend( queuedFirefoggConf, iObj );
+                                       return false;
+                               }
+                               // Update properties
+                               for ( var i in iObj ) {
+                                       js_log( "firefogg::updated: " + i + ' to ' + iObj[i] );
+                                       sElm['firefogg'][i] = iObj[i];
+                               }
+                               return sElm['firefogg'];
+                       } else {
+                               // Avoid concurrency
+                               sElm['firefogg'] = 'loading';
+                       }
+                       // Add the selector
+                       iObj['selector'] = this.selector;
+
+                       var loadSet = [
+                               [
+                                       'mvBaseUploadInterface',
+                                       'mvFirefogg',
+                                       '$j.ui'
+                               ],
+                               [
+                                       '$j.ui.progressbar',
+                                       '$j.ui.dialog',
+                                       '$j.ui.draggable'
+                               ]
+                       ];
+                       if ( iObj.encoder_interface ) {
+                               loadSet.push( [
+                                       'mvAdvFirefogg',
+                                       '$j.cookie',
+                                       '$j.ui.accordion',
+                                       '$j.ui.slider',
+                                       '$j.ui.datepicker'
+                               ] );
+                       }
+                       // Make sure we have everything loaded that we need:
+                       mvJsLoader.doLoadDepMode( loadSet, function() {
+                                       js_log( 'firefogg libs loaded. target select:' + iObj.selector );
+                                       // Select interface provider based on whether we want to include the
+                                       // encoder interface or not
+                                       if ( iObj.encoder_interface ) {
+                                               var myFogg = new mvAdvFirefogg( iObj );
+                                       } else {
+                                               var myFogg = new mvFirefogg( iObj );
+                                       }
+                                       if ( myFogg ) {
+                                               myFogg.doRewrite( callback );
+                                               var selectorElement = $j( iObj.selector ).get( 0 );
+                                               selectorElement['firefogg'] = myFogg;
+                                               
+                                               js_log( 'pre:' + selectorElement['firefogg']['firefogg_form_action'] )
+                                               if ( queuedFirefoggConf )
+                                                       $j.extend( selectorElement['firefogg'], queuedFirefoggConf );
+                                               js_log( 'post:' + selectorElement['firefogg']['firefogg_form_action'] )
+                                       }
+                       } );
+               }
+               // Take an input player as the selector and expose basic rendering controls
+               $.fn.firefoggRender = function( iObj, callback ) {
+                       // Check if we already have render loaded then just pass on updates/actions
+                       var sElm = $j( this.selector ).get( 0 );
+                       //add a special attribute to the selector: 
+                       if ( sElm['fogg_render'] ) {
+                               if ( sElm['fogg_render'] == 'loading' ) {
+                                       js_log( "Error: called firefoggRender while loading" );
+                                       return false;
+                               }
+                               // Call or update the property:
+                       }
+                       sElm['fogg_render'] = 'loading';
+                       // Add the selector
+                       iObj['player_target'] = this.selector;
+                       mvJsLoader.doLoad( [
+                               'mvBaseUploadInterface',
+                               'mvFirefogg',
+                               'mvFirefoggRender'
+                       ], function() {
+                               // Attach the firefoggRender obj to the selected elm: 
+                               sElm['fogg_render'] = new mvFirefoggRender( iObj );
+                               if ( callback && typeof callback == 'function' )
+                                       callback( sElm['fogg_render'] );
+                       } );
+               }
+
+               $.fn.baseUploadInterface = function( iObj ) {
+                       mvJsLoader.doLoadDepMode( [
+                               [
+                                       'mvBaseUploadInterface',
+                                       '$j.ui',
+                               ],
+                               [
+                                       '$j.ui.progressbar',
+                                       '$j.ui.dialog'
+                               ]
+                       ], function() {
+                               myUp = new mvBaseUploadInterface( iObj );
+                               myUp.setupForm();
+                       } );
+               }
+
+               // Shortcut to a themed button
+               $.btnHtml = function( msg, className, iconId, opt ) {
+                       if ( !opt )
+                               opt = { };
+                       var href = ( opt.href ) ? opt.href : '#';
+                       var target_attr = ( opt.target ) ? ' target="' + opt.target + '" ' : '';
+                       var style_attr = ( opt.style ) ? ' style="' + opt.style + '" ' : '';
+                       return '<a href="' + href + '" ' + target_attr + style_attr +
+                               ' class="ui-state-default ui-corner-all ui-icon_link ' +
+                               className + '"><span class="ui-icon ui-icon-' + iconId + '" ></span>' +
+                               '<span class="btnText">' + msg + '</span></a>';
+               }
+               // Shortcut to bind hover state
+               $.fn.btnBind = function() {
+                       $j( this ).hover(
+                               function() {
+                                       $j( this ).addClass( 'ui-state-hover' );
+                               },
+                               function() {
+                                       $j( this ).removeClass( 'ui-state-hover' );
+                               }
+                       )
+                       return this;
+               }
+               /**
+               * resize the dialog to fit the window
+               */
+               $.fn.dialogFitWindow = function( opt ) {
+                       var opt_default = { 'hspace':50, 'vspace':50 };
+                       if ( !opt )
+                               var opt = { };
+                       $j.extend( opt, opt_default );
+                       $j( this.selector ).dialog( 'option', 'width', $j( window ).width() - opt.hspace );
+                       $j( this.selector ).dialog( 'option', 'height', $j( window ).height() - opt.vspace );
+                       $j( this.selector ).dialog( 'option', 'position', 'center' );
+                               // update the child position: (some of this should be pushed up-stream via dialog config options
+                       $j( this.selector + '~ .ui-dialog-buttonpane' ).css( {
+                               'position':'absolute',
+                               'left':'0px',
+                               'right':'0px',
+                               'bottom':'0px'
+                       } );
+               }
+               
+               /**
+               * addLoaderDialog
+               *  small helper for putting a loading dialog box on top of everything
+               * (helps block for request that
+               *
+               * @param msg text text of the loader msg
+               */
+               $.addLoaderDialog = function( msg_txt ) {
+                       $.addDialog( msg_txt, msg_txt + '<br>' + mv_get_loading_img() );
+               }
+               
+               $.addDialog = function ( title, msg_txt, btn ) {
+                       $( '#mwe_tmp_loader' ).remove();
+                       // append the style free loader ontop: 
+                       $( 'body' ).append( '<div id="mwe_tmp_loader" style="display:none" title="' + title + '" >' +
+                                       msg_txt +
+                       '</div>' );
+                       // special btn == ok gives empty give a single "oky" -> "close"
+                       if ( btn == 'ok' ) {
+                               btn[ gM( 'mwe-ok' ) ] = function() {
+                                       $j( '#mwe_tmp_loader' ).close();
+                               }
+                       }
+                       // turn the loader into a real dialog loader: 
+                       mvJsLoader.doLoadDepMode( [
+                               [
+                                       '$j.ui'
+                               ],
+                               [
+                                       '$j.ui.dialog'
+                               ]
+                       ], function() {
+                               $( '#mwe_tmp_loader' ).dialog( {
+                                       bgiframe: true,
+                                       draggable: false,
+                                       resizable: false,
+                                       modal: true,
+                                       width:400,
+                                       buttons: btn
+                               } );
+                       } );
+               }
+               $.closeLoaderDialog = function() {
+                       mvJsLoader.doLoadDepMode( [
+                               [
+                                       '$j.ui'
+                               ],
+                               [
+                                       '$j.ui.dialog'
+                               ]
+                       ], function() {
+                               $j( '#mwe_tmp_loader' ).dialog( 'destroy' ).remove();
+                       } );
+               }
+       
+               $.mwProxy = function( apiConf ) {
+                       mvJsLoader.doLoad( ['mw.apiProxy'],
+                       function() {
+                               mw.apiProxy( apiConf );
+                       } );
+               }
+       } )( jQuery );
+}
+/*
+* Utility functions:
+*/
+// Simple URL rewriter (could probably be refactored into an inline regular exp)
+function getURLParamReplace( url, opt ) {
+       var pSrc = mw.parseUri( url );
+       if ( pSrc.protocol != '' ) {
+               var new_url = pSrc.protocol + '://' + pSrc.authority + pSrc.path + '?';
+       } else {
+               var new_url = pSrc.path + '?';
+       }
+       var amp = '';
+       for ( var key in pSrc.queryKey ) {
+               var val = pSrc.queryKey[ key ];
+               // Do override if requested
+               if ( opt[ key ] )
+                       val = opt[ key ];
+               new_url += amp + key + '=' + val;
+               amp = '&';
+       };
+       // Add any vars that were not already there:
+       for ( var i in opt ) {
+               if ( !pSrc.queryKey[i] ) {
+                       new_url += amp + i + '=' + opt[i];
+                       amp = '&';
+               }
+       }
+       return new_url;
+}
+/**
+ * Given a float number of seconds, returns npt format response.
+ *
+ * @param float Seconds
+ * @param boolean If we should show milliseconds or not.
+ */
+function seconds2npt( sec, show_ms ) {
+       if ( isNaN( sec ) ) {
+               // js_log("warning: trying to get npt time on NaN:" + sec);
+               return '0:0:0';
+       }
+       var hours = Math.floor( sec / 3600 );
+       var minutes = Math.floor( ( sec / 60 ) % 60 );
+       var seconds = sec % 60;
+       // Round the number of seconds to the required number of significant digits
+       if ( show_ms ) {
+               seconds = Math.round( seconds * 1000 ) / 1000;
+       } else {
+               seconds = Math.round( seconds );
+       }
+       if ( seconds < 10 )
+               seconds = '0' + seconds;
+       if ( minutes < 10 )
+               minutes = '0' + minutes;
+
+       return hours + ":" + minutes + ":" + seconds;
+}
+/*
+ * Take hh:mm:ss,ms or hh:mm:ss.ms input, return the number of seconds
+ */
+function npt2seconds( npt_str ) {
+       if ( !npt_str ) {
+               // js_log('npt2seconds:not valid ntp:'+ntp);
+               return false;
+       }
+       // Strip {npt:}01:02:20 or 32{s} from time  if present
+       npt_str = npt_str.replace( /npt:|s/g, '' );
+
+       var hour = 0;
+       var min = 0;
+       var sec = 0;
+
+       times = npt_str.split( ':' );
+       if ( times.length == 3 ) {
+               sec = times[2];
+               min = times[1];
+               hour = times[0];
+       } else if ( times.length == 2 ) {
+               sec = times[1];
+               min = times[0];
+       } else {
+               sec = times[0];
+       }
+       // Sometimes a comma is used instead of period for ms
+       sec = sec.replace( /,\s?/, '.' );
+       // Return seconds float
+       return parseInt( hour * 3600 ) + parseInt( min * 60 ) + parseFloat( sec );
+}
+/*
+ * Simple helper to grab an edit token
+ *
+ * @param title The wiki page title you want to edit
+ * @param api_url 'optional' The target API URL
+ * @param callback The callback function to pass the token to
+ */
+function get_mw_token( title, api_url, callback ) {
+       js_log( ':get_mw_token:' );
+       if ( !title && wgUserName ) {
+               title = 'User:' + wgUserName;
+       }
+       var reqObj = {
+                       'action': 'query',
+                       'prop': 'info',
+                       'intoken': 'edit',
+                       'titles': title
+               };
+       do_api_req( {
+               'data': reqObj,
+               'url' : api_url
+               }, function( data ) {
+                       for ( var i in data.query.pages ) {
+                               if ( data.query.pages[i]['edittoken'] ) {
+                                       if ( typeof callback == 'function' )
+                                               callback ( data.query.pages[i]['edittoken'] );
+                               }
+                       }
+                       // No token found:
+                       return false;
+               }
+       );
+}
+// Do a remote or local API request based on request URL
+// @param options: url, data, cbParam, callback
+function do_api_req( options, callback ) {
+       if ( typeof options.data != 'object' ) {
+               return js_error( 'Error: request paramaters must be an object' );
+       }
+       // Generate the URL if it's missing
+       if ( typeof options.url == 'undefined' || !options.url ) {
+               if ( typeof wgServer == 'undefined' ) {
+                       return js_error( 'Error: no api url for api request' );
+               }
+               options.url = mw.getLocalApiUrl();
+       }
+       if ( typeof options.data == 'undefined' )
+               options.data = { };
+
+       // Force format to JSON
+       options.data['format'] = 'json';
+
+       // If action is not set, assume query
+       if ( ! options.data['action'] )
+               options.data['action'] = 'query';
+
+       // js_log('do api req: ' + options.url +'?' + jQuery.param(options.data) );     
+       if ( options.url == 'proxy' && mw.proxy ) {
+               // assume the proxy is already "setup" since mw.proxy is defined.
+               // @@todo should probably integrate that setup into the api call
+               mw.proxy.doRequest( options.data,  callback );
+       } else if ( mw.parseUri( document.URL ).host == mw.parseUri( options.url ).host ) {
+               // Local request: do API request directly
+               $j.ajax( {
+                       type: "POST",
+                       url: options.url,
+                       data: options.data,
+                       dataType: 'json', // API requests _should_ always return JSON data:
+                       async: false,
+                       success: function( data ) {
+                               callback( data );
+                       },
+                       error: function( e ) {
+                               js_error( ' error' + e + ' in getting: ' + options.url );
+                       }
+               } );
+       } else {
+               // Remote request
+               // Set the callback param if it's not already set
+               if ( typeof options.jsonCB == 'undefined' )
+                       options.jsonCB = 'callback';
+
+               var req_url = options.url;
+               var paramAnd = ( req_url.indexOf( '?' ) == -1 ) ? '?' : '&';
+               // Put all the parameters into the URL
+               for ( var i in options.data ) {
+                       req_url += paramAnd + encodeURIComponent( i ) + '=' + encodeURIComponent( options.data[i] );
+                       paramAnd = '&';
+               }
+               var fname = 'mycpfn_' + ( mw.cb_count++ );
+               _global[ fname ] = callback;
+               req_url += '&' + options.jsonCB + '=' + fname;
+               loadExternalJs( req_url );
+       }
+}
+// Do a request:
+// @@note this contains metavid specific local vs remote api remapping.
+// this should be depreciated and we should use "$j.get" or an explicate api call 
+// (we should not mix the two request types) 
+function do_request( req_url, callback ) {
+       js_log( 'do_request::req_url:' + mw.parseUri( document.URL ) + ' != ' +  mw.parseUri( req_url ).host );
+       // If we are doing a request to the same domain or relative link, do a normal GET
+       if ( mw.parseUri( document.URL ).host == mw.parseUri( req_url ).host ||
+               req_url.indexOf( '://' ) == -1 ){ // if its a relative url go directly as well
+               // Do a direct request
+               $j.ajax( {
+                       type: "GET",
+                       url: req_url,
+                       async: false,
+                       success: function( data ) {
+                               callback( data );
+                       }
+               } );
+       } else {
+               // Get data via DOM injection with callback
+               global_req_cb.push( callback );
+               // Prepend json_ to feed_format if not already requesting json format (metavid specific) 
+               if ( req_url.indexOf( "feed_format=" ) != -1 && req_url.indexOf( "feed_format=json" ) == -1 )
+                       req_url = req_url.replace( /feed_format=/, 'feed_format=json_' );               
+               loadExternalJs( req_url + '&cb=mv_jsdata_cb&cb_inx=' + ( global_req_cb.length -1 ) );
+       }
+}
+
+function mv_jsdata_cb( response ) {
+       js_log( 'f:mv_jsdata_cb:' + response['cb_inx'] );
+       // Run the callback from the global request callback object
+       if ( !global_req_cb[response['cb_inx']] ) {
+               js_log( 'missing req cb index' );
+               return false;
+       }
+       if ( !response['pay_load'] ) {
+               js_log( "missing pay load" );
+               return false;
+       }
+       switch( response['content-type'] ) {
+               case 'text/plain':
+               break;
+               case 'text/xml':
+                       if ( typeof response['pay_load'] == 'string' ) {
+                                response['pay_load'] = mw.parseXML( response['pay_load'] );
+                       }
+               break
+               default:
+                       js_log( 'bad response type' + response['content-type'] );
+                       return false;
+               break;
+       }
+       global_req_cb[response['cb_inx']]( response['pay_load'] );
+}
+// Load external JS via DOM injection
+function loadExternalJs( url, callback ) {
+       js_log( 'load js: ' + url );
+       // if(window['$j']) // use jquery call:
+               /*$j.ajax({
+                       type: "GET",
+                       url: url,
+                       dataType: 'script',
+                       cache: true
+               });*/
+       // else{
+               var e = document.createElement( "script" );
+               e.setAttribute( 'src', url );
+               e.setAttribute( 'type', "text/javascript" );
+               /*if(callback)
+                       e.onload = callback;
+               */
+               // e.setAttribute('defer', true);
+               document.getElementsByTagName( "head" )[0].appendChild( e );
+       // }
+}
+function styleSheetPresent( url ) {
+       style_elements = document.getElementsByTagName( 'link' );
+       if ( style_elements.length > 0 ) {
+               for ( i = 0; i < style_elements.length; i++ ) {
+                       if ( style_elements[i].href == url )
+                               return true;
+               }
+       }
+       return false;
+}
+function loadExternalCss( url ) {
+       // We could have the script loader group these CSS requests.
+       // But it's debatable: it may hurt more than it helps with caching and all
+       if ( typeof url == 'object' ) {
+               for ( var i in url ) {
+                       loadExternalCss( url[i] );
+               }
+               return ;
+       }
+
+       if ( url.indexOf( '?' ) == -1 ) {
+               url += '?' + getMwReqParam();
+       }
+       if ( !styleSheetPresent( url ) ) {
+               js_log( 'load css: ' + url );
+               var e = document.createElement( "link" );
+               e.href = url;
+               e.type = "text/css";
+               e.rel = 'stylesheet';
+               document.getElementsByTagName( "head" )[0].appendChild( e );
+       }
+}
+function getMvEmbedURL() {
+       if ( _global['mv_embed_url'] )
+               return _global['mv_embed_url'];
+       var js_elements = document.getElementsByTagName( "script" );
+       for ( var i = 0; i < js_elements.length; i++ ) {
+               // Check for mv_embed.js and/or script loader
+               var src = js_elements[i].getAttribute( "src" );
+               if ( src ) {
+                       if ( src.indexOf( 'mv_embed.js' ) != -1 || (
+                               ( src.indexOf( 'mwScriptLoader.php' ) != -1 || src.indexOf( 'jsScriptLoader.php' ) != -1 )
+                               && src.indexOf( 'mv_embed' ) != -1 ) ) // (check for class=mv_embed script_loader call)
+                       {
+                               _global['mv_embed_url'] = src;
+                               return src;
+                       }
+               }
+       }
+       js_error( 'Error: getMvEmbedURL failed to get Embed Path' );
+       return false;
+}
+// Get a unique request ID to ensure fresh JavaScript
+function getMwReqParam() {
+       if ( _global['req_param'] )
+               return _global['req_param'];
+       var mv_embed_url = getMvEmbedURL();
+       
+       var req_param = '';
+       
+       // If we have a URI, add it to the req
+       var urid = mw.parseUri( mv_embed_url ).queryKey['urid']
+       // If we're in debug mode, get a fresh unique request key and pass on "debug" param
+       if ( mw.parseUri( mv_embed_url ).queryKey['debug'] == 'true' ) {
+               var d = new Date();
+               req_param += 'urid=' + d.getTime() + '&debug=true';
+       } else if ( urid ) {
+               // Set from request urid:
+               req_param += 'urid=' + urid;
+       } else {
+               // Otherwise, just use the mv_embed version
+               req_param += 'urid=' + mw.version;
+       }
+       // add the lang param:
+       var langKey = mw.parseUri( mv_embed_url ).queryKey['uselang'];
+       if ( langKey )
+               req_param += '&uselang=' + langKey;
+                       
+       _global['req_param'] = req_param;
+               
+       return _global['req_param'];
+}
+/*
+ * Set the global mv_embed path based on the script's location
+ */
+function getMvEmbedPath() {
+       if ( _global['mv_embed_path'] )
+               return _global['mv_embed_path'];
+       var mv_embed_url = getMvEmbedURL();
+       if ( mv_embed_url.indexOf( 'mv_embed.js' ) !== -1 ) {
+               mv_embed_path = mv_embed_url.substr( 0, mv_embed_url.indexOf( 'mv_embed.js' ) );
+       } else if ( mv_embed_url.indexOf( 'mwScriptLoader.php' ) !== -1 ) {
+               // Script loader is in the root of MediaWiki, so include the default mv_embed extension path
+               mv_embed_path = mv_embed_url.substr( 0, mv_embed_url.indexOf( 'mwScriptLoader.php' ) )
+                       + mediaWiki_mvEmbed_path;
+       } else {
+               mv_embed_path = mv_embed_url.substr( 0, mv_embed_url.indexOf( 'jsScriptLoader.php' ) );
+       }
+       // Make an absolute URL (if it's relative and we don't have an mv_embed path)
+       if ( mv_embed_path.indexOf( '://' ) == -1 ) {
+               var pURL = mw.parseUri( document.URL );
+               if ( mv_embed_path.charAt( 0 ) == '/' ) {
+                       mv_embed_path = pURL.protocol + '://' + pURL.authority + mv_embed_path;
+               } else {
+                       // Relative
+                       if ( mv_embed_path == '' ) {
+                               mv_embed_path = pURL.protocol + '://' + pURL.authority + pURL.directory + mv_embed_path;
+                       }
+               }
+       }
+       _global['mv_embed_path'] = mv_embed_path;
+       return mv_embed_path;
+}
+
+if ( typeof DOMParser == "undefined" ) {
+       DOMParser = function () { }
+       DOMParser.prototype.parseFromString = function ( str, contentType ) {
+               if ( typeof ActiveXObject != "undefined" ) {
+                       var d = new ActiveXObject( "MSXML.DomDocument" );
+                       d.loadXML( str );
+                       return d;
+               } else if ( typeof XMLHttpRequest != "undefined" ) {
+                       var req = new XMLHttpRequest;
+                       req.open( "GET", "data:" + ( contentType || "application/xml" ) +
+                                       ";charset=utf-8," + encodeURIComponent( str ), false );
+                       if ( req.overrideMimeType ) {
+                               req.overrideMimeType( contentType );
+                       }
+                       req.send( null );
+                       return req.responseXML;
+               }
+       }
+}
+/*
+* Utility functions
+*/
+function js_log( string ) {
+       // Add any prepend debug strings if necessary (used for cross browser)
+       if ( mw.conf['debug_pre'] )
+               string = mw.conf['debug_pre'] + string;
+                       
+       if ( window.console ) {
+               window.console.log( string );
+       } else {
+               /*
+                * IE and non-Firebug debug:
+                */
+               /*var log_elm = document.getElementById('mv_js_log');
+               if(!log_elm){
+                       document.getElementsByTagName("body")[0].innerHTML = document.getElementsByTagName("body")[0].innerHTML +
+                               '<div style="position:absolute;z-index:500;top:0px;left:0px;right:0px;height:10px;">'+
+                               '<textarea id="mv_js_log" cols="120" rows="5"></textarea>'+
+                               '</div>';
+
+                       var log_elm = document.getElementById('mv_js_log');
+               }
+               if(log_elm){
+                       log_elm.value+=string+"\n";
+               }*/
+       }
+       return false;
+}
+
+function js_error( string ) {
+       alert( string );
+       return false;
+}
diff --git a/js2/mwEmbed/php/jsAutoloadLocalClasses.php b/js2/mwEmbed/php/jsAutoloadLocalClasses.php
new file mode 100644 (file)
index 0000000..0a37c7c
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+if ( !defined( 'MEDIAWIKI' ) ) die( 1 );
+
+global $wgJSAutoloadLocalClasses, $wgMwEmbedDirectory;
+
+// Load classes from  mv_embed.js
+if ( is_file( $wgMwEmbedDirectory . 'mv_embed.js' ) ) {
+
+       //read the head of the file::
+       $f = fopen( $wgMwEmbedDirectory . 'mv_embed.js' , 'r');
+       $jsvar = '';
+       $file_head='';
+       while (!feof($f)) {
+               $file_head.= fread($f, 8192);
+               // Call jsClassPathLoader() for each lcPaths() call in the JS source
+               $replace_test = preg_replace_callback(
+                       '/lcPaths\s*\(\s*{(.*)}\s*\)\s*/siU',
+                       'jsClassPathLoader',
+                       $file_head
+               );
+               if( $replace_test !== false )
+                       break;
+       }
+       fclose( $f );
+}
+function jsClassPathLoader( $jvar ) {
+       global $wgJSAutoloadLocalClasses, $wgMwEmbedDirectory;
+       if ( !isset( $jvar[1] ) )
+               return false;
+       $jClassSet = json_decode( '{' . $jvar[1] . '}', true );
+       foreach ( $jClassSet as $jClass => $jPath ) {
+               // Strip $ from jClass (as they are stripped on URL request parameter input)
+               $jClass = str_replace( '$', '', $jClass );
+               $wgJSAutoloadLocalClasses[$jClass] = $wgMwEmbedDirectory . $jPath;
+       }
+}
diff --git a/js2/mwEmbed/php/languages/cldrConverter.php b/js2/mwEmbed/php/languages/cldrConverter.php
new file mode 100644 (file)
index 0000000..fc187b3
--- /dev/null
@@ -0,0 +1,205 @@
+<?php
+/*
+ * cldr format tries to build a structured representation of
+ * http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html
+ *
+ * it has structure similar to
+ * http://www.unicode.org/repos/cldr/tags/release-1-7-1/common/supplemental/plurals.xml
+ *
+ * It works by mapping array indexes to forms passed in via the PLURAL call
+ * the plural types are linear mapped to PLURAL argument index.
+ *
+ * Rules should come in the following order:
+ *  zero, one, two, few, many, other (other is a special default case that applies to all)
+ *
+ * cldr also allows export of rule sets in json to associated javascript
+ */
+class cldrConverter {
+       static $masterCLDR = array(
+               // if locales is known to have no plurals, there are no rules
+               array(
+                       'locales'=> array('az','fa','hu','ja','ko','my to','tr','vi','yo','zh',
+                                                               'bo','dz','id','jv ka','km','kn','ms','th')
+               ),
+               array(
+                       'locales'=> array('ar'),
+                       'rules' => array(
+                               'zero'  => 0,
+                               'one'   => 1,
+                               'two'   => 2,
+                               //n mod 100 in 3..10
+                               'few'   => array( 'mod' => 100, 'is'=>'3-10' ),
+                               //n mod 100 in 11..99
+                               'many'  => array( 'mod' => 100, 'is'=>'11-99')
+                       )
+               ),
+               array( 'locales' => array(      'da','de','el','en','eo','es','et','fi','fo','gl',
+                                                                       'he','iw','it','nb','nl','nn','no','pt_PT','sv',
+                                                                       'af','bg','bn','ca','eu','fur','fy','gu','ha',
+                                                                       'is','ku','lb','ml','mr','nah','ne','om','or',
+                                                                       'pa','pap','ps','so','sq','sw','ta','te','tk',
+                                                                       'ur','zu','mn','gsw'),
+                               'rules' => array(
+                                       'one' => 1
+                               )
+               ),
+               array(  'locales' => array('pt','am','bh','fil','tl','guw','hi','ln','mg','nso','ti','wa'),
+                               'rules'=> array(
+                                       'one'=> '0-1'
+                               )
+               ),
+               array(  'locales' => array('fr'),
+                               'rules'=>array(
+                                       //n within 0..2 and n is not 2
+                                       'one' => array( 'is'=>'0-2', 'not' => 2)
+                               )
+               ),
+               array(  'locales' => array('lv'),
+                               'rules' => array(
+                                       'zero' => 0,
+                                       //n mod 10 is 1 and n mod 100 is not 11
+                                       'one'=>array(
+                                                       array( 'mod' => 10, 'is' => 1 ),
+                                                       //AND
+                                                       array( 'mod' => 100, 'not' => 11)
+                                               )
+                               )
+               ),
+               array(  'locales' => array('ga','se','sma','smi','smj','smn','sms'),
+                               'rules' => array(
+                                       'one' => 1,
+                                       'two' => 2
+                               )
+               ),
+               array(  'locales' => array('ro','mo'),
+                               'rules' => array(
+                                       'one' => 1,
+                                       //n is 0 OR n is not 1 AND n mod 100 in 1..19
+                                       'few' => array(
+                                                               'or'=> array(
+                                                                       array( 'is' => 0),                                                              
+                                                                       array(
+                                                                               array( 'not' => 1),
+                                                                               //and
+                                                                               array( 'mod' => 100, 'is'=>'1-19')
+                                                                       )
+                                                               )
+                                                       )
+                               )
+               ),
+               array(  'locales' => array( 'lt' ),
+                               'rules' => array(
+                                       //n mod 10 is 1 and n mod 100 not in 11..19
+                                       'one' => array(
+                                                               array( 'mod'=>10, 'is'=> 1 ),
+                                                               array( 'mod'=> 100, 'not'=> '11-19')
+                                                       ),
+                                       //n mod 10 in 2..9 and n mod 100 not in 11..19
+                                       'few' => array(
+                                                               array( 'mod'=> 10, 'is'=> '2-9' ),
+                                                               array( 'mod'=> 100, 'not' => '11-19')
+                                                       ),
+                               )
+               ),
+               array(  'locales' => array( 'hr','ru','sr','uk','be','bs','sh' ),
+                               'rules' => array(
+                                       //n mod 10 is 1 and n mod 100 is not 11
+                                       'one' => array(
+                                               array( 'mod' => 10, 'is' => 1),
+                                               array( 'mod' => 100, 'not' => 11)
+                                       ),
+                                       //n mod 10 in 2..4 and n mod 100 not in 12..14
+                                       'few' => array(
+                                               array( 'mod' => 10, 'is' => '2-4'),
+                                               array( 'mod' => 100, 'not' => '12-14')
+                                       ),
+                                       //n mod 10 is 0 or n mod 10 in 5..9 or n mod 100 in 11..14
+                                       'many' => array(
+                                               'or'=>array(
+                                                       array( 'mod'=> 10, 'is' => 0),
+                                                       array( 'mod'=> 10, 'is' => '5-9'),
+                                                       array( 'mod'=> 100, 'is' => '11-14')
+                                               )
+                                       ),
+                               )
+               ),
+               array(  'locales' => array('cs','sk'),
+                               'rules' => array(
+                                       'one' => 1,
+                                       'few'=> '2-4'
+                               )
+               ),
+               array(  'locales' => array('pl'),
+                               'rules '=> array(
+                                       'one' => 1,
+                                       'few' => array(
+                                               //n mod 10 in 2..4
+                                               array( 'mod' => 10, 'is' => '2-4'),
+                                               //and n mod 100 not in 12..14
+                                               array( 'mod' => 100, 'not'=> '12-14'),
+                                               //and n mod 100 not in 22..24
+                                               array( 'mod' => 100, 'in' => '22-24')
+                                       )
+                               )
+               ),
+               array(  'locales' => array('sl'),
+                               'rules' => array(
+                                       'one' => array( 'mod'=>100, 'is' => 1 ),
+                                       'two' => array( 'mod'=>100, 'is' => 2 ),
+                                       'few' => array( 'mod'=>100, 'is' => '3-4')
+                               )
+               ),
+               array(  'locales' => array('mt'),
+                               'rules' => array(
+                                       'one' => 1,
+                                       //n is 0 or n mod 100 in 2..10
+                                       'few' => array(
+                                               array( 'is' => 0 ),
+                                               'or',
+                                               array( 'mod' => 100, 'is' => '2-10')
+                                       ),
+                                       //n mod 100 in 11..19
+                                       'many' => array( 'mod'=>100, 'is' => '11-19')
+                               )
+               ),
+               array(  'locales' => array( 'mk' ),
+                               'rules' => array(
+                                       'one' => array('mod' => 10, 'is' => '1')
+                               )
+               ),
+               array(  'locales' => array( 'cy' ),
+                               'rules' => array(
+                                       'one' => 1,
+                                       'two' => 2,
+                                       //n is 8 or n is 11
+                                       'many' => array(
+                                               array( 'is' => 8 ),
+                                               array( 'is' => 11 )
+                                       )
+                               )
+               )
+       );
+       //takes the cldr representation and returns the proper form
+       function cldrConvertPlural($count, $forms){
+               if ( !count($forms) ) { return ''; }
+               //get the rule set
+               $ruleSet = $this->getCldrRuleSet();
+               //get the number of forms (ruleSet Count + 1 for 'other' )
+               $fomsCount = count( $ruleSet ) + 1;
+
+               //if count is 1 no plurals for this language:
+               if( count( $forms ) == 1)
+                       return $forms[0];
+
+       }
+
+       static function getCldrRuleSet( $code ){
+               foreach(self::$masterCLDR as $ruleSet){
+                       if( in_array($code, $ruleSet['locales']) ){
+                               return $ruleSet['rules'];
+                       }
+               }
+               //could not find the language code
+               return false;
+       }
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/php/languages/mwEmbed.i18n.php b/js2/mwEmbed/php/languages/mwEmbed.i18n.php
new file mode 100644 (file)
index 0000000..deacc75
--- /dev/null
@@ -0,0 +1,9096 @@
+<?php
+
+/**
+ * Localization file for mwEmbed
+ * updates can be merged from javascript by running maintenance/mergeJavascriptMsg.php
+ * this file follows the "extension" conventions for language msgs in MediaWiki but should be "usable" stand-alone with the script-loader
+ *
+ * the following English language portion is automatically merged via the maintenance script.
+ */
+
+$messages = array();
+
+$messages['en'] = array(
+       /*
+        * js file: /libClipEdit/mvClipEdit.js
+        */
+       'mwe-crop' => 'Crop image',
+       'mwe-apply_crop' => 'Apply crop to image',
+       'mwe-reset_crop' => 'Reset crop',
+       'mwe-insert_image_page' => 'Insert into page',
+       'mwe-insert_into_sequence' => 'Insert into sequence',
+       'mwe-preview_insert' => 'Preview insert',
+       'mwe-cancel_image_insert' => 'Cancel insert',
+       'mwe-sc_fileopts' => 'Clip detail edit',
+       'mwe-sc_inoutpoints' => 'Set in-out points',
+       'mwe-sc_overlays' => 'Overlays',
+       'mwe-sc_audio' => 'Audio control',
+       'mwe-sc_duration' => 'Duration',
+       'mwe-template_properties' => 'Template properties',
+       'mwe-custom_title' => 'Custom title',
+       'mwe-edit_properties' => 'Edit properties',
+       'mwe-other_properties' => 'Other properties',
+       'mwe-resource_page' => 'Resource page:',
+       'mwe-set_in_out_points' => 'Set in-out points',
+       'mwe-start_time' => 'Start time',
+       'mwe-end_time' => 'End time',
+       'mwe-preview_inout' => 'Preview in-out points',
+       'mwe-edit-tools' => 'Edit tools',
+       'mwe-inline-description' => 'Caption',
+       'mwe-edit-video-tools' => 'Edit video tools:',
+       'mwe-duration' => 'Duration:',
+
+       /*
+        * js file: /libTimedText/mvTimeTextEdit.js
+        */
+       'mwe-upload-subs-file' => 'Upload subtitle',
+       'mwe-add-subs-file-title' => 'Select subtitle to upload',
+       'mwe-error-only-srt' => 'You can only upload srt files.',
+       'mwe-watch-video' => 'Watch video',
+       'mwe-select-other-language' => 'Select another language',
+       'mwe-saving' => 'saving...',
+
+       /*
+        * js file: /libTimedText/mvTextInterface.js
+        */
+       'mwe-select_transcript_set' => 'Select subtitles',
+       'mwe-auto_scroll' => 'auto scroll',
+       'mwe-close' => 'close',
+       'mwe-improve_transcript' => 'Improve',
+       'mwe-no_text_tracks_found' => 'No text subtitles found',
+       'mwe-add-edit-subs' => 'Add/edit subtitles',
+
+       /*
+        * js file: /libSequencer/mvTimedEffectsEdit.js
+        */
+       'mwe-transition_in' => 'Transition in',
+       'mwe-transition_out' => 'Transition out',
+       'mwe-effects' => 'Effects stack',
+       'mwe-remove_transition' => 'Remove transition',
+       'mwe-edit_transin' => 'Edit transition into clip',
+       'mwe-edit_transout' => 'Edit transition out of clip',
+       'mwe-add-transition' => 'Add a transition',
+
+       /*
+        * js file: /libSequencer/mvSequencer.js
+        */
+       'mwe-menu_clipedit' => 'Edit media',
+       'mwe-menu_transition' => 'Transitions and effects',
+       'mwe-menu_cliplib' => 'Add media',
+       'mwe-menu_resource_overview' => 'Resource overview',
+       'mwe-menu_options' => 'Options',
+       'mwe-loading_timeline' => 'Loading timeline ...',
+       'mwe-loading_user_rights' => 'Loading user rights ...',
+       'mwe-no_edit_permissions' => 'You do not have permissions to save changes to this sequence',
+       'mwe-edit_clip' => 'Edit clip',
+       'mwe-edit_save' => 'Save sequence changes',
+       'mwe-saving_wait' => 'Save in progress (please wait)',
+       'mwe-save_done' => 'Save complete',
+       'mwe-edit_cancel' => 'Cancel sequence edit',
+       'mwe-edit_cancel_confirm' => 'Are you sure you want to cancel your edit? Changes will be lost.',
+       'mwe-zoom_in' => 'Zoom in',
+       'mwe-zoom_out' => 'Zoom out',
+       'mwe-cut_clip' => 'Cut clips',
+       'mwe-expand_track' => 'Expand track',
+       'mwe-collapse_track' => 'Collapse track',
+       'mwe-play_from_position' => 'Play from playline position',
+       'mwe-pixle2sec' => 'pixels to seconds',
+       'mwe-rmclip' => 'Remove clip',
+       'mwe-clip_in' => 'clip in',
+       'mwe-clip_out' => 'clip out',
+       'mwe-welcome_to_sequencer' => '<h3>Welcome to the sequencer demo</h3> Very <b>limited</b> functionality right now. Not much documentation yet either.',
+       'mwe-no_selected_resource' => '<h3>No resource selected</h3> Select a clip to enable editing.',
+       'mwe-error_edit_multiple' => '<h3>Multiple resources selected</h3> Select a single clip to edit it.',
+       'mwe-editor_options' => 'Editor options',
+       'mwe-editor_mode' => 'Editor mode',
+       'mwe-simple_editor_desc' => 'simple editor (iMovie style)',
+       'mwe-advanced_editor_desc' => 'advanced editor (Final Cut style)',
+       'mwe-other_options' => 'Other options',
+       'mwe-contextmenu_opt' => 'Enable context menus',
+       'mwe-sequencer_credit_line' => 'Developed by <a href="http://kaltura.com">Kaltura, Inc.</a> in partnership with the <a href="http://wikimediafoundation.org/wiki/Home">Wikimedia Foundation</a> (<a href="#">more information</a>).',
+
+       /*
+        * js file: /mv_embed.js
+        */
+       'mwe-loading_txt' => 'Loading ...',
+       'mwe-size-gigabytes' => '$1 GB',
+       'mwe-size-megabytes' => '$1 MB',
+       'mwe-size-kilobytes' => '$1 K',
+       'mwe-size-bytes' => '$1 B',
+       'mwe-error_load_lib' => 'Error: JavaScript $1 was not retrievable or does not define $2',
+       'mwe-loading-add-media-wiz' => 'Loading add media wizard',
+       'mwe-apiproxy-setup' => 'Setting up API proxy',
+       'mwe-load-drag-item' => 'Loading dragged item',
+       'mwe-ok' => 'OK',
+       'mwe-cancel' => 'Cancel',
+
+       /*
+        * js file: /libMwApi/mw.proxy.js
+        */
+       'mwe-setting-up-proxy' => 'Setting up proxy...',
+       'mwe-re-try' => 'Retry API request',
+       'mwe-re-trying' => 'Retrying API request...',
+       'mwe-proxy-not-ready' => 'Proxy is not configured',
+       'mwe-please-login' => 'You are not <a target="_new" href="$1">logged in</a> on $2 or mwEmbed has not been enabled. Resolve the issue, and then retry the request.',
+       'mwe-remember-loging' => 'General security reminder: Only login to web sites when your address bar displays that site\'s address.',
+
+       /*
+        * js file: /libAddMedia/mvFirefogg.js
+        */
+       'fogg-select_file' => 'Select file',
+       'fogg-select_new_file' => 'Select new file',
+       'fogg-select_url' => 'Select URL',
+       'fogg-save_local_file' => 'Save Ogg',
+       'fogg-check_for_firefogg' => 'Checking for Firefogg...',
+       'fogg-installed' => 'Firefogg is installed',
+       'fogg-for_improved_uploads' => 'For improved uploads:',
+       'fogg-please_install' => '<a href="$1">Install Firefogg</a>. More <a href="http://commons.wikimedia.org/wiki/Commons:Firefogg">about Firefogg</a>.',
+       'fogg-use_latest_firefox' => 'Please first install <a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=firefogg">Firefox 3.5</a> (or later). <i>Then revisit this page to install the <b>Firefogg</b> extension.</i>',
+       'fogg-passthrough_mode' => 'Your selected file is already Ogg or not a video file',
+       'fogg-transcoding' => 'Encoding video to Ogg...',
+       'fogg-encoding-done' => 'Encoding complete',
+       'fogg-badtoken' => 'Token is not valid',
+       'fogg-preview' => 'Preview video',
+       'fogg-hidepreview' => 'Hide preview',
+
+       /*
+        * js file: /libAddMedia/searchLibs/baseRemoteSearch.js
+        */
+       'mwe-imported_from' => '$1 imported from [$2 $3]. See the original [$4 resource page] for more information.',
+
+       /*
+        * js file: /libAddMedia/searchLibs/metavidSearch.js
+        */
+       'mwe-stream_title' => '$1 $2 to $3',
+
+       /*
+        * js file: /libAddMedia/mvAdvFirefogg.js
+        */
+       'fogg-help-sticky' => 'Help (click to stick)',
+       'fogg-cg-preset' => 'Preset: <strong>$1</strong>',
+       'fogg-cg-quality' => 'Basic quality and resolution control',
+       'fogg-cg-meta' => 'Metadata for the clip',
+       'fogg-cg-range' => 'Encoding range',
+       'fogg-cg-advVideo' => 'Advanced video encoding controls',
+       'fogg-cg-advAudio' => 'Advanced audio encoding controls',
+       'fogg-preset-custom' => 'Custom settings',
+       'fogg-webvideo-desc' => 'Web video Theora, Vorbis 400 kbit/s and 400px maximum width',
+       'fogg-savebandwidth-desc' => 'Low bandwidth Theora, Vorbis 164 kbit/s and 200px maximum width',
+       'fogg-highquality-desc' => 'High quality Theora, Vorbis 1080px maximum width',
+       'fogg-videoQuality-title' => 'Video quality',
+       'fogg-videoQuality-help' => 'Used to set the <i>visual quality</i> of the encoded video (not used if you set bitrate in advanced controls below).',
+       'fogg-starttime-title' => 'Start second',
+       'fogg-starttime-help' => 'Only encode from time in seconds',
+       'fogg-endtime-title' => 'End second',
+       'fogg-endtime-help' => 'Only encode to time in seconds',
+       'fogg-audioQuality-title' => 'Audio quality',
+       'fogg-audioQuality-help' => 'Used to set the <i>acoustic quality</i> of the encoded audio (not used if you set bitrate in advanced controls below).',
+       'fogg-videoCodec-title' => 'Video codec',
+       'fogg-videoCodec-help' => 'Used to select the clip video codec. Presently only Theora is supported. More about the <a target="_new" href="http://en.wikipedia.org/wiki/Theora">Theora codec</a>.',
+       'fogg-audioCodec-title' => 'Audio codec',
+       'fogg-audioCodec-help' => 'Used to set the clip audio codec. Presently only Vorbis is supported. More about the <a target="_new" href="http://en.wikipedia.org/wiki/Vorbis">Vorbis codec</a>',
+       'fogg-width-title' => 'Video width',
+       'fogg-width-help' => 'Resize to given width.',
+       'fogg-height-title' => 'Video height',
+       'fogg-height-help' => 'Resize to given height.',
+       'fogg-videoBitrate-title' => 'Video bitrate',
+       'fogg-videoBitrate-help' => 'Video bitrate sets the encoding bitrate for video in (kb/s)',
+       'fogg-twopass-title' => 'Two pass encoding',
+       'fogg-twopass-help' => 'Two pass encoding enables more constant quality by making two passes over the video file',
+       'fogg-framerate-title' => 'Frame rate',
+       'fogg-framerate-help' => 'The video frame rate. More about <a target="_new" href="http://en.wikipedia.org/wiki/Frame_rate">frame rate</a>.',
+       'fogg-aspect-title' => 'Aspect ratio',
+       'fogg-aspect-help' => 'The video aspect ratio can be 4:3 or 16:9. More about <a target="_new" href="http://en.wikipedia.org/wiki/Aspect_ratio_%28image%29">aspect ratios</a>.',
+       'fogg-keyframeInterval-title' => 'Key frame interval',
+       'fogg-keyframeInterval-help' => 'The keyframe interval in frames. Note: Most codecs force keyframes if the difference between frames is greater than keyframe encode size. More about <a href="http://en.wikipedia.org/wiki/I-frame">keyframes</a>.',
+       'fogg-denoise-title' => 'Denoise filter',
+       'fogg-denoise-help' => 'Denoise input video. More about <a href="http://en.wikipedia.org/wiki/Video_denoising">denoise</a>.',
+       'fogg-novideo-title' => 'No video',
+       'fogg-novideo-help' => 'disable video in the output',
+       'fogg-audioBitrate-title' => 'Audio bitrate',
+       'fogg-samplerate-title' => 'Audio sampling rate',
+       'fogg-samplerate-help' => 'set output sample rate (in Hz).',
+       'fogg-noaudio-title' => 'No audio',
+       'fogg-noaudio-help' => 'disable audio in the output',
+       'fogg-title-title' => 'Title',
+       'fogg-title-help' => 'A title for your clip',
+       'fogg-artist-title' => 'Creator name',
+       'fogg-artist-help' => 'The creator of this clip',
+       'fogg-date-title' => 'Date',
+       'fogg-date-help' => 'The date the footage was created or released',
+       'fogg-location-title' => 'Location',
+       'fogg-location-help' => 'The location of the footage',
+       'fogg-organization-title' => 'Organization',
+       'fogg-organization-help' => 'Name of organization (studio)',
+       'fogg-copyright-title' => 'Copyright',
+       'fogg-copyright-help' => 'The copyright of the clip',
+       'fogg-license-title' => 'License',
+       'fogg-license-help' => 'The license of the clip (preferably a Creative Commons URL).',
+       'fogg-contact-title' => 'Contact',
+       'fogg-contact-help' => 'Contact link',
+
+       /*
+        * js file: /libAddMedia/remoteSearchDriver.js
+        */
+       'mwe-add_media_wizard' => 'Add media wizard',
+       'mwe-media_search' => 'Media search',
+       'rsd_box_layout' => 'Box layout',
+       'rsd_list_layout' => 'List layout',
+       'rsd_results_desc' => 'Results $1 to $2',
+       'rsd_results_desc_total' => 'Results $1 to $2 of $3',
+       'rsd_results_next' => 'next',
+       'rsd_results_prev' => 'previous',
+       'rsd_no_results' => 'No search results for <b>$1</b>',
+       'mwe-upload_tab' => 'Upload',
+       'rsd_layout' => 'Layout:',
+       'rsd_resource_edit' => 'Edit resource: $1',
+       'mwe-resource_description_page' => 'Resource description page',
+       'mwe-link' => 'link',
+       'rsd_local_resource_title' => 'Local resource title',
+       'rsd_do_insert' => 'Do insert',
+       'mwe-cc_title' => 'Creative Commons',
+       'mwe-cc_by_title' => 'Attribution',
+       'mwe-cc_nc_title' => 'Noncommercial',
+       'mwe-cc_nd_title' => 'No Derivative Works',
+       'mwe-cc_sa_title' => 'Share Alike',
+       'mwe-cc_pd_title' => 'Public Domain',
+       'mwe-unknown_license' => 'Unknown license',
+       'mwe-no_import_by_url' => 'This user or wiki <b>cannot</b> import assets from remote URLs.<p>Do you need to login?</p><p>Is upload_by_url permission set for you?<br />Does the wiki have <a href="http://www.mediawiki.org/wiki/Manual:$wgAllowCopyUploads">$wgAllowCopyUploads</a> enabled?</p>',
+       'mwe-results_from' => 'Results from <a href="$1" target="_new" >$2</a>',
+       'mwe-missing_desc_see_source' => 'This asset is missing a description. Please see the [$1 original source] and help describe it.',
+       'rsd_config_error' => 'Add media wizard configuration error: $1',
+       'mwe-your_recent_uploads' => 'Your recent uploads to $1',
+       'mwe-upload_a_file' => 'Upload a new file to $1',
+       'mwe-resource_page_desc' => 'Resource page description:',
+       'mwe-edit_resource_desc' => 'Edit wiki text resource description:',
+       'mwe-local_resource_title' => 'Local resource title:',
+       'mwe-watch_this_page' => 'Watch this page',
+       'mwe-do_import_resource' => 'Import resource',
+       'mwe-update_preview' => 'Update resource page preview',
+       'mwe-cancel_import' => 'Cancel import',
+       'mwe-importing_asset' => 'Importing asset',
+       'mwe-preview_insert_resource' => 'Preview insert of resource: $1',
+       'mwe-checking-resource' => 'Checking for resource',
+       'mwe-resource-needs-import' => 'Resource $1 needs to be imported to $2',
+       'mwe-ftype-svg' => 'SVG vector file',
+       'mwe-ftype-jpg' => 'JPEG image file',
+       'mwe-ftype-png' => 'PNG image file',
+       'mwe-ftype-oga' => 'Ogg audio file',
+       'mwe-ftype-ogg' => 'Ogg video file',
+       'mwe-ftype-unk' => 'Unknown file format',
+       'rsd-wiki_commons-title' => 'Wikimedia Commons',
+       'rsd-wiki_commons' => 'Wikimedia Commons, an archive of freely-licensed educational media content (images, sound and video clips)',
+       'rsd-this_wiki-title' => 'This wiki',
+       'rsd-this_wiki-desc' => 'The local wiki install',
+       'rsd-archive_org-title' => 'Archive.org',
+       'rsd-archive_org-desc' => 'The Internet Archive, a digital library of cultural artifacts',
+       'rsd-flickr-title' => 'Flickr.com',
+       'rsd-flickr-desc' => 'Flickr.com, a online photo sharing site',
+       'rsd-metavid-title' => 'Metavid.org',
+       'rsd-metavid-desc' => 'Metavid.org, a community archive of US House and Senate floor proceedings',
+
+       /*
+        * js file: /libAddMedia/simpleUploadForm.js
+        */
+       'mwe-select_file' => 'Select file',
+       'mwe-more_licence_options' => 'For more licence options, view the <a href="$1">normal upload page</a>',
+       'mwe-select_ownwork' => 'I am uploading entirely my own work, and licencing it under:',
+       'mwe-licence_cc-by-sa' => 'Creative Commons Share Alike (3.0)',
+       'mwe-upload' => 'Upload file',
+       'mwe-destfilename' => 'Destination filename:',
+       'mwe-summary' => 'Summary',
+       'mwe-error_not_loggedin' => 'You do not appear to be logged in or do not have upload privileges.',
+       'mwe-watch-this-file' => 'Watch this file',
+       'mwe-ignore-any-warnings' => 'Ignore any warnings',
+
+       /*
+        * js file: /libAddMedia/mvBaseUploadInterface.js
+        */
+       'mwe-upload-transcode-in-progress' => 'Transcode and upload in progress (do not close this window)',
+       'mwe-upload-in-progress' => 'Upload in progress (do not close this window)',
+       'mwe-upload-transcoded-status' => 'Transcoded',
+       'mwe-uploaded-status' => 'Uploaded',
+       'mwe-upload-stats-fileprogress' => '$1 of $2',
+       'mwe-upload_completed' => 'Your upload is complete',
+       'mwe-upload_done' => '<a href="$1">Your upload <i>should be</i> accessible</a>.',
+       'mwe-upload-unknown-size' => 'Unknown size',
+       'mwe-cancel-confim' => 'Are you sure you want to cancel?',
+       'mwe-successfulupload' => 'Upload successful',
+       'mwe-uploaderror' => 'Upload error',
+       'mwe-uploadwarning' => 'Upload warning',
+       'mwe-unknown-error' => 'Unknown error:',
+       'mwe-return-to-form' => 'Return to form',
+       'mwe-file-exists-duplicate' => 'This file is a duplicate of the following file:',
+       'mwe-fileexists' => 'A file with this name exists already. Please check <b><tt>$1</tt></b> if you are not sure if you want to change it.',
+       'mwe-fileexists-thumb' => '<center><b>Existing file</b></center>',
+       'mwe-ignorewarning' => 'Ignore warning and save file anyway',
+       'mwe-file-thumbnail-no' => 'The filename begins with <b><tt>$1</tt></b>',
+       'mwe-go-to-resource' => 'Go to resource page',
+       'mwe-upload-misc-error' => 'Unknown upload error',
+       'mwe-wgfogg_warning_bad_extension' => 'You have selected a file with an unsuported extension (<a href="http://commons.wikimedia.org/wiki/Commons:Firefogg#Supported_File_Types">more information</a>).',
+
+       /*
+        * js file: /libAddMedia/dragDropFile.js
+        */
+       'mwe-upload-multi' => 'Upload {{PLURAL:$1|file|files}}',
+       'mwe-review-upload' => 'Review file {{PLURAL:$1|upload|uploads}}',
+
+       /*
+        * js file: /skins/kskin/kskin.js
+        */
+       'mwe-credit-title' => 'Title: $1',
+
+       /*
+        * js file: /libEmbedVideo/embedVideo.js
+        */
+       'mwe-loading_plugin' => 'loading plugin ...',
+       'mwe-select_playback' => 'Set playback preference',
+       'mwe-link_back' => 'Link back',
+       'mwe-error_swap_vid' => 'Error: mv_embed was unable to swap the video tag for the mv_embed interface',
+       'mwe-add_to_end_of_sequence' => 'Add to end of sequence',
+       'mwe-missing_video_stream' => 'The video file for this stream is missing',
+       'mwe-play_clip' => 'Play clip',
+       'mwe-pause_clip' => 'Pause clip',
+       'mwe-volume_control' => 'Volume control',
+       'mwe-player_options' => 'Player options',
+       'mwe-closed_captions' => 'Closed captions',
+       'mwe-player_fullscreen' => 'Fullscreen',
+       'mwe-next_clip_msg' => 'Play next clip',
+       'mwe-prev_clip_msg' => 'Play previous clip',
+       'mwe-current_clip_msg' => 'Continue playing this clip',
+       'mwe-seek_to' => 'Seek $1',
+       'mwe-paused' => 'paused',
+       'mwe-download_segment' => 'Download selection:',
+       'mwe-download_full' => 'Download full video file:',
+       'mwe-download_right_click' => 'To download, right click and select <i>Save link as...</i>',
+       'mwe-download_clip' => 'Download video',
+       'mwe-download_text' => 'Download text (<a style="color:white" title="cmml" href="http://wiki.xiph.org/index.php/CMML">CMML</a> xml):',
+       'mwe-download' => 'Download',
+       'mwe-share' => 'Share',
+       'mwe-credits' => 'Credits',
+       'mwe-clip_linkback' => 'Clip source page',
+       'mwe-chose_player' => 'Choose video player',
+       'mwe-share_this_video' => 'Share this video',
+       'mwe-video_credits' => 'Video credits',
+       'mwe-menu_btn' => 'Menu',
+       'mwe-close_btn' => 'Close',
+       'mwe-ogg-player-vlc-player' => 'VLC player',
+       'mwe-ogg-player-videoElement' => 'Native Ogg video',
+       'mwe-ogg-player-oggPlugin' => 'Generic Ogg plugin',
+       'mwe-ogg-player-quicktime-mozilla' => 'QuickTime plugin',
+       'mwe-ogg-player-quicktime-activex' => 'QuickTime ActiveX',
+       'mwe-ogg-player-cortado' => 'Java Cortado',
+       'mwe-ogg-player-flowplayer' => 'Flowplayer',
+       'mwe-ogg-player-kplayer' => 'Kaltura player',
+       'mwe-ogg-player-selected' => '(selected)',
+       'mwe-ogg-player-omtkplayer' => 'OMTK Flash Vorbis',
+       'mwe-generic_missing_plugin' => 'You browser does not appear to support the following playback type: <b>$1</b><br />Visit the <a href="http://commons.wikimedia.org/wiki/Commons:Media_help">Playback Methods</a> page to download a player.<br />',
+       'mwe-for_best_experience' => 'For a better video playback experience we recommend:<br /><b><a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=mwEmbed">Firefox 3.5</a>.</b>',
+       'mwe-do_not_warn_again' => 'Dismiss for now.',
+       'mwe-playerselect' => 'Players',
+       'mwe-read_before_embed' => '<a href="http://mediawiki.org/wiki/Security_Notes_on_Remote_Embedding" target="_new">Read this</a> before embedding.',
+       'mwe-embed_site_or_blog' => 'Embed on a page',
+       'mwe-related_videos' => 'Related videos',
+       'mwe-seeking' => 'seeking',
+       'mwe-copy-code' => 'Copy code',
+       'mwe-video-h264' => 'H.264 video',
+       'mwe-video-flv' => 'Flash video',
+       'mwe-video-ogg' => 'Ogg video',
+       'mwe-video-audio' => 'Ogg audio',
+);
+
+/** Message documentation (Message documentation)
+ * @author EugeneZelenko
+ * @author Fryed-peach
+ * @author McDutchie
+ * @author Mormegil
+ * @author Purodha
+ * @author Siebrand
+ * @author Tbleher
+ * @author Translationista
+ */
+$messages['qqq'] = array(
+       'mwe-sc_inoutpoints' => 'In-out-points are start and end times with reagards to a part of the video that should be shown. So if a video has a length of 60 seconds, the in-point can be at 10 seconds, the out-point at 40 seconds, so that the length of the fragment shown is 30 seconds.',
+       'mwe-sc_duration' => '{{Identical|Duration}}',
+       'mwe-set_in_out_points' => 'In-out-points are start and end times with reagards to a part of the video that should be shown. So if a video has a length of 60 seconds, the in-point can be at 10 seconds, the out-point at 40 seconds, so that the length of the fragment shown is 30 seconds.',
+       'mwe-preview_inout' => 'This message is used for the button that performs the action of previewing the user set start and end time of an audio or video asset.',
+       'mwe-edit-tools' => 'Caption in the [[mw:Extension:Add Media Wizard|Add Media Wizard]], meaning “Tools which can be used to edit the image”.',
+       'mwe-edit-video-tools' => 'This message is used as a header (h3). It heads the tools that are used to edit (the) video in the mwEmbed JavaScript library.',
+       'mwe-duration' => '{{Identical|Duration}}',
+       'mwe-close' => '{{Identical|Close}}',
+       'mwe-transition_out' => 'Transition out describes the button when clicked displays the interface for setting the transition-out of a video clip. The outgoing transition happens at the end of a video clip display.',
+       'mwe-menu_options' => '{{Identical|Options}}',
+       'mwe-zoom_in' => '{{Identical|Zoom in}}',
+       'mwe-zoom_out' => '{{Identical|Zoom out}}',
+       'mwe-loading_txt' => '{{Identical|Loading}}',
+       'mwe-error_load_lib' => 'Parameters:
+* $1 Corresponds to the JavaScript file that was not retrievable or does not define its class name.
+* $2 Is the class name that was associated with the JavaScript file that was not found or could not be retrieved.',
+       'mwe-ok' => '{{Identical|OK}}',
+       'mwe-cancel' => '{{Identical|Cancel}}',
+       'fogg-help-sticky' => 'This is the tooltip message for the help icon. Mousing over this icon displays the help message. This tooltip tells the user that when they click the icon the help message will remain displayed.',
+       'fogg-videoBitrate-help' => 'This is an explanation of what the term "video bitrate" means (i.e. the speed of video encoding in kilobits per second).',
+       'fogg-title-title' => '{{Identical|Title}}',
+       'fogg-date-title' => '{{Identical|Date}}',
+       'fogg-copyright-title' => '{{Identical|Copyright}}',
+       'fogg-license-title' => '{{Identical|License}}',
+       'fogg-contact-title' => '{{Identical|Contact}}',
+       'mwe-add_media_wizard' => 'This message is used as the title of the popup window of the "Add media wizard"',
+       'rsd_results_desc_total' => 'Parameters:
+* $1 is the lowest result number in the displayed set for the current search
+* $2 is the highest result number in the displayed set for the current search
+* $3 is the number of results for the current search',
+       'rsd_results_next' => '{{Identical|Next}}',
+       'rsd_results_prev' => '{{Identical|Previous}}',
+       'mwe-upload_tab' => '{{Identical|Upload}}',
+       'mwe-link' => '{{Identical|Link}}',
+       'mwe-cc_title' => '{{optional}}',
+       'mwe-select_file' => '{{Identical|Select file}}',
+       'mwe-upload' => '{{Identical|Upload file}}',
+       'mwe-summary' => '{{Identical|Summary}}',
+       'mwe-upload-multi' => '{{Identical|Upload file}}',
+       'mwe-credit-title' => '{{Identical|Title}}',
+       'mwe-closed_captions' => "Closed captions are also known as '''subtitles'''.",
+       'mwe-seek_to' => 'This is a status message in the mwEmbed JavaScript video viewer. Parameters:
+* $1 is the time of the video that is being sought',
+       'mwe-download' => '{{Identical|Download}}',
+       'mwe-close_btn' => '{{Identical|Close}}',
+       'mwe-playerselect' => '{{Identical|Player}}',
+);
+
+/** Afrikaans (Afrikaans)
+ * @author Naudefj
+ */
+$messages['af'] = array(
+       'mwe-preview_insert' => 'Voorskou',
+       'mwe-cancel_image_insert' => 'Kanselleer byvoeging',
+       'mwe-sc_duration' => 'Duur',
+       'mwe-edit_properties' => 'Wysig eienskappe',
+       'mwe-other_properties' => 'Ander eienskappe',
+       'mwe-start_time' => 'Begintyd',
+       'mwe-end_time' => 'Eindtyd',
+       'mwe-duration' => 'Duur:',
+       'mwe-saving' => 'besig om te stoor...',
+       'mwe-close' => 'sluit',
+       'mwe-improve_transcript' => 'Verbeter',
+       'mwe-menu_options' => 'Opsies',
+       'mwe-other_options' => 'Ander opsies',
+       'mwe-loading_txt' => 'laai ...',
+       'mwe-error_load_lib' => 'Fout: JavaScript $1 kon nie gevind word of definieer nie $2 nie',
+       'mwe-ok' => 'OK',
+       'mwe-cancel' => 'Kanselleer',
+       'fogg-select_file' => 'Kies lêer',
+       'fogg-select_new_file' => 'Kies nuwe lêer',
+       'fogg-select_url' => 'Kies URL',
+       'fogg-save_local_file' => 'Stoor Ogg',
+       'fogg-passthrough_mode' => "U gekose lêer is reeds 'n Ogg-lêer of nie 'n videolêer nie",
+       'fogg-transcoding' => 'Enkodeer video na Ogg',
+       'fogg-encoding-done' => 'Enkodering is voltooi',
+       'fogg-hidepreview' => 'Versteek voorskou',
+       'mwe-stream_title' => '$1 $2 tot $3',
+       'fogg-videoQuality-title' => 'Videokwaliteit',
+       'fogg-starttime-title' => 'Beginsekonde',
+       'fogg-endtime-title' => 'Stopsekonde',
+       'fogg-audioQuality-title' => 'Oudiokwaliteit',
+       'fogg-noaudio-title' => 'Geen klank',
+       'fogg-title-title' => 'Naam',
+       'fogg-date-title' => 'Datum',
+       'fogg-location-title' => 'Ligging',
+       'fogg-organization-title' => 'Organisasie',
+       'fogg-copyright-title' => 'Kopiereg',
+       'fogg-license-title' => 'Lisensie',
+       'fogg-contact-title' => 'Kontak',
+       'rsd_results_desc' => 'Resultate $1 tot $2',
+       'rsd_results_next' => 'Volgende',
+       'rsd_results_prev' => 'vorige',
+       'mwe-upload_tab' => 'Oplaai',
+       'rsd_layout' => 'Uitleg:',
+       'rsd_resource_edit' => 'Wysig hulpbron: $1',
+       'mwe-link' => 'skakel',
+       'mwe-cc_by_title' => 'Naamsvermelding',
+       'mwe-cc_nd_title' => 'Geen afgeleide werke',
+       'mwe-cc_pd_title' => 'Publieke Domein',
+       'mwe-unknown_license' => 'Onbekend lisensie',
+       'mwe-results_from' => 'Resultate van <a href="$1" target="_new">$2</a>',
+       'mwe-missing_desc_see_source' => "Hierdie bate het nie 'n beskrywing nie. Raadpleeg die [$1 oorspronklike bron] en help om dit te beskryf.",
+       'mwe-your_recent_uploads' => 'U onlangse oplaaie na $1',
+       'mwe-upload_a_file' => "Laai 'n nuwe lêer na $1",
+       'mwe-watch_this_page' => 'Volg hierdie bladsy',
+       'mwe-select_file' => 'Kies lêer',
+       'mwe-more_licence_options' => 'Gebruik die <a href="$1">normale oplaaiblad</a> vir meer lisensie keuses',
+       'mwe-upload' => 'Laai lêer',
+       'mwe-summary' => 'Samevatting',
+       'mwe-error_not_loggedin' => 'U is nie aangeteken nie of het nie regte om op te mag laai nie.',
+       'mwe-upload-transcode-in-progress' => 'Besig met transkodering en oplaai (moenie hierdie venster toemaak nie)',
+       'mwe-upload-in-progress' => 'Besig om op te laai (moenie hierdie venster toemaak nie)',
+       'mwe-upload-transcoded-status' => 'Getranskodeer',
+       'mwe-uploaded-status' => 'Opgelaai',
+       'mwe-upload-stats-fileprogress' => '$1 van $2',
+       'mwe-upload_completed' => 'Jou oplaai is voltooi',
+       'mwe-upload_done' => '<a href="$1">Jou oplaai <i>behoort</i> nou beskikbaar te wees</a>.',
+       'mwe-upload-unknown-size' => 'Onbekend grootte',
+       'mwe-cancel-confim' => 'Is u seker u wil kanselleer?',
+       'mwe-successfulupload' => 'Oplaai suksesvol',
+       'mwe-uploadwarning' => 'Oplaai waarskuwing',
+       'mwe-unknown-error' => 'Onbekende fout:',
+       'mwe-return-to-form' => 'Terug na die vorm',
+       'mwe-file-exists-duplicate' => "Hierdie lêer is 'n duplikaat van die volgende lêer:",
+       'mwe-fileexists-thumb' => '<center><b>Bestaande lêer</b></center>',
+       'mwe-upload-multi' => "Laai {{PLURAL:$1|'n lêer|lêers}}",
+       'mwe-credit-title' => 'Naam: $1',
+       'mwe-loading_plugin' => 'laai uitbreiding ...',
+       'mwe-add_to_end_of_sequence' => 'Voeg by aan die einde van die reeks',
+       'mwe-volume_control' => 'Volumebeheer',
+       'mwe-closed_captions' => 'Onderskrifte',
+       'mwe-download' => 'Aflaai',
+       'mwe-share' => 'Deel',
+       'mwe-credits' => 'Krediete',
+       'mwe-menu_btn' => 'Keuseskerm',
+       'mwe-close_btn' => 'Sluit',
+       'mwe-ogg-player-quicktime-mozilla' => 'QuickTime-uitbreiding',
+       'mwe-ogg-player-quicktime-activex' => 'QuickTime ActiveX',
+       'mwe-ogg-player-cortado' => 'Java Cortado',
+       'mwe-ogg-player-flowplayer' => 'Flowplayer',
+       'mwe-ogg-player-selected' => '(gekies)',
+       'mwe-ogg-player-omtkplayer' => 'OMTK Flash Vorbis',
+       'mwe-playerselect' => 'Mediaspelers',
+       'mwe-embed_site_or_blog' => 'Voeg by jou webblad of webjoernaal',
+);
+
+/** Arabic (العربية)
+ * @author Meno25
+ * @author OsamaK
+ */
+$messages['ar'] = array(
+       'mwe-crop' => 'اقتص الصورة',
+       'mwe-cancel_image_insert' => 'ألغِ الإدراج',
+       'mwe-sc_audio' => 'تحكم الصوت',
+       'mwe-sc_duration' => 'المدة',
+       'mwe-template_properties' => 'خصائص القالب',
+       'mwe-custom_title' => 'عنوان مُخصّص',
+       'mwe-edit_properties' => 'عدل الخصائص',
+       'mwe-other_properties' => 'خصائص أخرى',
+       'mwe-start_time' => 'وقت البداية',
+       'mwe-end_time' => 'وقت النهاية',
+       'mwe-auto_scroll' => 'لف تلقائي',
+       'mwe-close' => 'أغلق',
+       'mwe-improve_transcript' => 'حسّن',
+       'mwe-no_text_tracks_found' => 'لم توجد مقطوعات نصية',
+       'mwe-remove_transition' => 'أزل الترجمة',
+       'mwe-edit_transin' => 'عدّل الترجمة في المقطع',
+       'mwe-edit_transout' => 'عدّل الترجمة خارج المقطع',
+       'mwe-menu_clipedit' => 'حرّر الوسيط',
+       'mwe-menu_transition' => 'ترجمات ومؤثرات',
+       'mwe-menu_cliplib' => 'أضف وسيطًا',
+       'mwe-menu_options' => 'خيارات',
+       'mwe-loading_timeline' => 'يحمل الشريط الزمني...',
+       'mwe-loading_user_rights' => 'يحمل صلاحيات المستخدم...',
+       'mwe-edit_clip' => 'حرّر المقطع',
+       'mwe-saving_wait' => 'الحفظ قيد التنفيذ (من فضلك انتظر)',
+       'mwe-save_done' => 'اكتمل الحفظ',
+       'mwe-edit_cancel_confirm' => 'أمتأكد من أنك تريد إلغاء تعديلك؟ سوف تضيع التعديلات.',
+       'mwe-zoom_in' => 'قرّب',
+       'mwe-zoom_out' => 'بعّد',
+       'mwe-expand_track' => 'وسّع المقطوعة',
+       'mwe-collapse_track' => 'اطوِ المقطوعة',
+       'mwe-rmclip' => 'أزل المقطع',
+       'mwe-editor_options' => 'خيارات المحرر',
+       'mwe-editor_mode' => 'وضع المحرّر',
+       'mwe-simple_editor_desc' => 'مُحرّر بسيط (على نمط iMovie)',
+       'mwe-other_options' => 'خيارات أخرى',
+       'mwe-loading_txt' => 'يحمل...',
+       'mwe-cancel' => 'ألغِ',
+       'mwe-re-try' => 'أعد طلب الواجهة البرمجية',
+       'mwe-re-trying' => 'يعيد طلب الواجهة البرمجية...',
+       'fogg-select_file' => 'اختر ملفًا',
+       'fogg-select_new_file' => 'اختر ملفًا جديدًا',
+       'fogg-select_url' => 'اختر مسارًا',
+       'fogg-save_local_file' => 'احفظ Ogg',
+       'fogg-check_for_firefogg' => 'يلتمس Firefogg...',
+       'fogg-installed' => 'Firefogg مُثبّت',
+       'fogg-transcoding' => 'ترميز الفيديو إلى Ogg',
+       'fogg-encoding-done' => 'انتهى الترميز',
+       'fogg-preview' => 'عاين الفيديو',
+       'fogg-hidepreview' => 'أخفِ المعاينة',
+       'fogg-cg-meta' => 'بيانات المقطع العلوية',
+       'fogg-cg-range' => 'نطاق الترميز',
+       'fogg-cg-advVideo' => 'متحكمات ترميز فيديو متقدمة',
+       'fogg-cg-advAudio' => 'متحكمات ترميز صوت متقدمة',
+       'fogg-preset-custom' => 'إعدادات مُخصّصة',
+       'fogg-videoQuality-title' => 'جودة الفيديو',
+       'fogg-starttime-title' => 'ثانية البدء',
+       'fogg-starttime-help' => 'رمّز من هذا الوقت بالثانية فقط',
+       'fogg-endtime-title' => 'ثانية الانتهاء',
+       'fogg-endtime-help' => 'رمّز إلى هذا الوقت بالثانية فقط',
+       'fogg-audioQuality-title' => 'جودة الصوت',
+       'fogg-width-title' => 'عرض الفيديو',
+       'fogg-height-title' => 'ارتفاع الفيديو',
+       'fogg-framerate-title' => 'معدل الإطارات',
+       'fogg-title-title' => 'العنوان',
+       'fogg-title-help' => 'عنوان مقطعك',
+       'fogg-artist-title' => 'اسم المنشئ',
+       'fogg-artist-help' => 'منشئ هذا المقطع',
+       'fogg-date-title' => 'التاريخ',
+       'fogg-location-title' => 'الموقع',
+       'fogg-copyright-title' => 'حقوق النشر',
+       'fogg-license-title' => 'الرخصة',
+       'fogg-contact-title' => 'الاتصال',
+       'fogg-contact-help' => 'وصلة الاتصال',
+       'mwe-add_media_wizard' => 'أضف معالج وسائط',
+       'mwe-media_search' => 'بحث الميديا',
+       'rsd_list_layout' => 'تخطيط القائمة',
+       'rsd_results_desc' => 'النتائج  $1 إلى $2',
+       'rsd_results_next' => 'تالي',
+       'rsd_results_prev' => 'سابق',
+       'mwe-upload_tab' => 'رفع',
+       'rsd_layout' => 'التخطيط:',
+       'mwe-link' => 'وصلة',
+       'mwe-cc_by_title' => 'عزو',
+       'mwe-cc_sa_title' => 'المشاركة على قدم المساواة',
+       'mwe-cc_pd_title' => 'ملكية عامة',
+       'mwe-unknown_license' => 'رخصة غير معروفة',
+       'mwe-results_from' => 'النتائج من <a href="$1" target="_new" >$2</a>',
+       'mwe-upload_a_file' => 'رفع ملف جديد',
+       'mwe-watch_this_page' => 'راقب هذه الصفحة',
+       'mwe-update_preview' => 'حدّث المعاينة',
+       'mwe-cancel_import' => 'إلغاء الاستيراد',
+       'mwe-ftype-ogg' => 'ملف فيديو Ogg',
+       'mwe-select_file' => 'اختر الملف',
+       'mwe-upload' => 'رفع الملف',
+       'mwe-destfilename' => 'اسم ملف المقصد:',
+       'mwe-summary' => 'ملخص',
+       'mwe-upload_completed' => 'اكتمل رفعك',
+       'mwe-cancel-confim' => 'أمتأكد من أنك تريد الإلغاء؟',
+       'mwe-successfulupload' => 'نجح الرفع',
+       'mwe-uploaderror' => 'خطأ رفع',
+       'mwe-uploadwarning' => 'تحذير رفع',
+       'mwe-unknown-error' => 'خطأ غير معروف:',
+       'mwe-return-to-form' => 'ارجع إلى النموذج',
+       'mwe-fileexists-thumb' => '<center><b>ملف موجود</b></center>',
+       'mwe-loading_plugin' => 'تحميل ملحق...',
+       'mwe-add_to_end_of_sequence' => 'أضف إلى نهاية السلسلة',
+       'mwe-play_clip' => 'شغّل المقطع',
+       'mwe-pause_clip' => 'ألبث المقطع',
+       'mwe-player_options' => 'خيارات المُشغّل',
+       'mwe-player_fullscreen' => 'املأ الشاشة',
+       'mwe-next_clip_msg' => 'شغّل المقطع التالي',
+       'mwe-prev_clip_msg' => 'شغل المقطع السابق',
+       'mwe-seek_to' => 'ابحث في $1',
+       'mwe-download_segment' => 'نزّل التحديد:',
+       'mwe-download_clip' => 'نزّل الفيديو',
+       'mwe-download' => 'نزّل',
+       'mwe-share' => 'مشاركة',
+       'mwe-clip_linkback' => 'صفحة مصدر المقطع',
+       'mwe-chose_player' => 'اختر مشغل الفيديو',
+       'mwe-share_this_video' => 'شارك هذا الفيديو',
+       'mwe-menu_btn' => 'قائمة',
+       'mwe-close_btn' => 'إغلاق',
+       'mwe-ogg-player-vlc-mozilla' => 'ملحق VLC',
+);
+
+/** Belarusian (Taraškievica orthography) (Беларуская (тарашкевіца))
+ * @author EugeneZelenko
+ * @author Jim-by
+ */
+$messages['be-tarask'] = array(
+       'mwe-crop' => 'Выразаць частку выявы',
+       'mwe-apply_crop' => 'Прыняць выразку часткі выявы',
+       'mwe-reset_crop' => 'Адмяніць выразку часткі',
+       'mwe-insert_image_page' => 'Уставіць на старонку',
+       'mwe-insert_into_sequence' => 'Уставіць у пасьлядоўнасьць',
+       'mwe-preview_insert' => 'Папярэдні прагляд устаўкі',
+       'mwe-cancel_image_insert' => 'Адмяніць устаўку',
+       'mwe-sc_fileopts' => 'Падрабязнасьці рэдагаваньня часткі файла',
+       'mwe-sc_inoutpoints' => 'Устаноўка пунктаў увода-вываду',
+       'mwe-sc_overlays' => 'Накладаньні',
+       'mwe-sc_audio' => 'Аўдыё-кантроль',
+       'mwe-sc_duration' => 'Працягласьць',
+       'mwe-template_properties' => 'Уласьцівасьці шаблёну',
+       'mwe-custom_title' => 'Нестандартная назва',
+       'mwe-edit_properties' => 'Рэдагаваць уласьцівасьці',
+       'mwe-other_properties' => 'Іншыя ўласьцівасьці',
+       'mwe-resource_page' => 'Старонка рэсурсу:',
+       'mwe-set_in_out_points' => 'Устанавіць пункты ўвода-вываду',
+       'mwe-start_time' => 'Час пачатку',
+       'mwe-end_time' => 'Час сканчэньня',
+       'mwe-preview_inout' => 'Праглядзець пункты ўводу-вываду',
+       'mwe-edit-tools' => 'Інструмэнты рэдагаваньня',
+       'mwe-inline-description' => 'Загаловак',
+       'mwe-edit-video-tools' => 'Прылады рэдагаваньня відэа:',
+       'mwe-duration' => 'Працягласьць:',
+       'mwe-upload-subs-file' => 'Загрузіць субтытры',
+       'mwe-add-subs-file-title' => 'Выберыце субтытры для загрузкі',
+       'mwe-error-only-srt' => 'Вы можаце загружаць толькі srt-файлы.',
+       'mwe-watch-video' => 'Глядзець відэа',
+       'mwe-select-other-language' => 'Выбраць іншую мову',
+       'mwe-saving' => 'захаваньне…',
+       'mwe-select_transcript_set' => 'Выбраць субтытры',
+       'mwe-auto_scroll' => 'аўтаматычная пракрутка',
+       'mwe-close' => 'закрыць',
+       'mwe-improve_transcript' => 'Палепшыць',
+       'mwe-no_text_tracks_found' => 'Тэкставая інфармацыя ня знойдзеная',
+       'mwe-add-edit-subs' => 'Дадаць/рэдагаваць субтытры',
+       'mwe-transition_in' => 'Пераход у',
+       'mwe-transition_out' => 'Пераход з',
+       'mwe-effects' => 'Набор эфэктаў',
+       'mwe-remove_transition' => 'Выдаліць пераход',
+       'mwe-edit_transin' => 'Рэдагаваць пераход у частку файла',
+       'mwe-edit_transout' => 'Рэдагаваць пераход з часткі файла',
+       'mwe-add-transition' => 'Дадаць пераход',
+       'mwe-menu_clipedit' => 'Рэдагаваць мэдыя',
+       'mwe-menu_transition' => 'Пераходы і эфэкты',
+       'mwe-menu_cliplib' => 'Дадаць мэдыя',
+       'mwe-menu_resource_overview' => 'Агляд рэсурсаў',
+       'mwe-menu_options' => 'Устаноўкі',
+       'mwe-loading_timeline' => 'Загрузка шкалы часу ...',
+       'mwe-loading_user_rights' => 'Загрузка правоў удзельніка ...',
+       'mwe-no_edit_permissions' => 'Вы ня маеце правоў для захаваньня зьменаў у гэтай пасьлядоўнасьці',
+       'mwe-edit_clip' => 'Рэдагаваць частку файла',
+       'mwe-edit_save' => 'Захаваць зьмены пасьлядоўнасьці',
+       'mwe-saving_wait' => 'Захаваньне зьдзяйсьняецца (калі ласка, пачакайце)',
+       'mwe-save_done' => 'Захаваньне скончанае',
+       'mwe-edit_cancel' => 'Адмяніць рэдагаваньне пасьлядоўнасьці',
+       'mwe-edit_cancel_confirm' => 'Вы ўпэўнены, што жадаеце адмяніць Вашае рэдагаваньне? Зьмены будуць страчаныя.',
+       'mwe-zoom_in' => 'Павялічыць',
+       'mwe-zoom_out' => 'Паменшыць',
+       'mwe-cut_clip' => 'Кадраваньне кліпаў',
+       'mwe-expand_track' => 'Павялічыць сьцежку',
+       'mwe-collapse_track' => 'Паменшыць сьцежку',
+       'mwe-play_from_position' => 'Прайграваць з цяперашняй пазыцыі',
+       'mwe-pixle2sec' => 'піксэлі ў сэкундах',
+       'mwe-rmclip' => 'Выдаліць частку файла',
+       'mwe-clip_in' => 'дадаць кліп',
+       'mwe-clip_out' => 'выдаліць кліп',
+       'mwe-no_selected_resource' => '<h3>Рэсурс не выбраны</h3> Выберыце частку файла для уключэньня рэдагаваньня.',
+       'mwe-error_edit_multiple' => '<h3>Выбраныя некалькі рэсурсаў</h3> Выберыце адну частку файла для яе рэдагаваньня.',
+       'mwe-editor_options' => 'Устаноўкі рэдактара',
+       'mwe-editor_mode' => 'Рэжым рэдактара',
+       'mwe-simple_editor_desc' => 'просты рэдактар (стыль iMovie)',
+       'mwe-advanced_editor_desc' => 'палепшаны рэдактар (стыль Final Cut)',
+       'mwe-other_options' => 'Іншыя ўстаноўкі',
+       'mwe-contextmenu_opt' => 'Дазволіць кантэкстныя мэню',
+       'mwe-sequencer_credit_line' => 'Распрацавана <a href="http://kaltura.com">Kaltura, Inc.</a> у садружнасьці з <a href="http://wikimediafoundation.org/wiki/Home">фундацыяй «Вікімэдыя»</a> (<a href="#">падрабязнасьці </a>).',
+       'mwe-loading_txt' => 'загрузка …',
+       'mwe-error_load_lib' => 'Памылка: JavaScript $1 не даступны альбо не вызначае $2',
+       'mwe-loading-add-media-wiz' => 'Загрузка майстра даданьня мэдыя',
+       'mwe-apiproxy-setup' => 'Устаноўка API-проксі',
+       'mwe-load-drag-item' => 'Загрузка перанесенага элемэнту',
+       'mwe-ok' => 'Добра',
+       'mwe-cancel' => 'Адмяніць',
+       'mwe-setting-up-proxy' => 'Наладка проксі...',
+       'mwe-re-try' => 'Паўтарыць API-запыт',
+       'mwe-re-trying' => 'Паўторны API-запыт…',
+       'mwe-proxy-not-ready' => 'Проксі не сканфігураваны',
+       'mwe-please-login' => 'Вы не <a target="_new" href="$1">ўвайшлі ў сыстэму</a> $2 альбо mwEmbed ня быў уключаны. Вырашыце гэтую праблему і потым паўтарыце запыт.',
+       'mwe-remember-loging' => 'Агульны напамін бясьпекі: Уваходзьце ў сыстэму толькі ў тым выпадку, калі ў радку адраса адлюстроўваецца адрас сайту, які чакаецца.',
+       'fogg-select_file' => 'Выберыце файл',
+       'fogg-select_new_file' => 'Выберыце новы файл',
+       'fogg-select_url' => 'Выберыце URL-адрас',
+       'fogg-save_local_file' => 'Захаваць Ogg',
+       'fogg-check_for_firefogg' => 'Праверка наяўнасьці Firefogg …',
+       'fogg-installed' => 'Firefogg усталяваны',
+       'fogg-for_improved_uploads' => 'Для палепшаных загрузак:',
+       'fogg-please_install' => '<a href="$1">Усталяваць Firefogg</a>. Болей <a href="http://commons.wikimedia.org/wiki/Commons:Firefogg">пра Firefogg</a>',
+       'fogg-use_latest_firefox' => 'Калі ласка, спачатку ўсталюйце <a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=firefogg">Firefox 3.5</a> (ці больш позьнюю вэрсію). <i>Потым зноў наведайце гэтую старонку і ўсталюйце пашырэньне <b>Firefogg</b>.</i>',
+       'fogg-passthrough_mode' => 'Выбраны Вамі файл ужо ў фармаце Ogg альбо не зьяўляецца відэа-файлам',
+       'fogg-transcoding' => 'Перакадыроўка відэа ў фармат Ogg',
+       'fogg-encoding-done' => 'Перакадыроўка скончаная',
+       'fogg-badtoken' => 'Няслушны маркер',
+       'fogg-preview' => 'Папярэдні прагляд відэа',
+       'fogg-hidepreview' => 'Схаваць папярэдні прагляд',
+       'mwe-imported_from' => '$1 імпартавана з [$2 $3]. Глядзіце пачатковую [$4 старонку рэсурсу] для дадатковай інфармацыі.',
+       'mwe-stream_title' => '$1 $2 да $3',
+       'fogg-help-sticky' => 'Дапамога (націсьніце, каб паказвалася заўсёды)',
+       'fogg-cg-preset' => 'Набор установак: <strong>$1</strong>',
+       'fogg-cg-quality' => 'Базавае кіраваньне якасьцю і разрозьненьнем',
+       'fogg-cg-meta' => 'Мэта-зьвесткі часткі файла',
+       'fogg-cg-range' => 'Дыяпазон кадыроўкі',
+       'fogg-cg-advVideo' => 'Палепшанае кіраваньне відэа-кадыроўкай',
+       'fogg-cg-advAudio' => 'Палепшанае кіраваньне аўдыя-кадыроўкі',
+       'fogg-preset-custom' => 'Нестандартныя ўстаноўкі',
+       'fogg-webvideo-desc' => 'Ўэб-відэа Theora, Vorbis 400 кбіт/с з максымальнай шырынёй 400 пкс',
+       'fogg-savebandwidth-desc' => 'Нізкаякаснае ўэб-відэа Theora, Vorbis 164 кбіт/с з максымальнай шырынёй 200 пкс',
+       'fogg-highquality-desc' => 'Высакаякаснае ўэб-відэа Theora, Vorbis з максымальнай шырынёй 1080 пкс',
+       'fogg-videoQuality-title' => 'Якасьць відэа',
+       'fogg-videoQuality-help' => 'Выкарыстоўваюцца для ўстаноўкі <i>візуальнай якасьці</i> кадаванага відэа (не выкарыстоўваецца, калі Вы ўстанавілі хуткасьць перадачы ніжэй у пашыраных ўстаноўках).',
+       'fogg-starttime-title' => 'Пачаць з сэкунды',
+       'fogg-starttime-help' => 'Кадаваць толькі з часу, пазначанага ў сэкундах',
+       'fogg-endtime-title' => 'Скончыць на сэкундзе',
+       'fogg-endtime-help' => 'Кадаваць толькі да часу, пазначанага ў сэкундах',
+       'fogg-audioQuality-title' => 'Якасьць аўдыё',
+       'fogg-audioQuality-help' => 'Выкарыстоўваецца для ўстаноўкі <i>якасьці гуку</i> кадаванага аўдыё (не выкарыстоўваецца, калі Вы ўстанавілі бітрэйт ў пашыраных устаноўках).',
+       'fogg-videoCodec-title' => 'Альгарытмы кадаваньня відэа',
+       'fogg-videoCodec-help' => 'Выкарыстоўваецца для выбару альгарытму кадаваньня відэа. У цяперашні час падтрымліваецца толькі Theora. Падрабязьней пра <a target="_new" href="http://en.wikipedia.org/wiki/Theora">альгарытм кадаваньня Theora</a>.',
+       'fogg-audioCodec-title' => 'Альгарытмы кадаваньня аўдыё',
+       'fogg-audioCodec-help' => 'Выкарыстоўваецца для выбару альгарытму кадаваньня аўдыё кліпа. У цяперашні час падтрымліваецца толькі Vorbis. Падрабязьней пра <a target="_new" href="http://en.wikipedia.org/wiki/Vorbis">альгарытм кадаваньня Vorbis</a>',
+       'fogg-width-title' => 'Шырыня відэа',
+       'fogg-width-help' => 'Зьмяніць памер згодна пададзенай шырыні.',
+       'fogg-height-title' => 'Вышыня відэа',
+       'fogg-height-help' => 'Зьмяніць памер згодна пададзенай вышыні.',
+       'fogg-videoBitrate-title' => 'Бітрэйт відэа',
+       'fogg-videoBitrate-help' => 'Бітрэйт відэа ўстанаўлівае бітрэйт кадаваньня відэа ў (кбіт/с)',
+       'fogg-twopass-title' => 'Двухпраходнае кадаваньне',
+       'fogg-twopass-help' => 'Двухпраходнае кадаваньне дазваляе падвысіць якасьць кадаваньня праз правядзеньне двух праходаў па відэа-файлу',
+       'fogg-framerate-title' => 'Частата кадраў',
+       'fogg-framerate-help' => 'Частата кадраў відэа. Падрабязьней пра <a target="_new" href="http://en.wikipedia.org/wiki/Frame_rate">частату кадраў</a>.',
+       'fogg-aspect-title' => 'Фармат кадра',
+       'fogg-aspect-help' => 'Суадносіны шырыні і вышыні кадра можа састаўляць 4:3 ці 16:9. Падрабязьней пра <a target="_new" href="http://en.wikipedia.org/wiki/Aspect_ratio_%28image%29">фармат кадраў</a>.',
+       'fogg-keyframeInterval-title' => 'Інтэрвал паміж ключавымі кадрамі',
+       'fogg-keyframeInterval-help' => 'Інтэрвал паміж ключавымі кадрамі. Заўвага: Большасьць альгарытмаў кадаваньня утрымлівае ключавыя кадры ў выпадку, калі розьніца паміж кадрамі болей памеру ключавых кадраў кадаваньня. Падрабязьней пра <a href="http://en.wikipedia.org/wiki/I-frame">ключавыя кадры</a>.',
+       'fogg-denoise-title' => 'Фільтар выдаленьня шуму',
+       'fogg-denoise-help' => 'Выходны фільтар выдаленьня шуму з відэа. Падрабязьней пра <a href="http://en.wikipedia.org/wiki/Video_denoising">выдаленьне шуму</a>.',
+       'fogg-novideo-title' => 'Бяз відэа',
+       'fogg-novideo-help' => 'адключыць відэа на выхадзе',
+       'fogg-audioBitrate-title' => 'Бітрэйт аўдыё',
+       'fogg-samplerate-title' => 'Частата дыскрэтызацыі аўдыё',
+       'fogg-samplerate-help' => 'устанавіць выходную частату дыскрэтызацыі (у Гц).',
+       'fogg-noaudio-title' => 'Бяз аўдыё',
+       'fogg-noaudio-help' => 'адключыць гук на выхадзе',
+       'fogg-title-title' => 'Назва',
+       'fogg-title-help' => 'Назва для Вашага кліпу',
+       'fogg-artist-title' => 'Імя стваральніка',
+       'fogg-artist-help' => 'Стваральнік гэтага кліпу',
+       'fogg-date-title' => 'Дата',
+       'fogg-date-help' => 'Дата стварэньня ці выпуску матэрыялу',
+       'fogg-location-title' => 'Месцазнаходжаньне',
+       'fogg-location-help' => 'Месцазнаходжаньне матэрыялу',
+       'fogg-organization-title' => 'Арганізацыя',
+       'fogg-organization-help' => 'Назва арганізацыі (студыі)',
+       'fogg-copyright-title' => 'Аўтарскія правы',
+       'fogg-copyright-help' => 'Аўтарскія правы на кліп',
+       'fogg-license-title' => 'Ліцэнзія',
+       'fogg-license-help' => 'Ліцэнзія на кліп (пажадана URL-адрас Creative Commons).',
+       'fogg-contact-title' => 'Кантакты',
+       'fogg-contact-help' => 'Спасылка на кантакты',
+       'mwe-add_media_wizard' => 'Майстар даданьня мэдыа',
+       'mwe-media_search' => 'Пошук мэдыя',
+       'rsd_box_layout' => 'У выглядзе поля',
+       'rsd_list_layout' => 'У выглядзе сьпісу',
+       'rsd_results_desc' => 'Вынікі $1 да $2',
+       'rsd_results_desc_total' => 'Вынікі ад $1 да $2 з $3',
+       'rsd_results_next' => 'наступныя',
+       'rsd_results_prev' => 'папярэднія',
+       'rsd_no_results' => 'Няма вынікаў пошуку для <b>$1</b>',
+       'mwe-upload_tab' => 'Загрузка',
+       'rsd_layout' => 'Выгляд:',
+       'rsd_resource_edit' => 'Рэдагаваць рэсурс: $1',
+       'mwe-resource_description_page' => 'Старонка апісаньня рэсурсу',
+       'mwe-link' => 'спасылка',
+       'rsd_local_resource_title' => 'Назва лякальнага рэсурсу',
+       'rsd_do_insert' => 'Выканаць устаўку',
+       'mwe-cc_by_title' => 'Згадваньне аўтара',
+       'mwe-cc_nc_title' => 'Некамэрцыйнае',
+       'mwe-cc_nd_title' => 'Вытворныя працы не дазваляюцца',
+       'mwe-cc_sa_title' => 'З захаваньнем умоваў',
+       'mwe-cc_pd_title' => 'Грамадзкая ўласнасьць',
+       'mwe-unknown_license' => 'Невядомая ліцэнзія',
+       'mwe-no_import_by_url' => 'Гэты ўдзельнік альбо {{SITENAME}} <b>ня можа</b> імпартаваць файлы з вонкавых URL-адрасоў.<p>Вам неабходна ўвайсьці ў сыстэму?</p><p>Вы маеце адпаведныя правы?</p><p>У {{GRAMMAR:месны|{{SITENAME}}}} дазволенае <a href="http://www.mediawiki.org/wiki/Manual:$wgAllowCopyUploads">імпартаваньне файлаў з вонкавых URL-адрасоў</a>?</p>',
+       'mwe-results_from' => 'Вынікі з <a href="$1" target="_new" >$2</a>',
+       'mwe-missing_desc_see_source' => 'Гэты файл ня мае апісаньня. Калі ласка, глядзіце [$1 арыгінальную крыніцу] і дапамажыце дадаць яе апісаньне.',
+       'rsd_config_error' => 'Памылка канфігурацыі майстра даданьня мэдыя: $1',
+       'mwe-your_recent_uploads' => 'Вашыя апошнія загрузкі на $1',
+       'mwe-upload_a_file' => 'Загрузіць новы файл на $1',
+       'mwe-resource_page_desc' => 'Апісаньне старонкі рэсурсу:',
+       'mwe-edit_resource_desc' => 'Рэдагаваць вікі-тэксту апісаньня рэсурсу:',
+       'mwe-local_resource_title' => 'Назва лякальнага рэсурсу:',
+       'mwe-watch_this_page' => 'Назіраць за гэтай старонкай',
+       'mwe-do_import_resource' => 'Імпартаваць рэсурс',
+       'mwe-update_preview' => 'Абнавіць папярэдні прагляд',
+       'mwe-cancel_import' => 'Адмяніць імпартаваньне',
+       'mwe-importing_asset' => 'Імпартаваньне ўласьцівасьці',
+       'mwe-preview_insert_resource' => 'Папярэдні прагляд устаўкі рэсурсу: $1',
+       'mwe-checking-resource' => 'Праверка рэсурсу',
+       'mwe-resource-needs-import' => 'Неабходны імпарт рэсурсу $1 на $2',
+       'mwe-ftype-svg' => 'файл вэктарнай выявы ў фармаце SVG',
+       'mwe-ftype-jpg' => 'файл выявы ў фармаце JPEG',
+       'mwe-ftype-png' => 'файл выявы ў фармаце PNG',
+       'mwe-ftype-oga' => 'аўдыё-файл ў фармаце Ogg',
+       'mwe-ftype-ogg' => 'Відэа-файл ў фармаце Ogg',
+       'mwe-ftype-unk' => 'Невядомы фармат файла',
+       'rsd-wiki_commons-title' => 'ВікіСховішча',
+       'rsd-wiki_commons' => 'ВікіСховішча — архіў мэдыя-матэрыялаў, якія распаўсюджваюцца згодна ўмоваў вольных ліцэнзіяў (выявы, аўдыё- і відэа-кліпы)',
+       'rsd-this_wiki-title' => 'Гэтая вікі',
+       'rsd-this_wiki-desc' => 'Лякальная вікі',
+       'rsd-archive_org-desc' => 'Internet Archive — лічбавая бібліятэка культурных артэфактаў',
+       'rsd-flickr-desc' => 'Flickr.com — анляйн рэсурс абмену фотаздымкамі',
+       'rsd-metavid-desc' => 'Metavid.org — архіў матэрыялаў слуханьняў Палаты прадстаўнікоў і Сэнату ЗША',
+       'mwe-select_file' => 'Выбраць файл',
+       'mwe-more_licence_options' => 'Для дадатковых ліцэнзіяў, глядзіце <a href="$1">звычайную старонкі загрузкі</a>',
+       'mwe-select_ownwork' => 'Я загружаю выключна ўласную працу згодна ўмоваў ліцэнзіі:',
+       'mwe-licence_cc-by-sa' => 'Creative Commons Share Alike (3.0)',
+       'mwe-upload' => 'Загрузіць файл',
+       'mwe-destfilename' => 'Мэтавая назва файла:',
+       'mwe-summary' => 'Апісаньне',
+       'mwe-error_not_loggedin' => 'Выглядае, што Вы не ўвайшлі ў сыстэму альбо ня маеце дазволу на загрузку.',
+       'mwe-watch-this-file' => 'Праглядзець гэты файл',
+       'mwe-ignore-any-warnings' => 'Ігнараваць любыя папярэджаньні',
+       'mwe-upload-transcode-in-progress' => 'Працягваецца перакадыроўка і загрузка (не зачыняйце гэта акно)',
+       'mwe-upload-in-progress' => 'Працягваецца загрузка (не зачыняйце гэта акно)',
+       'mwe-upload-transcoded-status' => 'Перакадыраваны',
+       'mwe-uploaded-status' => 'Загружаны',
+       'mwe-upload-stats-fileprogress' => '$1 з $2',
+       'mwe-upload_completed' => 'Вашая загрузка скончаная',
+       'mwe-upload_done' => '<a href="$1">Ваша загрузка <i>павінна быць</i> даступнай</a>.',
+       'mwe-upload-unknown-size' => 'Невядомы памер',
+       'mwe-cancel-confim' => 'Вы ўпэўненыя, што жадаеце адмяніць?',
+       'mwe-successfulupload' => 'Пасьпяховая загрузка',
+       'mwe-uploaderror' => 'Памылка загрузкі',
+       'mwe-uploadwarning' => 'Папярэджаньне пад час загрузкі',
+       'mwe-unknown-error' => 'Невядомая памылка:',
+       'mwe-return-to-form' => 'Вярнуцца да формы',
+       'mwe-file-exists-duplicate' => 'Гэты файл дублюе наступныя файлы:',
+       'mwe-fileexists' => 'Файл з такой назвай ужо існуе. Калі ласка, праверце <b><tt>$1</tt></b>, калі Вы ня ўпэўненыя, што жадаеце яго замяніць.',
+       'mwe-fileexists-thumb' => '<center><b>Існуючы файл</b></center>',
+       'mwe-ignorewarning' => 'Праігнараваць папярэджаньне і захаваць файл',
+       'mwe-file-thumbnail-no' => 'Назва файла пачынаецца з <b><tt>$1</tt></b>',
+       'mwe-go-to-resource' => 'Перайсьці на старонку рэсурсу',
+       'mwe-upload-misc-error' => 'Невядомая памылка загрузкі',
+       'mwe-wgfogg_warning_bad_extension' => 'Вы выбралі файл з пашырэньнем, якое не падтрымліваецца (<a href="http://commons.wikimedia.org/wiki/Commons:Firefogg#Supported_File_Types">падрабязнасьці</a>).',
+       'mwe-upload-multi' => 'Загрузіць {{PLURAL:$1|файл|файлы}}',
+       'mwe-review-upload' => 'Праглядзець загрузку {{PLURAL:$1|файла|файлаў}}',
+       'mwe-credit-title' => 'Назва: $1',
+       'mwe-loading_plugin' => 'Загружаецца дапаўненьне …',
+       'mwe-select_playback' => 'Устанавіць настройкі прайграваньня',
+       'mwe-link_back' => 'Адваротная спасылка',
+       'mwe-error_swap_vid' => 'Памылка: mv_embed ня змог памяняць відэа тэг для інтэрфэйсу mv_embed',
+       'mwe-add_to_end_of_sequence' => 'Дадаць у канец пасьлядоўнасьці',
+       'mwe-missing_video_stream' => 'Відэа-файл для гэтага струменя адсутнічае',
+       'mwe-play_clip' => 'Прайграць частку файла',
+       'mwe-pause_clip' => 'Прыпыніць частку файла',
+       'mwe-volume_control' => 'Рэгуляваньне гучнасьці',
+       'mwe-player_options' => 'Устаноўкі прайгравальніка',
+       'mwe-closed_captions' => 'Субтытры',
+       'mwe-player_fullscreen' => 'На ўвесь экран',
+       'mwe-next_clip_msg' => 'Прайграць наступную частку файла',
+       'mwe-prev_clip_msg' => 'Прайграць папярэднюю частку файла',
+       'mwe-current_clip_msg' => 'Працягваць прайграваньне гэтай часткі файла',
+       'mwe-seek_to' => 'Перайсьці да $1',
+       'mwe-paused' => 'паўза',
+       'mwe-download_segment' => 'Выбар загрузкі:',
+       'mwe-download_full' => 'Загрузіць поўны відэа-файл:',
+       'mwe-download_right_click' => 'Для загрузкі націсьніце правую кнопку мышкі і выберыце <i>Захаваць спасылку як…</i>',
+       'mwe-download_clip' => 'Загрузіць відэа',
+       'mwe-download_text' => 'Загрузіць тэкст (<a style="color:white" title="cmml" href="http://wiki.xiph.org/index.php/CMML">CMML</a> xml):',
+       'mwe-download' => 'Загрузіць',
+       'mwe-share' => 'Зрабіць агульным',
+       'mwe-credits' => 'Стваральнікі',
+       'mwe-clip_linkback' => 'Крынічная старонка часткі файла',
+       'mwe-chose_player' => 'Выберыце відэа-прайгравальнік',
+       'mwe-share_this_video' => 'Зрабіць гэтае відэа агульным',
+       'mwe-video_credits' => 'Стваральнікі відэа',
+       'mwe-menu_btn' => 'Мэню',
+       'mwe-close_btn' => 'Зачыніць',
+       'mwe-ogg-player-vlc-player' => 'Прайгравальнік VLC',
+       'mwe-ogg-player-videoElement' => 'Убудаваная падтрымка Ogg-відэа',
+       'mwe-ogg-player-oggPlugin' => 'Агульнае дапаўненьне Ogg',
+       'mwe-ogg-player-quicktime-mozilla' => 'Дапаўненьне QuickTime',
+       'mwe-ogg-player-quicktime-activex' => 'QuickTime ActiveX',
+       'mwe-ogg-player-cortado' => 'Java Cortado',
+       'mwe-ogg-player-flowplayer' => 'Flowplayer',
+       'mwe-ogg-player-kplayer' => 'Прайгравальнік Kaltura',
+       'mwe-ogg-player-selected' => '(выбраны)',
+       'mwe-ogg-player-omtkplayer' => 'OMTK Flash Vorbis',
+       'mwe-generic_missing_plugin' => 'Ваш браўзэр, хутчэй за ўсё, не падтрымлівае наступны тып прайграваньня: <b>$1</b><br />Наведайце старонку <a href="http://commons.wikimedia.org/wiki/Commons:Media_help">Мэтады прайграваньня</a> для загрузкі прайгравальніка.<br />',
+       'mwe-for_best_experience' => 'Для лепшага прайграваньня відэа, мы рэкамэндуем: <br /><b><a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=mwEmbed">Firefox 3.5</a>.</b>',
+       'mwe-do_not_warn_again' => 'Пакуль адхіліць.',
+       'mwe-playerselect' => 'Прайгравальнікі',
+       'mwe-read_before_embed' => 'Калі ласка, <a href="http://mediawiki.org/wiki/Security_Notes_on_Remote_Embedding" target="_new">прачытайце гэта</a> перад устаўкай!',
+       'mwe-embed_site_or_blog' => 'Уставіць на старонку',
+       'mwe-related_videos' => 'Зьвязаныя відэа',
+       'mwe-seeking' => 'пошук',
+       'mwe-copy-code' => 'Капіяваць код',
+       'mwe-video-h264' => 'H.264 відэа',
+       'mwe-video-flv' => 'Flash-відэа',
+       'mwe-video-ogg' => 'Ogg-відэа',
+       'mwe-video-audio' => 'Ogg-аўдыё',
+);
+
+/** Bulgarian (Български)
+ * @author DCLXVI
+ */
+$messages['bg'] = array(
+       'mwe-sc_duration' => 'Продължителност',
+       'fogg-select_file' => 'Избиране на файл',
+       'fogg-select_new_file' => 'Избиране на нов файл',
+       'fogg-date-title' => 'Дата',
+       'fogg-license-title' => 'Лиценз',
+);
+
+/** Breton (Brezhoneg)
+ * @author Fohanno
+ * @author Fulup
+ * @author Y-M D
+ */
+$messages['br'] = array(
+       'mwe-cancel_image_insert' => "Nullañ an ensoc'hadenn",
+       'mwe-sc_duration' => 'Pad',
+       'mwe-custom_title' => 'Titl personelaet',
+       'mwe-edit_properties' => 'Aozañ ar perzhioù',
+       'mwe-edit-tools' => 'Binvioù aozañ',
+       'mwe-inline-description' => "Alc'hwez",
+       'mwe-duration' => 'Pad :',
+       'mwe-saving' => "oc'h enrollañ...",
+       'mwe-close' => 'serriñ',
+       'mwe-improve_transcript' => 'Gwellaat',
+       'mwe-menu_clipedit' => 'Aozañ ar media',
+       'mwe-menu_cliplib' => 'Ouzhpennañ ur media',
+       'mwe-menu_options' => 'Dibarzhioù',
+       'mwe-edit_clip' => "Aozañ ar c'hlip",
+       'mwe-save_done' => 'Echu eo an enrollañ',
+       'mwe-zoom_in' => 'Zoumiñ',
+       'mwe-zoom_out' => 'Dizoumiñ',
+       'mwe-rmclip' => "Dilemel ar c'hlip",
+       'mwe-editor_options' => 'Dibarzhioù an aozer',
+       'mwe-simple_editor_desc' => 'aozer eeun (stil iMovie)',
+       'mwe-other_options' => 'Dibarzhioù all',
+       'mwe-loading_txt' => 'o kargañ...',
+       'mwe-ok' => 'Mat eo',
+       'mwe-cancel' => 'Nullañ',
+       'mwe-setting-up-proxy' => 'Arventenniñ ar proksi...',
+       'fogg-select_file' => 'Diuzañ ur restr',
+       'fogg-select_new_file' => 'Diuzañ ur restr nevez',
+       'fogg-save_local_file' => 'Enrollañ er furmad Ogg',
+       'fogg-installed' => 'Staliet eo Firefogg',
+       'fogg-badtoken' => "N'eo ket reizh ar jedouer",
+       'mwe-stream_title' => '$1 $2 da $3',
+       'fogg-preset-custom' => 'Arventennoù personelaet',
+       'fogg-videoQuality-title' => 'Kalite ar video',
+       'fogg-audioQuality-title' => 'Kalite ar son',
+       'fogg-videoCodec-title' => 'Codec video',
+       'fogg-audioCodec-title' => 'codec son',
+       'fogg-width-title' => 'Ledander ar video',
+       'fogg-height-title' => 'Uhelder ar video',
+       'fogg-novideo-title' => 'Video ebet',
+       'fogg-noaudio-title' => 'Tamm son ebet',
+       'fogg-title-title' => 'Titl',
+       'fogg-title-help' => 'Un titl evit ho klip',
+       'fogg-artist-title' => "Anv ar c'hrouer",
+       'fogg-artist-help' => "Krouer ar c'hlip-mañ",
+       'fogg-date-title' => 'Deiziad',
+       'fogg-location-title' => "Lec'hiadur",
+       'fogg-organization-title' => 'Aozadur',
+       'fogg-copyright-title' => 'Copyright',
+       'fogg-copyright-help' => "Copyright ar c'hlip",
+       'fogg-license-title' => 'Aotre-implijout',
+       'fogg-contact-title' => 'Darempred',
+       'rsd_results_desc' => "Disoc'hoù $1 da $2",
+       'rsd_results_desc_total' => "Disoc'hoù $1 da $2 diwar $3",
+       'rsd_results_next' => "war-lerc'h",
+       'rsd_results_prev' => 'kent',
+       'mwe-link' => 'liamm',
+       'mwe-cc_pd_title' => 'Domani foran',
+       'mwe-update_preview' => 'Hizivaat ar rakwel',
+       'mwe-cancel_import' => 'Nullañ an enporzhiadur',
+       'mwe-ftype-jpg' => 'Restr skeudenn JPEG',
+       'mwe-ftype-png' => 'Restr skeudenn PNG',
+       'rsd-this_wiki-title' => 'Ar wiki-mañ',
+       'mwe-select_file' => 'Dibab ar restr',
+       'mwe-upload' => 'Kargañ ur restr',
+       'mwe-summary' => 'Diverrañ',
+       'mwe-uploaded-status' => 'Karget',
+       'mwe-upload-stats-fileprogres' => '$1 eus $2',
+       'mwe-upload-unknown-size' => 'Ment dianav',
+       'mwe-unknown-error' => 'Fazi dianav :',
+       'mwe-return-to-form' => "Distreiñ d'ar furmskrid",
+       'mwe-play_clip' => "Lenn ar c'hlip",
+       'mwe-pause_clip' => "Ehanañ ar c'hlip",
+       'mwe-player_options' => 'Dibarzhioù al lenner',
+       'mwe-player_fullscreen' => 'Skramm leun',
+       'mwe-next_clip_msg' => "Lenn ar c'hlip da-heul",
+       'mwe-prev_clip_msg' => "Lenn ar c'hlip kent",
+       'mwe-current_clip_msg' => "Kenderc'hel da lenn ar c'hlip-mañ",
+       'mwe-seek_to' => 'Mont da $1',
+       'mwe-paused' => 'ehanet',
+       'mwe-download_segment' => 'Pellgargañ an diuzadenn',
+       'mwe-download_full' => 'Pellgargañ ar restr video a-bezh :',
+       'mwe-download_clip' => 'Pellgargañ ar video',
+       'mwe-download' => 'Pellgargañ',
+       'mwe-share' => 'Eskemm',
+       'mwe-credits' => 'Kredoù',
+       'mwe-chose_player' => 'Dibab al lenner video',
+       'mwe-share_this_video' => 'Rannañ ar video-mañ',
+       'mwe-menu_btn' => 'Lañser',
+       'mwe-close_btn' => 'Serriñ',
+       'mwe-ogg-player-cortado' => 'Java Cortado',
+       'mwe-ogg-player-flowplayer' => 'Flowplayer',
+       'mwe-ogg-player-selected' => '(diuzet)',
+       'mwe-ogg-player-omtkplayer' => 'OMTK Flash Vorbis',
+       'mwe-do_not_warn_again' => 'Ehanañ evit ar poent.',
+       'mwe-playerselect' => 'Lennerioù',
+       'mwe-seeking' => 'o klask',
+);
+
+/** Bosnian (Bosanski)
+ * @author CERminator
+ */
+$messages['bs'] = array(
+       'mwe-crop' => 'Isjecanje slike',
+       'mwe-insert_image_page' => 'Ubaci u stranicu',
+       'mwe-insert_into_sequence' => 'Ubaci u niz',
+       'mwe-preview_insert' => 'Pregled ubacivanja',
+       'mwe-cancel_image_insert' => 'Odustani od ubacivanja',
+       'mwe-sc_audio' => 'Kontrola zvuka',
+       'mwe-sc_duration' => 'Trajanje',
+       'mwe-template_properties' => 'Svojstva šablona',
+       'mwe-custom_title' => 'Prilagođeni naslov',
+       'mwe-edit_properties' => 'Uredi svojstva',
+       'mwe-other_properties' => 'Ostala svojstva',
+       'mwe-resource_page' => 'Izvorna stranica:',
+       'mwe-start_time' => 'Vrijeme početka',
+       'mwe-end_time' => 'Vrijeme završetka',
+       'mwe-edit-tools' => 'Uređivanje alata',
+       'mwe-duration' => 'Trajanje:',
+       'mwe-watch-video' => 'Gledaj video',
+       'mwe-select-other-language' => 'Odaberi drugi jezik',
+       'mwe-saving' => 'spremam...',
+       'mwe-select_transcript_set' => 'Odaberi podnaslove',
+       'mwe-auto_scroll' => 'automatsko pomjeranje',
+       'mwe-close' => 'zatvori',
+       'mwe-improve_transcript' => 'Poboljšati',
+       'mwe-remove_transition' => 'Ukloni prelazak',
+       'mwe-add-transition' => 'Dodaj prijelaz',
+       'mwe-menu_clipedit' => 'Uredi mediju',
+       'mwe-menu_transition' => 'Prijelazi i efekti',
+       'mwe-menu_cliplib' => 'Dodaj mediju',
+       'mwe-menu_resource_overview' => 'Pregled resursa',
+       'mwe-menu_options' => 'Opcije',
+       'mwe-loading_timeline' => 'Učitavanje vremenske linije ...',
+       'mwe-loading_user_rights' => 'Učitavanje korisničkih prava ...',
+       'mwe-no_edit_permissions' => 'Nemate dopuštenja da spremite izmjene ove sekvence',
+       'mwe-edit_clip' => 'Uredi isječak',
+       'mwe-edit_save' => 'Spremi izmjene sekvence',
+       'mwe-saving_wait' => 'Spremanje u toku (molimo pričekajte)',
+       'mwe-save_done' => 'Spremanje završeno',
+       'mwe-edit_cancel' => 'Odustani od uređivanja sekvence',
+       'mwe-edit_cancel_confirm' => 'Da li ste sigurni da želite odustati od Vašeg uređivanja? Izmjene će biti izgubljene.',
+       'mwe-zoom_in' => 'Približi',
+       'mwe-zoom_out' => 'Udalji',
+       'mwe-cut_clip' => 'Rezanje isječaka',
+       'mwe-expand_track' => 'Proširi traku',
+       'mwe-collapse_track' => 'Smanji traku',
+       'mwe-pixle2sec' => 'pikseli u sekunde',
+       'mwe-rmclip' => 'Ukloni isječak',
+       'mwe-editor_options' => 'Opcije uređivača',
+       'mwe-editor_mode' => 'Način uređivanja',
+       'mwe-simple_editor_desc' => 'jednostavni uređivač (iMovie stil)',
+       'mwe-advanced_editor_desc' => 'napredni uređivač (Final Cut stil)',
+       'mwe-other_options' => 'Ostale opcije',
+       'mwe-contextmenu_opt' => 'Omogući kontekstne menije',
+       'mwe-loading_txt' => 'učitavam ...',
+       'mwe-apiproxy-setup' => 'Postavljanje API proksija',
+       'mwe-ok' => 'U redu',
+       'mwe-cancel' => 'Odustani',
+       'mwe-re-try' => 'Pokušaj API zahtjev',
+       'fogg-select_file' => 'Odaberi datoteku',
+       'fogg-select_new_file' => 'Odaberi novu datoteku',
+       'fogg-select_url' => 'Odaberi URL',
+       'fogg-save_local_file' => 'Sačuvaj Ogg',
+       'fogg-check_for_firefogg' => 'Provjera za Firefogg ...',
+       'fogg-installed' => 'Firefogg je instaliran',
+       'fogg-passthrough_mode' => 'Vaša odabrana datoteka je već Ogg ili nije video datoteka',
+       'fogg-badtoken' => 'Token nije valjan',
+       'mwe-imported_from' => '$1 uvezeno iz [$2 $3]. Pogledajte original ($4 stranica izvora) za više informacija.',
+       'mwe-stream_title' => '$1 $2 do $3',
+       'fogg-help-sticky' => 'Pomoć (klikni za lijepljenje)',
+       'fogg-cg-meta' => 'Metapodaci za isječak',
+       'fogg-cg-range' => 'Raspon šifriranja',
+       'fogg-preset-custom' => 'Prilagođene postavke',
+       'fogg-noaudio-title' => 'Bez zvuka',
+       'mwe-add_media_wizard' => 'Dodaj media čarobnjak',
+       'mwe-media_search' => 'Pretraga medije',
+       'rsd_results_desc' => 'Rezultati $1 od $2',
+       'rsd_results_next' => 'slijedeći',
+       'rsd_results_prev' => 'prethodni',
+       'rsd_no_results' => 'Nema rezultata pretrage za <b>$1</b>',
+       'mwe-upload_tab' => 'Postavljanje',
+       'rsd_layout' => 'Izgled:',
+       'rsd_resource_edit' => 'Uredi izvor: $1',
+       'mwe-resource_description_page' => 'Stranica opisa izvora',
+       'mwe-link' => 'link',
+       'rsd_local_resource_title' => 'Naslov lokalnog izvora',
+       'mwe-cc_nc_title' => 'Nije komercijalno',
+       'mwe-cc_pd_title' => 'Javno vlasništvo',
+       'mwe-unknown_license' => 'Nepoznata licenca',
+       'mwe-results_from' => 'Rezultati od <a href="$1" target="_new" >$2</a>',
+       'mwe-your_recent_uploads' => 'Vaša nedavna postavljanja na $1',
+       'mwe-upload_a_file' => 'Postavljanje nove datoteke na $1',
+       'mwe-resource_page_desc' => 'Opis izvorišne stranice:',
+       'mwe-local_resource_title' => 'Naslov lokalnog izvora:',
+       'mwe-watch_this_page' => 'Prati ovu stranicu',
+       'mwe-do_import_resource' => 'Uvoz resursa',
+       'mwe-update_preview' => 'Ažuriraj pregled',
+       'mwe-cancel_import' => 'Poništi uvoz',
+       'mwe-checking-resource' => 'Provjeravanje resursa',
+       'mwe-ftype-svg' => 'SVG vektorska datoteka',
+       'mwe-ftype-jpg' => 'JPEG slikovna datoteka',
+       'mwe-ftype-png' => 'PNG slikovna datoteka',
+       'mwe-ftype-oga' => 'Ogg zvučna datoteka',
+       'mwe-ftype-ogg' => 'Ogg video datoteka',
+       'rsd-this_wiki-title' => 'Ovaj wiki',
+       'mwe-select_file' => 'Odaberite datoteku',
+       'mwe-upload' => 'Postavljanje datoteke',
+       'mwe-destfilename' => 'Ime odredišne datoteke:',
+       'mwe-summary' => 'Sažetak',
+       'mwe-watch-this-file' => 'Prati ovu datoteku',
+       'mwe-ignore-any-warnings' => 'Zanemari sva upozorenja',
+       'mwe-upload-in-progress' => 'Postavljanje u toku (ne zatvarajte ovaj prozor)',
+       'mwe-uploaded-status' => 'Postavljena',
+       'mwe-upload-stats-fileprogress' => '$1 od $2',
+       'mwe-upload_completed' => 'Vaše postavljanje je završeno',
+       'mwe-upload-unknown-size' => 'Nepoznata veličina',
+       'mwe-cancel-confim' => 'Jeste li sigurni da želite poništiti?',
+       'mwe-successfulupload' => 'Postavljanje uspješno',
+       'mwe-uploaderror' => 'Greška pri postavljanju',
+       'mwe-uploadwarning' => 'Upozorenje pri postavljanju',
+       'mwe-unknown-error' => 'Nepoznata greška:',
+       'mwe-return-to-form' => 'Natrag na obrazac',
+       'mwe-file-exists-duplicate' => 'Ova datoteka je dvojnik slijedećih datoteka:',
+       'mwe-fileexists-thumb' => '<center><b>Postojeća datoteka</b></center>',
+       'mwe-upload-misc-error' => 'Nepoznata greška pri postavljanju',
+       'mwe-player_fullscreen' => 'Puni ekran',
+       'mwe-paused' => 'zaustavljeno',
+       'mwe-download' => 'Učitavanje',
+       'mwe-share' => 'Dijeli',
+       'mwe-credits' => 'Zasluge',
+       'mwe-share_this_video' => 'Dijeli ovaj video',
+       'mwe-menu_btn' => 'Meni',
+       'mwe-close_btn' => 'Zatvori',
+       'mwe-related_videos' => 'Povezani snimci',
+);
+
+/** Catalan (Català)
+ * @author Solde
+ */
+$messages['ca'] = array(
+       'rsd_results_desc' => 'Resultats',
+       'rsd_results_next' => 'següent',
+       'rsd_results_prev' => 'anterior',
+);
+
+/** Czech (Česky)
+ * @author Mormegil
+ */
+$messages['cs'] = array(
+       'mwe-crop' => 'Oříznout obrázek',
+       'mwe-apply_crop' => 'Použít ořez',
+       'mwe-reset_crop' => 'Zrušit ořez',
+       'mwe-insert_image_page' => 'Vložit do stránky',
+       'mwe-preview_insert' => 'Náhled vložení',
+       'mwe-cancel_image_insert' => 'Zrušit vkládání',
+       'mwe-edit-tools' => 'Nástroje pro editaci',
+       'mwe-inline-description' => 'Titulek',
+       'mwe-no_text_tracks_found' => 'Žádné titulky nenalezeny',
+       'mwe-add-edit-subs' => 'Přidat/editovat titulky',
+       'mwe-loading_txt' => 'Načítá se …',
+       'mwe-loading-add-media-wiz' => 'Načítá se průvodce pro přidání souboru',
+       'mwe-cancel' => 'Storno',
+       'fogg-check_for_firefogg' => 'Ověřuje se Firefogg…',
+       'fogg-installed' => 'Firefogg je nainstalován',
+       'fogg-for_improved_uploads' => 'Pro vylepšené načítání:',
+       'fogg-please_install' => '<a href="$1">Nainstalujte si Firefogg.</a> <a href="http://commons.wikimedia.org/wiki/Commons:Firefogg/cs">Další informace o&nbsp;Firefoggu</a>',
+       'fogg-use_latest_firefox' => 'Nejprve si nainstalujte <a href="http://www.mozilla-europe.org/cs/firefox/?from=firefogg">Firefox 3.5</a> (nebo novější). <i>Poté se vraťte na tuto stránku, abyste si mohli nainstalovat rozšíření <b>Firefogg</b>.</i>',
+       'mwe-add_media_wizard' => 'Průvodce pro přidání souboru',
+       'mwe-media_search' => 'Hledání multimédií',
+       'rsd_box_layout' => 'Ikony',
+       'rsd_list_layout' => 'Seznam',
+       'rsd_results_desc' => 'Výsledky $1–$2',
+       'rsd_results_desc_total' => 'Výsledky $1–$2 z $3',
+       'rsd_results_next' => 'dalších',
+       'rsd_results_prev' => 'předchozích',
+       'rsd_no_results' => 'Hledání <b>$1</b> nenalezlo žádné výsledky',
+       'rsd_layout' => 'Rozložení:',
+       'rsd_resource_edit' => 'Editace zdroje: $1',
+       'mwe-resource_description_page' => 'Stránka s popisem zdroje',
+       'mwe-link' => 'odkaz',
+       'rsd_do_insert' => 'Vložit',
+       'mwe-cc_by_title' => 'Uveďte autora',
+       'mwe-cc_nc_title' => 'Neužívejte dílo komerčně',
+       'mwe-cc_nd_title' => 'Nezasahujte do díla',
+       'mwe-cc_sa_title' => 'Zachovejte licenci',
+       'mwe-cc_pd_title' => 'Volné dílo',
+       'mwe-unknown_license' => 'Neznámá licence',
+       'mwe-results_from' => 'Výsledky z <a href="$1" target="_new" >$2</a>',
+       'mwe-preview_insert_resource' => 'Náhled vložení zdroje: $1',
+       'mwe-ftype-svg' => 'Vektorový obrázek SVG',
+       'mwe-ftype-jpg' => 'Obrázek JPEG',
+       'mwe-ftype-png' => 'Obrázek PNG',
+       'mwe-ftype-oga' => 'Zvukový soubor Ogg',
+       'mwe-ftype-ogg' => 'Soubor videa Ogg',
+       'mwe-ftype-unk' => 'Neznámý formát souboru',
+       'rsd-wiki_commons-title' => 'Wikimedia Commons',
+       'rsd-wiki_commons' => 'Wikimedia Commons, archiv svobodně licencovaného vzdělávacího multimediálního obsahu (obrázky, zvuky, video)',
+       'rsd-this_wiki-title' => 'Tato wiki',
+       'rsd-this_wiki-desc' => 'Místní instalace wiki',
+       'rsd-archive_org-desc' => 'Internet Archive, digitální knihovna kulturních výtvorů',
+       'rsd-flickr-desc' => 'Flickr.com, server pro online sdílení fotografií',
+       'rsd-metavid-desc' => 'Metavid.org, komunitní archiv záznamů jednání amerického Senátu a Sněmovny reprezentantů',
+       'mwe-licence_cc-by-sa' => 'Creative Commons Zachovejte licenci (3.0)',
+       'mwe-upload-in-progress' => 'Soubor se načítá (nezavírejte toto okno)',
+       'mwe-upload-stats-fileprogress' => '$1 z $2',
+       'mwe-upload_completed' => 'Načítání dokončeno',
+       'mwe-upload_done' => '<a href="$1">Načtený soubor <i>by měl být</i> nyní dostupný.</a>',
+       'mwe-cancel-confim' => 'Určitě chcete stornovat?',
+       'mwe-successfulupload' => 'Úspěšně načteno',
+       'mwe-uploadwarning' => 'Upozornění k načítání',
+       'mwe-unknown-error' => 'Neznámá chyba:',
+       'mwe-return-to-form' => 'Zpět na formulář',
+       'mwe-fileexists' => 'Soubor s tímto jménem již existuje, prosím podívejte se na <b><tt>$1</tt></b>, pokud nevíte jistě, zda chcete tento soubor nahradit.',
+       'mwe-fileexists-thumb' => '<center><b>Existující soubor</b></center>',
+       'mwe-ignorewarning' => 'Ignorovat varování a přesto soubor načíst',
+       'mwe-go-to-resource' => 'Přejít k souboru',
+       'mwe-upload-misc-error' => 'Neznámá chyba',
+       'mwe-play_clip' => 'Přehrát klip',
+       'mwe-pause_clip' => 'Pozastavit klip',
+       'mwe-volume_control' => 'Ovládání hlasitosti',
+       'mwe-player_options' => 'Možnosti přehrávače',
+       'mwe-closed_captions' => 'Titulky',
+       'mwe-player_fullscreen' => 'Celá obrazovka',
+       'mwe-seek_to' => 'Přesun na $1',
+       'mwe-download_full' => 'Stažení celého videosouboru:',
+       'mwe-download' => 'Stáhnout',
+       'mwe-share' => 'Sdílet',
+       'mwe-chose_player' => 'Vybrat přehrávač videa',
+       'mwe-share_this_video' => 'Sdílet toto video',
+       'mwe-close_btn' => 'Zavřít',
+       'mwe-ogg-player-videoElement' => 'Vestavěná podpora pro Ogg video',
+       'mwe-ogg-player-oggPlugin' => 'Generický zásuvný modul Ogg',
+       'mwe-ogg-player-quicktime-mozilla' => 'Zásuvný modul QuickTime',
+       'mwe-ogg-player-quicktime-activex' => 'ActiveX prvek QuickTime',
+       'mwe-ogg-player-cortado' => 'Java Cortado',
+       'mwe-ogg-player-flowplayer' => 'Flowplayer',
+       'mwe-ogg-player-selected' => '(vybraný)',
+       'mwe-ogg-player-omtkplayer' => 'OMTK Flash Vorbis',
+       'mwe-generic_missing_plugin' => 'Váš prohlížeč patrně nepodporuje následující způsob přehrávání: <b>$1</b><br />Přehrávač si můžete stáhnout prostřednictvím stránky <a href="http://commons.wikimedia.org/wiki/Commons:N%C3%A1pov%C4%9Bda_k_multim%C3%A9di%C3%ADm">nápovědy k multimédiím</a>.<br />',
+       'mwe-for_best_experience' => 'Pro příjemnější přehrávání videa doporučujeme:<br /><b><a href="http://www.mozilla-europe.org/cs/firefox/?from=mwEmbed">Firefox 3.5</a>.</b>',
+       'mwe-do_not_warn_again' => 'Skrýt toto hlášení.',
+       'mwe-playerselect' => 'Přehrávače',
+       'mwe-read_before_embed' => 'Před vkládáním <a href="http://mediawiki.org/wiki/Security_Notes_on_Remote_Embedding" target="_new">čtěte upozornění</a>.',
+       'mwe-embed_site_or_blog' => 'Vložení na stránku',
+       'mwe-seeking' => 'přesun',
+       'mwe-copy-code' => 'Kopírovat kód',
+);
+
+/** Welsh (Cymraeg)
+ * @author Lloffiwr
+ */
+$messages['cy'] = array(
+       'mwe-loading_txt' => "wrthi'n llwytho ...",
+);
+
+/** German (Deutsch)
+ * @author Als-Holder
+ * @author Jan Luca
+ * @author Lukas9950
+ * @author MF-Warburg
+ * @author McDutchie
+ * @author Metalhead64
+ * @author Pill
+ * @author Tbleher
+ * @author The Evil IP address
+ * @author Umherirrender
+ */
+$messages['de'] = array(
+       'mwe-crop' => 'Bild zuschneiden',
+       'mwe-apply_crop' => 'Zuschnitt auf das Bild anwenden',
+       'mwe-reset_crop' => 'Zuschnitt zurücksetzen',
+       'mwe-insert_image_page' => 'In Seite einfügen',
+       'mwe-insert_into_sequence' => 'In Sequenz einfügen',
+       'mwe-cancel_image_insert' => 'Einfügen abbrechen',
+       'mwe-sc_fileopts' => 'Clipdetail bearbeiten',
+       'mwe-sc_inoutpoints' => 'Ein-Aus-Punkte setzen',
+       'mwe-sc_overlays' => 'Überlagerungen',
+       'mwe-sc_audio' => 'Audiosteuerung',
+       'mwe-sc_duration' => 'Dauer',
+       'mwe-template_properties' => 'Vorlageneigenschaften',
+       'mwe-custom_title' => 'Benutzerdefinierter Titel',
+       'mwe-edit_properties' => 'Eigenschaften bearbeiten',
+       'mwe-other_properties' => 'Andere Eigenschaften',
+       'mwe-resource_page' => 'Quellseite:',
+       'mwe-set_in_out_points' => 'Ein-Aus-Punkte setzen',
+       'mwe-start_time' => 'Startzeit',
+       'mwe-end_time' => 'Endzeit',
+       'mwe-preview_inout' => 'Vorschau der Ein-Aus-Punkte',
+       'mwe-duration' => 'Dauer:',
+       'mwe-watch-video' => 'Video ansehen',
+       'mwe-select-other-language' => 'Andere Sprache auswählen',
+       'mwe-saving' => 'wird gespeichert …',
+       'mwe-select_transcript_set' => 'Untertitel auswählen',
+       'mwe-auto_scroll' => 'Automatisches Scrollen',
+       'mwe-close' => 'schließen',
+       'mwe-improve_transcript' => 'Verbessern',
+       'mwe-no_text_tracks_found' => 'Keine Textabschnitte gefunden',
+       'mwe-transition_in' => 'Übergang ein',
+       'mwe-transition_out' => 'Übergang aus',
+       'mwe-remove_transition' => 'Übergang entfernen',
+       'mwe-menu_transition' => 'Übergänge und Effekte',
+       'mwe-menu_resource_overview' => 'Quellübersicht',
+       'mwe-menu_options' => 'Optionen',
+       'mwe-loading_timeline' => 'Lade Zeitleiste …',
+       'mwe-loading_user_rights' => 'Lade Benutzerrechte …',
+       'mwe-no_edit_permissions' => 'Du hast keine Berechtigungen, Änderungen zu dieser Sequenz zu speichern',
+       'mwe-edit_clip' => 'Clip bearbeiten',
+       'mwe-edit_save' => 'Sequenzänderungen speichern',
+       'mwe-saving_wait' => 'Speichere (bitte warten)',
+       'mwe-save_done' => 'Speicherung fertig',
+       'mwe-edit_cancel' => 'Sequenzbearbeitung abbrechen',
+       'mwe-edit_cancel_confirm' => 'Bist du sicher, dass du deine Bearbeitung abbrechen willst? Änderungen gehen verloren.',
+       'mwe-zoom_in' => 'Vergrößern',
+       'mwe-zoom_out' => 'Verkleinern',
+       'mwe-cut_clip' => 'Clips schneiden',
+       'mwe-expand_track' => 'Spur ausklappen',
+       'mwe-collapse_track' => 'Spur einklappen',
+       'mwe-play_from_position' => 'Abspielen ab Playline-Position',
+       'mwe-rmclip' => 'Clip entfernen',
+       'mwe-clip_in' => 'Clip hinzufügen',
+       'mwe-clip_out' => 'Clip entfernen',
+       'mwe-no_selected_resource' => '<h3>Keine Quelle ausgewählt</h3> Wähle einen Clip aus, um das Bearbeiten zu aktivieren.',
+       'mwe-error_edit_multiple' => '<h3>Mehrere Quellen ausgewählt</h3> Wähle nur einen Clip aus, um ihn zu bearbeiten.',
+       'mwe-editor_options' => 'Editoroptionen',
+       'mwe-editor_mode' => 'Editormodus',
+       'mwe-simple_editor_desc' => 'einfacher Editor (iMovie-Stil)',
+       'mwe-advanced_editor_desc' => 'erweiterter Editor (Final-Cut-Stil)',
+       'mwe-other_options' => 'Andere Optionen',
+       'mwe-contextmenu_opt' => 'Kontextmenüs aktivieren',
+       'mwe-sequencer_credit_line' => 'Entwickelt von <a href="http://kaltura.com">Kaltura, Inc.</a> in Zusammenarbeit mit der <a href="http://wikimediafoundation.org/wiki/Home">Wikimedia Foundation</a> (<a href="#">mehr Informationen</a>).',
+       'mwe-loading_txt' => 'lade …',
+       'mwe-error_load_lib' => 'Fehler: JavaScript $1 war nicht abrufbar oder lässt $2 nicht zu',
+       'mwe-apiproxy-setup' => 'API-Proxy-Konfiguration',
+       'mwe-ok' => 'OK',
+       'mwe-cancel' => 'Abbrechen',
+       'mwe-setting-up-proxy' => 'Proxy-Einstellung …',
+       'mwe-re-try' => 'Wiederhole API-Anfrage',
+       'mwe-re-trying' => 'Wiederholung der API-Anfrage …',
+       'mwe-proxy-not-ready' => 'Proxy nicht konfiguriert',
+       'mwe-please-login' => 'Du bist auf $2 nicht <a target="_new" href="$1">angemeldet</a> oder mwEmbed ist nicht aktiviert. Löse das Problem und wiederhole deine Anfrage.',
+       'mwe-remember-loging' => 'Allgemeiner Sicherheitshinweis: Websiteanmeldung nur, wenn deine Adressleiste die Websiteadresse anzeigt.',
+       'fogg-select_file' => 'Wähle Datei',
+       'fogg-select_new_file' => 'Wähle eine neue Datei',
+       'fogg-select_url' => 'Wähle eine URL',
+       'fogg-save_local_file' => 'Ogg speichern',
+       'fogg-check_for_firefogg' => 'Suche nach Firefogg …',
+       'fogg-installed' => 'Firefogg ist installiert',
+       'fogg-for_improved_uploads' => 'Für verbessertes Hochladen:',
+       'fogg-please_install' => '<a href="$1">Installiere Firefogg</a>. Mehr <a href="http://commons.wikimedia.org/wiki/Commons:Firefogg">über Firefogg</a>',
+       'fogg-use_latest_firefox' => 'Installiere bitte zuerst [http://de.www.mozilla.com/de/ Firefox 3.5] (oder eine spätere Version).
+<i>Besuche danach die Seite neu, um die <b>Firefogg</b>-Erweiterung zu installieren.</i>',
+       'fogg-passthrough_mode' => 'Deine ausgewählte Datei ist bereits Ogg oder keine Videodatei',
+       'fogg-transcoding' => 'Codiere Video nach Ogg',
+       'fogg-encoding-done' => 'Codierung abgeschlossen',
+       'fogg-badtoken' => 'Token nicht gültig',
+       'fogg-preview' => 'Videovorschau',
+       'fogg-hidepreview' => 'Vorschau verstecken',
+       'mwe-imported_from' => '$1 importiert von [$2 $3]. Siehe die [$4 Originalquellseite] für mehr Informationen.',
+       'mwe-stream_title' => '$1 $2 bis $3',
+       'fogg-help-sticky' => 'Hilfe (klicken für das Feststellen)',
+       'fogg-cg-preset' => 'Voreinstellung: <strong>$1</strong>',
+       'fogg-cg-quality' => 'Qualitäts- und Auflösungs-Basiseinstellungen',
+       'fogg-cg-meta' => 'Metadaten für den Clip',
+       'fogg-cg-range' => 'Codierungsbereich',
+       'fogg-cg-advVideo' => 'Erweiterte Videocodierungseinstellungen',
+       'fogg-cg-advAudio' => 'Erweiterte Audiocodierungseinstellungen',
+       'fogg-preset-custom' => 'Benutzerdefinierte Einstellungen',
+       'fogg-webvideo-desc' => 'Internetvideo Theora, Vorbis 400 kbit/s und 400px maximale Größe',
+       'fogg-savebandwidth-desc' => 'Niedrige Bandbreite Theora, Vorbis 164 kbit/s und 200px maximale Größe',
+       'fogg-highquality-desc' => 'Hohe Qualität Theora, Vorbis 1080px maximale Größe',
+       'fogg-videoQuality-title' => 'Videoqualität',
+       'fogg-videoQuality-help' => 'Wird verwendet, um die <i>visuelle Qualität</i> des kodierten Videos einzustellen (nicht verwendet, wenn du die Bitrate in erweiterten Einstellungen unten änderst).',
+       'fogg-starttime-title' => 'Startsekunde',
+       'fogg-starttime-help' => 'Nur von Zeit in Sekunden kodieren',
+       'fogg-endtime-title' => 'Endsekunde',
+       'fogg-audioQuality-title' => 'Audioqualität',
+       'fogg-audioQuality-help' => 'Wird verwendet, um die <i>akustische Qualität</i> vom kodierten Audio einzustellen (nicht verwendet, wenn du die Bitrate in erweiterten Einstellungen unten änderst).',
+       'fogg-videoCodec-title' => 'Videocodec',
+       'fogg-videoCodec-help' => 'Wird verwendet, um den Videocodec für den Clip auszuwählen. Aktuell wird nur Theora unterstützt. Mehr über <a target="_new" href="http://de.wikipedia.org/wiki/Theora">Theora</a>.',
+       'fogg-audioCodec-title' => 'Audiocodec',
+       'fogg-audioCodec-help' => 'Wird verwendet, um den Audiocodec des Clips einzustellen. Aktuell wird nur Vorbis unterstützt. Mehr über <a target="_new" href="http://de.wikipedia.org/wiki/Vorbis">Vorbis</a>',
+       'fogg-width-title' => 'Videobreite',
+       'fogg-width-help' => 'An die gegebene Breite anpassen.',
+       'fogg-height-title' => 'Videohöhe',
+       'fogg-height-help' => 'An die gegebene Höhe anpassen.',
+       'fogg-videoBitrate-title' => 'Videobitrate',
+       'fogg-videoBitrate-help' => 'Videobitrate stellt die Kodierungsbitrate für das Video ein (in kb/s)',
+       'fogg-twopass-title' => 'Two-pass encoding',
+       'fogg-framerate-title' => 'Bildfrequenz',
+       'fogg-framerate-help' => 'Die Video-Bildfrequenz. Mehr über <a target="_new" href="http://de.wikipedia.org/wiki/Bildfrequenz">Bildfrequenz</a>.',
+       'fogg-aspect-title' => 'Seitenverhältnis',
+       'fogg-aspect-help' => 'Das Video-Seitenverhältnis kann in 4:3 oder 16:9 fraktioniert werden. Mehr über <a target="_new" href="http://de.wikipedia.org/wiki/Seitenverhältnis_(Film)">Seitenverhältnis</a>.',
+       'fogg-keyframeInterval-title' => 'Schlüsselbild-Intervall',
+       'fogg-keyframeInterval-help' => 'Der Schlüsselbild-Intervall in Bilder. Achtung: Manche Codecs erzwingen Schlüsselbilder, wenn der Unterschied zwischen Bildern größer ist als die Schlüsselbildgröße. Mehr über <a href="http://de.wikipedia.org/wiki/B-Frame">B-Frame</a>.',
+       'fogg-denoise-title' => 'Rauschfilter',
+       'fogg-denoise-help' => 'Video entrauschen. Mehr über <a href="http://de.wikipedia.org/wiki/Rauschunterdrückungsverfahren">Rauschunterdrückung</a>.',
+       'fogg-novideo-title' => 'Kein Video',
+       'fogg-novideo-help' => 'Video in der Ausgabe deaktivieren',
+       'fogg-audioBitrate-title' => 'Audiobitrate',
+       'fogg-samplerate-title' => 'Audio-Abtastrate',
+       'fogg-samplerate-help' => 'Ausgabe-Abtastrate (in Hz).',
+       'fogg-noaudio-title' => 'Kein Audio',
+       'fogg-noaudio-help' => 'Audio in der Ausgabe deaktivieren',
+       'fogg-title-title' => 'Titel',
+       'fogg-title-help' => 'Ein Titel für deinen Clip',
+       'fogg-artist-title' => 'Autor',
+       'fogg-artist-help' => 'Der Autor dieses Clips',
+       'fogg-date-title' => 'Datum',
+       'fogg-date-help' => 'Das Datum, an dem das Filmmaterial erstellt oder veröffentlicht wurde',
+       'fogg-location-title' => 'Lage',
+       'fogg-location-help' => 'Ort des Filmmaterials',
+       'fogg-organization-title' => 'Organisation',
+       'fogg-organization-help' => 'Name der Organisation (Studio)',
+       'fogg-copyright-title' => 'Copyright',
+       'fogg-copyright-help' => 'Copyright des Clips',
+       'fogg-license-title' => 'Lizenz',
+       'fogg-license-help' => 'Die Lizenz des Clips (vorzugsweise eine Creative-Commons-URL).',
+       'fogg-contact-title' => 'Kontakt',
+       'fogg-contact-help' => 'Kontaktlink',
+       'mwe-add_media_wizard' => 'Media-Wizard',
+       'mwe-media_search' => 'Mediensuche',
+       'rsd_list_layout' => 'Listenlayout',
+       'rsd_results_desc' => 'Ergebnisse $1 bis $2',
+       'rsd_results_desc_total' => 'Ergebnisse $1 bis $2 von $3',
+       'rsd_results_next' => 'weiter',
+       'rsd_results_prev' => 'zurück',
+       'rsd_no_results' => 'Keine Suchergebnisse für <b>$1</b>',
+       'mwe-upload_tab' => 'Hochladen',
+       'rsd_layout' => 'Layout:',
+       'rsd_resource_edit' => 'Quelle bearbeiten: $1',
+       'mwe-resource_description_page' => 'Quellbeschreibungsseite',
+       'mwe-link' => 'Link',
+       'rsd_local_resource_title' => 'Lokaler Quelltitel',
+       'rsd_do_insert' => 'Einfügen',
+       'mwe-cc_by_title' => 'Namensnennung',
+       'mwe-cc_nc_title' => 'Keine kommerzielle Nutzung',
+       'mwe-cc_nd_title' => 'Keine Bearbeitung',
+       'mwe-cc_sa_title' => 'Weitergabe unter gleichen Bedingungen',
+       'mwe-cc_pd_title' => 'Public Domain',
+       'mwe-unknown_license' => 'Unbekannte Lizenz',
+       'mwe-no_import_by_url' => 'Dieser Benutzer oder dieses Wiki <b>kann keine</b> Posten von externen URLs importieren.<p>Musst du dich anmelden?</p><p>Ist die upload_by_url-Berechtigung für dich konfiguriert? Ist <a href="http://www.mediawiki.org/wiki/Manual:$wgAllowCopyUploads">$wgAllowCopyUploads</a> auf diesem Wiki aktiviert?</p>',
+       'mwe-results_from' => 'Ergebnisse von <a href="$1" target="_new" >$2</a>',
+       'mwe-missing_desc_see_source' => 'Diesem Posten fehlt eine Beschreibung. Bitte sieh dir die [$1 Originalquelle] an und hilf mit, ihn zu beschreiben.',
+       'mwe-your_recent_uploads' => 'Deine letzten hochgeladenen Dateien auf $1',
+       'mwe-upload_a_file' => 'Eine neue Datei nach $1 hochladen',
+       'mwe-resource_page_desc' => 'Quellseitenbeschreibung:',
+       'mwe-edit_resource_desc' => 'Wikitextquellbeschreibung bearbeiten:',
+       'mwe-local_resource_title' => 'Lokaler Quelltitel:',
+       'mwe-watch_this_page' => 'Diese Seite beobachten',
+       'mwe-do_import_resource' => 'Quelle importieren',
+       'mwe-update_preview' => 'Vorschau aktualisieren',
+       'mwe-cancel_import' => 'Import abbrechen',
+       'mwe-importing_asset' => 'Importiere',
+       'mwe-checking-resource' => 'Suche die Quelle',
+       'mwe-resource-needs-import' => 'Quelle $1 muss nach $2 importiert werden',
+       'mwe-ftype-svg' => 'SVG-Vektorgrafik',
+       'mwe-ftype-jpg' => 'JPEG-Bild',
+       'mwe-ftype-png' => 'PNG-Bild',
+       'mwe-ftype-oga' => 'Ogg-Audiodatei',
+       'mwe-ftype-ogg' => 'Ogg-Videodatei',
+       'mwe-ftype-unk' => 'Unbekanntes Dateiformat',
+       'rsd-this_wiki-title' => 'Dieses Wiki',
+       'mwe-select_file' => 'Datei auswählen',
+       'mwe-more_licence_options' => 'Für mehr Lizenzoptionen, besuche die <a href="$1">normale Hochladeseite</a>',
+       'mwe-select_ownwork' => 'Ich lade meine eigene Arbeit hoch und lizenziere sie unter:',
+       'mwe-licence_cc-by-sa' => 'Creative Commons Weitergabe unter gleichen Bedingungen (3.0)',
+       'mwe-upload' => 'Datei hochladen',
+       'mwe-destfilename' => 'Zieldateiname:',
+       'mwe-summary' => 'Zusammenfassung',
+       'mwe-error_not_loggedin' => 'Du bist nicht angemeldet oder hast keine Hochladeberechtigungen.',
+       'mwe-watch-this-file' => 'Diese Datei ansehen',
+       'mwe-ignore-any-warnings' => 'Alle Warnungen ignorieren',
+       'mwe-upload-transcode-in-progress' => 'Transcodiere und lade hoch (dieses Fenster nicht schließen)',
+       'mwe-upload-in-progress' => 'Lade hoch (dieses Fenster nicht schließen)',
+       'mwe-upload-transcoded-status' => 'Transcodiert',
+       'mwe-uploaded-status' => 'Hochgeladen',
+       'mwe-upload-stats-fileprogress' => '$1 von $2',
+       'mwe-upload_completed' => 'Das Hochladen ist abgeschlossen',
+       'mwe-upload_done' => '<a href="$1">Deine hochgeladene Datei <i>sollte</i> verfügbar sein</a>.',
+       'mwe-upload-unknown-size' => 'Unbekannte Größe',
+       'mwe-cancel-confim' => 'Möchtest du wirklich abbrechen?',
+       'mwe-successfulupload' => 'Hochladen erfolgreich',
+       'mwe-uploaderror' => 'Hochladefehler',
+       'mwe-uploadwarning' => 'Hochladewarnung',
+       'mwe-unknown-error' => 'Unbekannter Fehler:',
+       'mwe-return-to-form' => 'Zurück zum Formular',
+       'mwe-file-exists-duplicate' => 'Diese Datei ist ein Duplikat der folgenden Datei:',
+       'mwe-fileexists' => 'Eine Datei mit diesem Namen existiert bereits. Bitte prüfe <b><tt>$1</tt></b>, wenn du dir bei der Änderung nicht sicher bist.',
+       'mwe-fileexists-thumb' => '<center><b>Existierende Datei</b></center>',
+       'mwe-ignorewarning' => 'Warnung ignorieren und Datei trotzdem speichern',
+       'mwe-file-thumbnail-no' => 'Der Dateiname beginnt mit <b><tt>$1</tt></b>',
+       'mwe-go-to-resource' => 'Gehe zur Quellseite',
+       'mwe-upload-misc-error' => 'Unbekannter Hochladefehler',
+       'mwe-wgfogg_warning_bad_extension' => 'Du hast eine Datei mit einer nicht unterstützten Extension ausgewählt (<a href="http://commons.wikimedia.org/wiki/Commons:Firefogg#Supported_File_Types">mehr Informationen</a>).',
+       'mwe-upload-multi' => '{{PLURAL:$1|Datei|Dateien}} hochladen',
+       'mwe-review-upload' => 'Hochgeladene {{PLURAL:$1|Datei|Dateien}} überprüfen',
+       'mwe-loading_plugin' => 'lade Plugin …',
+       'mwe-select_playback' => 'Wiedergabeeinstellungen ändern',
+       'mwe-error_swap_vid' => 'Fehler: mv_embed konnte nicht das Videotag für die mv_embed-Oberfläche auslagern',
+       'mwe-add_to_end_of_sequence' => 'Zum Ende der Sequenz hinzufügen',
+       'mwe-missing_video_stream' => 'Die Videodatei für diesen Stream fehlt',
+       'mwe-play_clip' => 'Clip abspielen',
+       'mwe-pause_clip' => 'Clip pausieren',
+       'mwe-volume_control' => 'Lautstärkensteuerung',
+       'mwe-player_options' => 'Playeroptionen',
+       'mwe-closed_captions' => 'Untertitel',
+       'mwe-player_fullscreen' => 'Vollbild',
+       'mwe-next_clip_msg' => 'Nächsten Clip wiedergeben',
+       'mwe-prev_clip_msg' => 'Vorherigen Clip wiedergeben',
+       'mwe-current_clip_msg' => 'Mit der Wiedergabe dieses Clips fortfahren',
+       'mwe-seek_to' => 'Suche $1',
+       'mwe-paused' => 'pausiert',
+       'mwe-download_segment' => 'Auswahl herunterladen:',
+       'mwe-download_full' => 'Ganze Videodatei herunterladen:',
+       'mwe-download_right_click' => 'Klicke zum Herunterladen die rechte Maustaste und wähle <i>Link speichern unter…</i> aus',
+       'mwe-download_clip' => 'Video herunterladen',
+       'mwe-download_text' => 'Text herunterladen (<a style="color:white" title="cmml" href="http://wiki.xiph.org/index.php/CMML">CMML</a> xml):',
+       'mwe-download' => 'Herunterladen',
+       'mwe-share' => 'Teilen',
+       'mwe-credits' => 'Credits',
+       'mwe-clip_linkback' => 'Clip-Quellseite',
+       'mwe-chose_player' => 'Videoplayer auswählen',
+       'mwe-share_this_video' => 'Dieses Video teilen',
+       'mwe-video_credits' => 'Videocredits',
+       'mwe-menu_btn' => 'Menü',
+       'mwe-close_btn' => 'Schließen',
+       'mwe-ogg-player-videoElement' => 'Natives Ogg-Video',
+       'mwe-ogg-player-oggPlugin' => 'Allgemeines Ogg-Plugin',
+       'mwe-ogg-player-quicktime-mozilla' => 'QuickTime-Plugin',
+       'mwe-ogg-player-quicktime-activex' => 'QuickTime ActiveX',
+       'mwe-ogg-player-cortado' => 'Java Cortado',
+       'mwe-ogg-player-flowplayer' => 'Flowplayer',
+       'mwe-ogg-player-selected' => '(ausgewählt)',
+       'mwe-ogg-player-omtkplayer' => 'OMTK Flash Vorbis',
+       'mwe-generic_missing_plugin' => 'Dein Browser scheint folgenden Wiedergabetyp nicht zu unterstützen: <b>$1</b><br />Besuche die <a href="http://commons.wikimedia.org/wiki/Commons:Media_help">Multimediahilfe</a>, um einen Player herunterzuladen.<br />',
+       'mwe-for_best_experience' => 'Für eine bessere Videowiedergabe wird empfohlen:<br /><b><a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=mwEmbed">Firefox 3.5</a>.</b>',
+       'mwe-do_not_warn_again' => 'Dieses Mal ignorieren.',
+       'mwe-playerselect' => 'Player',
+       'mwe-read_before_embed' => 'Bitte lies vor dem Einbinden die <a href="http://mediawiki.org/wiki/Security_Notes_on_Remote_Embedding" target="_new">Sicherheitsanmerkungen</a>!',
+       'mwe-embed_site_or_blog' => 'Auf deiner Seite einbinden',
+       'mwe-related_videos' => 'Ähnliche Videos',
+       'mwe-seeking' => 'suchen',
+       'mwe-copy-code' => 'Code kopieren',
+       'mwe-video-h264' => 'H.264-Video',
+       'mwe-video-flv' => 'Flash-Video',
+       'mwe-video-ogg' => 'Ogg-Video',
+       'mwe-video-audio' => 'Ogg-Audiodatei',
+);
+
+/** Zazaki (Zazaki)
+ * @author Aspar
+ * @author McDutchie
+ * @author Mirzali
+ * @author Xoser
+ */
+$messages['diq'] = array(
+       'mwe-crop' => 'resım bıqesn',
+       'mwe-apply_crop' => 'qesnayiş resım re tetbiq bıker',
+       'mwe-reset_crop' => 'qesnayiş sıfır ker',
+       'mwe-insert_image_page' => 'pela têarê ker',
+       'mwe-insert_into_sequence' => 'bıerz rêz',
+       'mwe-preview_insert' => 'têarêkerdeyan seyr bıker',
+       'mwe-cancel_image_insert' => 'têare kerdış ibtal bıker',
+       'mwe-sc_fileopts' => 'teferruatê klibi bıvurn',
+       'mwe-sc_inoutpoints' => 'nuqtayê destpêkerdış u qediyayişi eyar ker',
+       'mwe-sc_overlays' => 'tebeqeyi',
+       'mwe-sc_audio' => 'kontrolê vengi',
+       'mwe-sc_duration' => 'mudde/zeman',
+       'mwe-template_properties' => 'xusûsê şabloni',
+       'mwe-custom_title' => 'sernameyo xusûsi',
+       'mwe-edit_properties' => 'xusûsê vurnayişi',
+       'mwe-other_properties' => 'xusûsê bini',
+       'mwe-resource_page' => 'pelê çımeyi:',
+       'mwe-set_in_out_points' => 'noqtayê destpêkerdış u qediyayişi eyar bıker',
+       'mwe-start_time' => 'demê destpêkerdışi',
+       'mwe-end_time' => 'demê qediyayişi',
+       'mwe-preview_inout' => 'noqtayê destpêkerdış u qediyayişi seyr bıker',
+       'mwe-edit-tools' => 'Hacetanê vurnayisi',
+       'mwe-inline-description' => 'Kapsiyon',
+       'mwe-edit-video-tools' => 'Hacetanê videyo edit kerdisi',
+       'mwe-duration' => 'Sure:',
+       'mwe-upload-subs-file' => 'Nusteyê bin bar bike',
+       'mwe-add-subs-file-title' => 'Nusteye bini ke ti bar kenê ey biweçine',
+       'mwe-error-only-srt' => 'Ti teyna eşkenê dosyayê srt bar bike.',
+       'mwe-watch-video' => 'Videyo seyr bike',
+       'mwe-select-other-language' => 'Yew zIwanê bini biweçine',
+       'mwe-saving' => 'ho qeyd beno...',
+       'mwe-select_transcript_set' => 'Tebeqeyan bivecin',
+       'mwe-auto_scroll' => 'bı otomatik xıj bıker',
+       'mwe-close' => 'bıqefeln',
+       'mwe-improve_transcript' => 'dewlemend ker',
+       'mwe-no_text_tracks_found' => 'çı metın nêdiya',
+       'mwe-add-edit-subs' => 'sernameyê bine ilave/bivurne',
+       'mwe-transition_in' => 'dekewtış',
+       'mwe-transition_out' => 'teber kewtış',
+       'mwe-effects' => 'loda (kopê) efekti',
+       'mwe-remove_transition' => 'raviyertış wedar/werad',
+       'mwe-edit_transin' => 'şiyayişê klibi bıvurn',
+       'mwe-edit_transout' => 'klip ra şliyayiş bıvurn',
+       'mwe-add-transition' => 'Yew çarnayiş de bike',
+       'mwe-menu_clipedit' => 'medya bıvurn',
+       'mwe-menu_transition' => 'efekt u raviyertışi',
+       'mwe-menu_cliplib' => 'medya têarê ker',
+       'mwe-menu_resource_overview' => 'Resource overview',
+       'mwe-menu_options' => 'tercihi',
+       'mwe-loading_timeline' => 'Loading timeline ...',
+       'mwe-loading_user_rights' => 'heqê karberi bar bêni',
+       'mwe-no_edit_permissions' => 'şıma nêşkeni vuriyayişan no rêzkerdışi re qeyd bıkeri',
+       'mwe-edit_clip' => 'klib bıvurn',
+       'mwe-edit_save' => 'vuriyayişanê rêzkerdışan qeyd bıker',
+       'mwe-saving_wait' => 'qeyd kerdış dewam keno ( kerem kerê vınderê)',
+       'mwe-save_done' => 'qeyd kerdış temam bı',
+       'mwe-edit_cancel' => 'vuriyayişê rêzbiyayişi iptal bıker',
+       'mwe-edit_cancel_confirm' => 'şıma raşta wazeni vurnayişanê xo iptal ker? vuriyayişi vindibeni',
+       'mwe-zoom_in' => 'biyar nızdi (zoom ker)',
+       'mwe-zoom_out' => 'dûr ker (zoom meker)',
+       'mwe-cut_clip' => 'kliban bıqesn',
+       'mwe-expand_track' => 'reç hêra ker',
+       'mwe-collapse_track' => 'reç teng ker',
+       'mwe-play_from_position' => "bı serê xetê kaydayiş ra bıd' kaydayış",
+       'mwe-pixle2sec' => 'piksel re saniye',
+       'mwe-rmclip' => 'klib wedar/werad',
+       'mwe-clip_in' => 'zerre re klib',
+       'mwe-clip_out' => 'teber re klib',
+       'mwe-no_selected_resource' => '<h3>çı çıme nêvıciya</h3> qey aktifkerdışê vurnayişi yew klib bıvıcinê.',
+       'mwe-error_edit_multiple' => '<h3>yew ra zêd çıme vıciya</h3> qey vurnayişi yew klib bıvıcinê.',
+       'mwe-editor_options' => 'tercihê editori',
+       'mwe-editor_mode' => 'modê editori',
+       'mwe-simple_editor_desc' => "editoro basit (bı stilê imovie'yi)",
+       'mwe-advanced_editor_desc' => "editoro dewlemend (bı stilê final cut'i)",
+       'mwe-other_options' => 'tercihê bini',
+       'mwe-contextmenu_opt' => 'menuyê muhtewayan aktif bıker',
+       'mwe-sequencer_credit_line' => 'hetê <a href="http://kaltura.com">Kaltura, Inc.</a>yi ra pê ortaxiyê <a href="http://wikimediafoundation.org/wiki/Home">Wikimedia Foundation</a> (<a href="#">qey malumato zêd</a>)yi dewlemend biyo.',
+       'mwe-loading_txt' => 'bar beno...',
+       'mwe-error_load_lib' => 'xeta: $1 JavaScript re nêresiyeno ya zi pê $2yi şınasnaye niyo.',
+       'mwe-loading-add-media-wiz' => 'sihırbazê medya ardışi bar beno',
+       'mwe-apiproxy-setup' => 'proxyê APIyi eyar beno',
+       'mwe-load-drag-item' => 'unsur bar beno',
+       'mwe-ok' => 'temam',
+       'mwe-cancel' => 'iptal',
+       'mwe-setting-up-proxy' => 'proxy bar beno...',
+       'mwe-re-try' => "waştışê Retry API'yi",
+       'mwe-re-trying' => "newe ra waştışê Retry API'yi...",
+       'mwe-proxy-not-ready' => 'proxy nêvıraziyayo/ro nêniyayo',
+       'mwe-please-login' => '<a target="_new" href="$1">logged in</a> on $2 aktif nêbiyo, newe ra tesel bıkerê.',
+       'mwe-remember-loging' => 'virrardışê pawıtışê umumiyi: adresê keyepeli têna wextê cıkewetışi de aseni',
+       'fogg-select_file' => 'dosya bıweçin',
+       'fogg-select_new_file' => 'dosyaya neweyi bıweçin',
+       'fogg-select_url' => 'URL bıweçin',
+       'fogg-save_local_file' => 'Ogg qeyd bıker',
+       'fogg-check_for_firefogg' => 'Firefogg kontrol beno...',
+       'fogg-installed' => 'Firefogg bar bı',
+       'fogg-for_improved_uploads' => 'qey barkerdışê dewlemend biyayeyani:',
+       'fogg-please_install' => '<a href="$1">Firefogg bar ker</a>. <a href="http://commons.wikimedia.org/wiki/Commons:Firefogg">derheqê firefoggi de</a>',
+       'fogg-use_latest_firefox' => 'kerem kerê ewwil <a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=firefogg">Firefox 3.5</a>\'i barkerê. <i>u hema parçeyê <b>Firefogg</b> i bar kerê, qey barkerdışi no pel ziyaret bıkerê</i>',
+       'fogg-passthrough_mode' => 'dosyaya ke şıma weçina ca ra yew dosyaya Oggi ya zi videoyi niyo',
+       'fogg-transcoding' => 'Video Ogg ra kod beno',
+       'fogg-encoding-done' => 'kodkerdış temam bı',
+       'fogg-badtoken' => 'nişan qebul nêbı',
+       'fogg-preview' => 'video temaşa bıker',
+       'fogg-hidepreview' => 'temaşakerdışi bınımn',
+       'mwe-imported_from' => 'adresa $1 [$2 $3]i ra kırışt zerreyi. qey malumato zêd bıewnê [ pelê çımeyê $4 ] orjinali.',
+       'mwe-stream_title' => '$1 $2 ra $3 re',
+       'fogg-help-sticky' => 'ardim (qey dusnayişi bıtıknê)',
+       'fogg-cg-preset' => 'eyaro ver: <strong>$1</strong>',
+       'fogg-cg-quality' => 'qaliteya bıngeyın u kontrolê resolutioni',
+       'fogg-cg-meta' => 'qey klibi metadata',
+       'fogg-cg-range' => 'benatê dayişê kodkerdışi',
+       'fogg-cg-advVideo' => 'kontrolê kodkerdışê videoyi yo dewlemend biyaye',
+       'fogg-cg-advAudio' => 'kontrolê kodkerdışê vengi yo dewlemend biyaye',
+       'fogg-preset-custom' => 'eyarê xusûsiyi',
+       'fogg-webvideo-desc' => 'Videyoyê webî Theora, Vorbis 400 kbit/s and 400px veriniyê maksimumî',
+       'fogg-savebandwidth-desc' => 'Bandwithê qicî Theora, Vorbis 164 kbit/s and 200px veriniyê maksimumî',
+       'fogg-highquality-desc' => 'Qaliteyo hewl Theora, Vorbis 1080px veriniyê maximumî',
+       'fogg-videoQuality-title' => 'Qeliteyê Videyoyî',
+       'fogg-videoQuality-help' => 'Qe deşifre kerdişî videyoyî <i>qeliteyê vînayîşî</i> biron ( eka to bitrate rona, ena nihebiyeno)',
+       'fogg-starttime-title' => 'Saniye başli biker',
+       'fogg-starttime-help' => 'Teyna saniyasan ra deşîfre bike',
+       'fogg-endtime-title' => 'Saniye biqed',
+       'fogg-endtime-help' => 'Teyna saniyasan rê deşîfre bike',
+       'fogg-audioQuality-title' => 'Qeliteyê vengî',
+       'fogg-audioQuality-help' => 'Qe deşifre kerdişî videyoyî <i>qeliteyê akusticî</i> biron ( eka to bitrate rona, ena nihebiyeno)',
+       'fogg-videoCodec-title' => 'Deşifreyê videyoyî',
+       'fogg-videoCodec-help' => 'Pê ena verini de deşifreyê videyoyî weçino. Feqt nika, teyna Theora ra destek dano. Qe enformasyonê zafyerî bewne  <a target="_new" href="http://en.wikipedia.org/wiki/Theora">Theora codec</a>.',
+       'fogg-audioCodec-title' => 'Deşifreyê vengî',
+       'fogg-audioCodec-help' => 'Pê ena verini de deşifreyê vengî weçino. Feqt nika, teyna Theora ra destek dano. Qe enformasyonê zafyerî bewne  <a target="_new" href="http://en.wikipedia.org/wiki/Theora">Theora codec</a>.',
+       'fogg-width-title' => 'Veriniyê videyoyî',
+       'fogg-width-help' => 'Verinî rê reyna ebat bide',
+       'fogg-height-title' => 'Derganiyê videyoyî',
+       'fogg-height-help' => 'Derganiyê videyoyî rê reyna ebat bide.',
+       'fogg-videoBitrate-title' => 'Bitrateyê videyoyî',
+       'fogg-videoBitrate-help' => 'Bitrateyê videyoyî deşifre kerdişê videyoyî roneno (kb/s)',
+       'fogg-twopass-title' => 'Di pass deşifre',
+       'fogg-twopass-help' => 'Di pass deşifre eşkeno videyoyî zaf hewl bike.',
+       'fogg-framerate-title' => 'Ebatê çerçuveyî',
+       'fogg-framerate-help' => 'Ebatê çerçuveyî yê videyoyî. Qe enformasyonê zafyeri bewne <a target="_new" href="http://en.wikipedia.org/wiki/Frame_rate">frame rate</a>.',
+       'fogg-aspect-title' => 'Ratioyî Ebatî',
+       'fogg-aspect-help' => 'Ratioyî Ebatî teyna 4:3 ya zi 16:9 beno. Qe enformasyonê zafyeri bewne <a target="_new" href="http://en.wikipedia.org/wiki/Aspect_ratio_%28image%29">aspect ratios</a>.',
+       'fogg-keyframeInterval-title' => 'Benateyê key çerçuveyî',
+       'fogg-keyframeInterval-help' => 'Benateyê key çerçuveyî, çerçuve de. Not bike ke deşifre kerdoğanê zafyerî,  keyframe keno eka benate înan ra zaf ferqê ebatî esto. Qe enformasyonê zafyerî bewne                            <a href="http://en.wikipedia.org/wiki/I-frame">keyframes</a>.',
+       'fogg-denoise-title' => 'Filitreyê veng tey kerdişî',
+       'fogg-denoise-help' => 'Videyoyê veng tey kerdişî. Qe enformasyonê zafyerî bewne <a href="http://en.wikipedia.org/wiki/Video_denoising">denoise</a>.',
+       'fogg-novideo-title' => 'Videyo çini yo',
+       'fogg-novideo-help' => 'output de videyo biqefilne',
+       'fogg-audioBitrate-title' => 'Bitreytingê vengî',
+       'fogg-samplerate-title' => 'Reytingê vengî',
+       'fogg-samplerate-help' => 'samplerate videyoyî eyar bike (Hz de).',
+       'fogg-noaudio-title' => 'Veng çini yo',
+       'fogg-noaudio-help' => 'Vengê videyoyî biqefilne',
+       'fogg-title-title' => 'Sername',
+       'fogg-title-help' => 'Sernameyê videyoyî',
+       'fogg-artist-title' => 'Nameyê viraştoğî',
+       'fogg-artist-help' => 'Nameyê viraştoğê ena videyo',
+       'fogg-date-title' => 'Wext',
+       'fogg-date-help' => 'Wextê ke video qeyd biyo ya zi vila biyo',
+       'fogg-location-title' => 'Ca',
+       'fogg-location-help' => 'Caye ke videyo qeyd biyo',
+       'fogg-organization-title' => 'Organizasyon',
+       'fogg-organization-help' => 'Nameyê organizasyonî (studio)',
+       'fogg-copyright-title' => 'Heqa kopya',
+       'fogg-copyright-help' => 'Heqa kopyayê videyoyî',
+       'fogg-license-title' => 'Lisans',
+       'fogg-license-help' => 'Lisansê videyoyî (tercih ma yew URLê Creative Commonsî o).',
+       'fogg-contact-title' => 'Kontak',
+       'fogg-contact-help' => 'Linkê kontakî',
+       'mwe-add_media_wizard' => 'sihırbazê medyayi têarê ker',
+       'mwe-media_search' => 'cıgêrayişê medyayi',
+       'rsd_box_layout' => 'ca gınayişê qutiyi',
+       'rsd_list_layout' => 'ca gınayişê listeyi',
+       'rsd_results_desc' => '$1 rê $2î neticeyî',
+       'rsd_results_desc_total' => 'qey  $1, $2, $3 neticeyi',
+       'rsd_results_next' => 'aver',
+       'rsd_results_prev' => 'apey',
+       'rsd_no_results' => 'qey <b>$1</b>i neticeya cıgêrayişi çina',
+       'mwe-upload_tab' => 'bar ker',
+       'rsd_layout' => 'ca gınayişi:',
+       'rsd_resource_edit' => 'çımeyê vuriyayişi: $1',
+       'mwe-resource_description_page' => 'pelê çımeyi yo beyanati',
+       'mwe-link' => 'gıre',
+       'rsd_local_resource_title' => 'sernameyê çımeyi yo mehelliyi',
+       'rsd_do_insert' => 'têarêkerdış bıker',
+       'mwe-cc_by_title' => 'etıf',
+       'mwe-cc_nc_title' => 'oyo ke ticari niyo',
+       'mwe-cc_nd_title' => 'No Derivative Works',
+       'mwe-cc_sa_title' => 'bare biyayişo zepê',
+       'mwe-cc_pd_title' => 'malê umumiyi',
+       'mwe-unknown_license' => 'lisanso ke nêzaniyeno',
+       'mwe-no_import_by_url' => 'No karber ya zi wiki dûr ra URLyan ra <b>nêeşkeno</b> qezenç bıkırışo zerre.<p>Şima qayili hesabê xo akeri?</p><p>Eke desturî eyar biyê?<br /> Luzûm beno ke şıma <a href="http://www.mediawiki.org/wiki/Manual:$wgAllowCopyUploads">$wgAllowCopyUploads</a>yi aktif bıkeri.</p>',
+       'mwe-results_from' => 'qey <a href="$1" target="_new" >$2</a>yi neticeyi',
+       'mwe-missing_desc_see_source' => 'This asset is missing a description. Please see the [$1 orginal source] and help describe it.',
+       'rsd_config_error' => 'xetaya vıraştışê sihırbazê medya ardışiı: $1',
+       'mwe-your_recent_uploads' => 'Barbiyayeyê şıma yo $1 rê peyini',
+       'mwe-upload_a_file' => 'Yew dosyaya newe $1 rê bar biker',
+       'mwe-resource_page_desc' => 'beyanatê pelê çımeyi',
+       'mwe-edit_resource_desc' => 'beyanatê çımeyi yo metnê wikiyi bıvurn',
+       'mwe-local_resource_title' => 'sernameyê çımeyi yo mehelliyi',
+       'mwe-watch_this_page' => 'no pel temaşa bıker',
+       'mwe-do_import_resource' => "çıme bıd' zerre",
+       'mwe-update_preview' => 'pêştemaşa rocane bıker',
+       'mwe-cancel_import' => 'zerre dayişi iptal bıker',
+       'mwe-importing_asset' => 'Importing asset',
+       'mwe-preview_insert_resource' => 'têarêkerdış3e çımeyi pêştemaşa bıker: $1',
+       'mwe-checking-resource' => 'çıme kontrol beno',
+       'mwe-resource-needs-import' => 'Çimeyê $1yi gani zerre $2 bıdiyo',
+       'mwe-ftype-svg' => "dosyaya vektorê SVC'yi",
+       'mwe-ftype-jpg' => "dosyaya resımi ya JPEG'yi",
+       'mwe-ftype-png' => 'dosyaya resımi ya PNG',
+       'mwe-ftype-oga' => 'dosyaya vengi ya Ogg',
+       'mwe-ftype-ogg' => 'dosyaya videoyi ya Ogg',
+       'mwe-ftype-unk' => 'formatê dosyayi nêzaniyeno',
+       'rsd-wiki_commons-title' => 'Wikimediya Embar',
+       'rsd-wiki_commons' => 'Wikimediya Embar, yew arşivê ke tede free-lisans medya (resim, veng u video) est a.',
+       'rsd-this_wiki-title' => 'Ena wiki',
+       'rsd-this_wiki-desc' => 'Wikiyê lokali ronayişi',
+       'rsd-archive_org-desc' => 'Arşivê Interneti, yew kitabxaneyê dijitali ke tede maddeyanê kulturi est a.',
+       'rsd-flickr-desc' => 'Flickr.com, yew siteyê foto barkerdişi',
+       'rsd-metavid-desc' => 'Metavid.org, yew videyo arşivê meclisê DAY (Dewletê Amerikayê Yewbiyayey)',
+       'mwe-select_file' => 'dosya bıweçinê',
+       'mwe-more_licence_options' => 'qey tercihê lisansi, <a href="$1">pelê barkerdışi yo normal</a> re bıewnê',
+       'mwe-select_ownwork' => 'ez bıtemami xebatê xo bar kena, lisans zey cêrın o',
+       'mwe-licence_cc-by-sa' => 'Creative Commons bare biyayişê zepê (3.0)',
+       'mwe-upload' => 'dosya bar ker',
+       'mwe-destfilename' => 'nameyê dosyayi ya hedefi',
+       'mwe-summary' => 'bı kılmi',
+       'mwe-error_not_loggedin' => 'şıma nêkewte cı ya zi heqê şıma çino',
+       'mwe-watch-this-file' => 'Ena dosya seyr bike',
+       'mwe-ignore-any-warnings' => 'ikazan ra diqet meke',
+       'mwe-upload-transcode-in-progress' => 'newe ra kodkerdış u barkerdış dewam keno (na pencıra ramecanê)',
+       'mwe-upload-in-progress' => 'barkerdış dewam keno (na pencera ramecanê)',
+       'mwe-upload-transcoded-status' => 'newe ra kod bı',
+       'mwe-uploaded-status' => 'bar bı',
+       'mwe-upload-stats-fileprogress' => '$2 de $1',
+       'mwe-upload_completed' => 'barkerdışê şıma temam bı',
+       'mwe-upload_done' => '<a href="$1">barkerdışê şıma re resiyeno <i>olmalıdır</i></a>.',
+       'mwe-upload-unknown-size' => 'ebatê ke nêzaniyeni',
+       'mwe-cancel-confim' => 'şıma raşta qayili iptal keri?',
+       'mwe-successfulupload' => 'barkerdış bıserkewteyo',
+       'mwe-uploaderror' => 'xetaya barkerdışi',
+       'mwe-uploadwarning' => 'hişyariya barkerdışi',
+       'mwe-unknown-error' => 'xetaya ke nêzaniyeno',
+       'mwe-return-to-form' => 'agêr form',
+       'mwe-file-exists-duplicate' => 'na dosya zey dosyaya cêrına',
+       'mwe-fileexists' => 'no name de ca ra yew dosya esta. eke şıma emin niê bıvurni, kerem kerê <b><tt>$1</tt></b> kontrol bıkerê.',
+       'mwe-fileexists-thumb' => '<center><b>dosyaya mewcud</b></center>',
+       'mwe-ignorewarning' => 'goş hişyariya mekuwi u dosya newe ra bar bıker',
+       'mwe-file-thumbnail-no' => 'nameyê dosyayi pê <b><tt>$1</tt></b> destpêkeno',
+       'mwe-go-to-resource' => 'şo pelê çımeyi',
+       'mwe-upload-misc-error' => 'xetaya barkerdışi yo ke nêzaniyeno',
+       'mwe-wgfogg_warning_bad_extension' => 'dosyaya ke şıma vıcina parçeyê aye re destek çino (<a href="http://commons.wikimedia.org/wiki/Commons:Firefogg#Supported_File_Types">qey malumato zêd</a>).',
+       'mwe-upload-multi' => '{{PLURAL:$1|dosya|dosyayan}} bar bike',
+       'mwe-review-upload' => '{{PLURAL:$1|bar biyayen|bar biyayenan}} kontrol bike',
+       'mwe-credit-title' => 'Sername: $1',
+       'mwe-loading_plugin' => 'loading plugin ...',
+       'mwe-select_playback' => 'tercihê kaydayişi eyar ker',
+       'mwe-link_back' => "tepiya agêrayiş re gıre bıd'",
+       'mwe-error_swap_vid' => "xeta: qey mv_embed, mv_embed'i etiketê videoyi nêşkeno teqas bıkero",
+       'mwe-add_to_end_of_sequence' => 'bıerz peyni rêz',
+       'mwe-missing_video_stream' => 'qey no herikyayişi dosyaya videoyi nêaseno',
+       'mwe-play_clip' => 'klib bıde kaykerdış',
+       'mwe-pause_clip' => 'klib bıde vındertış',
+       'mwe-volume_control' => 'kontrolê vengi',
+       'mwe-player_options' => 'tercihê palyeri',
+       'mwe-closed_captions' => 'Nusteyê bin',
+       'mwe-player_fullscreen' => 'Tam ekran',
+       'mwe-next_clip_msg' => 'klibo bin bıde kaykerdış',
+       'mwe-prev_clip_msg' => 'klibo verin bıde kaykerdış',
+       'mwe-current_clip_msg' => 'kaykerdışê no klibi re dewam bıker',
+       'mwe-seek_to' => 'Şo muddet ser $1',
+       'mwe-paused' => 'vındarnaye',
+       'mwe-download_segment' => 'tercihi biyar war',
+       'mwe-download_full' => 'dosyaya videoyi ya tam biyar war',
+       'mwe-download_right_click' => 'qey wari ardışi, raşt bıtıknê u <i>Hedef bıferq qeyd ker...</i> bıtıknê',
+       'mwe-download_clip' => 'video biyar war',
+       'mwe-download_text' => 'Metn biyar war (<a style="color:white" title="cmml" href="http://wiki.xiph.org/index.php/CMML">CMML</a> xml):',
+       'mwe-download' => 'biyar war',
+       'mwe-share' => 'par/bare bıker',
+       'mwe-credits' => 'êyê ke destek dayê',
+       'mwe-clip_linkback' => 'pelê çımeyi yo klibi',
+       'mwe-chose_player' => 'video player bıweçin',
+       'mwe-share_this_video' => 'na video bare/par bıker',
+       'mwe-video_credits' => 'êyê ke destek dayê video',
+       'mwe-menu_btn' => 'menu',
+       'mwe-close_btn' => 'bıqefeln',
+       'mwe-ogg-player-vlc-player' => 'Kay kerdogê VLC',
+       'mwe-ogg-player-videoElement' => 'Destekê Ogg videoyi yo mehelli',
+       'mwe-ogg-player-oggPlugin' => 'Generic Ogg plugin',
+       'mwe-ogg-player-quicktime-mozilla' => 'QuickTime plugin',
+       'mwe-ogg-player-quicktime-activex' => 'QuickTime ActiveX',
+       'mwe-ogg-player-cortado' => 'Java Cortado',
+       'mwe-ogg-player-flowplayer' => 'Flowplayer',
+       'mwe-ogg-player-kplayer' => 'Kaykerdoğê kaltura',
+       'mwe-ogg-player-selected' => '(tercih biyaye)',
+       'mwe-ogg-player-omtkplayer' => 'OMTK Flash Vorbis',
+       'mwe-generic_missing_plugin' => 'wina aseno ke cıgêrayoxê şıma nê tipê kaydayişan re destek nêdano: <b>$1</b><br />qey war ardışê playereki<a href="http://commons.wikimedia.org/wiki/Commons:Media_help">metodê kaydayişi</a> ziyaret bıkerê.<br />',
+       'mwe-for_best_experience' => 'şıma wazenî hema/hona yew video playero rınd bıxebıtni tewsiyeya ma:<br /><b><a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=mwEmbed">Firefox 3.5</a>.</b>',
+       'mwe-do_not_warn_again' => 'ına hal caverdê',
+       'mwe-playerselect' => 'Playeri',
+       'mwe-read_before_embed' => 'kerem kerê verê nımıtışi <a href="http://mediawiki.org/wiki/Security_Notes_on_Remote_Embedding" target="_new">derheqê dûr ra nımıtışi de malumatê pawıtışan</a> bıwenê!',
+       'mwe-embed_site_or_blog' => 'Zerreyê keyepel u blogê xo de bınımnê',
+       'mwe-related_videos' => 'videoyê ke elaqedari',
+       'mwe-seeking' => 'cıgêrayox',
+       'mwe-copy-code' => 'Kodê kopya',
+);
+
+/** Lower Sorbian (Dolnoserbski)
+ * @author Michawiki
+ */
+$messages['dsb'] = array(
+       'mwe-crop' => 'Wobraz wobrězaś',
+       'mwe-apply_crop' => 'Wobrězanje na wobraz nałožyś',
+       'mwe-reset_crop' => 'Wobrězanje anulěrowaś',
+       'mwe-insert_image_page' => 'Do boka zasajźiś',
+       'mwe-insert_into_sequence' => 'Do sekwence zasajźiś',
+       'mwe-preview_insert' => 'Pséglěd zasajźenja',
+       'mwe-cancel_image_insert' => 'Zasajźenje pśetergnuś',
+       'mwe-sc_fileopts' => 'Wobźěłanje klipowych drobnostkow',
+       'mwe-sc_inoutpoints' => 'Zachopne-kóńcne dypki stajiś',
+       'mwe-sc_overlays' => 'Pśewarstowanja',
+       'mwe-sc_audio' => 'Awdioregulěrowanje',
+       'mwe-sc_duration' => 'Cas',
+       'mwe-template_properties' => 'Kakosći pśedłogi',
+       'mwe-custom_title' => 'Swójski titel',
+       'mwe-edit_properties' => 'Kakosći wobźěłaś',
+       'mwe-other_properties' => 'Druge kakosći',
+       'mwe-resource_page' => 'Resursowy bok:',
+       'mwe-set_in_out_points' => 'Zachopne-kóńcne dypki stajiś',
+       'mwe-start_time' => 'Zachopny cas',
+       'mwe-end_time' => 'Kóńcny cas',
+       'mwe-preview_inout' => 'Zachopne-kóńcne dypki ako pśeglěd pokazaś',
+       'mwe-edit-tools' => 'Wobźěłowańske rědy',
+       'mwe-inline-description' => 'Nadpismo',
+       'mwe-edit-video-tools' => 'Rědy za wobźěłowanje wideo:',
+       'mwe-duration' => 'Cas:',
+       'mwe-upload-subs-file' => 'Pódtitel nagraś',
+       'mwe-add-subs-file-title' => 'Pódtitel za nagraśe wubraś',
+       'mwe-error-only-srt' => 'Jano srt-dataje daju se direktnje nagraś.',
+       'mwe-watch-video' => 'Wideo se woglědaś',
+       'mwe-select-other-language' => 'Drugu rěc wubraś',
+       'mwe-saving' => 'składujo se...',
+       'mwe-select_transcript_set' => 'Pódtitele wubraś',
+       'mwe-auto_scroll' => 'awtomatiski kulaś',
+       'mwe-close' => 'zacyniś',
+       'mwe-improve_transcript' => 'Pólěpšyś',
+       'mwe-no_text_tracks_found' => 'Žedne tekstowe cery namakane',
+       'mwe-add-edit-subs' => 'Pódtitele pśidaś/wobźěłaś',
+       'mwe-transition_in' => 'Zablendowanje',
+       'mwe-transition_out' => 'Wublendowanje',
+       'mwe-effects' => 'Skład efektow',
+       'mwe-remove_transition' => 'Pśechad wótpóraś',
+       'mwe-edit_transin' => 'Zablendowanje do klipa wobźěłaś',
+       'mwe-edit_transout' => 'Wublendowanje z klipa wobźěłaś',
+       'mwe-add-transition' => 'Pśechad pśidaś',
+       'mwe-menu_clipedit' => 'Medije wobźěłaś',
+       'mwe-menu_transition' => 'Pśechady a efekty',
+       'mwe-menu_cliplib' => 'Medije pśidaś',
+       'mwe-menu_resource_overview' => 'Pśeglěd resursow',
+       'mwe-menu_options' => 'Opcije',
+       'mwe-loading_timeline' => 'Casowu ceru zacytaś ...',
+       'mwe-loading_user_rights' => 'Wužywarske pšawa se zacytuju ...',
+       'mwe-no_edit_permissions' => 'Njamaš pšawa, aby změny na toś tej sekwency składował.',
+       'mwe-edit_clip' => 'Klip wobźěłaś',
+       'mwe-edit_save' => 'Sekwencowe změny składowaś',
+       'mwe-saving_wait' => 'Składujo se rowno (pšosym cakaj)',
+       'mwe-save_done' => 'Składowanje dokóńcone',
+       'mwe-edit_cancel' => 'Wobźěłanje sekwence pśetergnuś',
+       'mwe-edit_cancel_confirm' => 'Coš napšawdu swójo wobźěłanje pśetergnuś? Změny se zgubiju.',
+       'mwe-zoom_in' => 'Pówětšyś',
+       'mwe-zoom_out' => 'Pómjeńšyś',
+       'mwe-cut_clip' => 'Klipy stśigaś',
+       'mwe-expand_track' => 'Ceru wuklapnuś',
+       'mwe-collapse_track' => 'Ceru złožyś',
+       'mwe-play_from_position' => 'Wót pozicije wótegraś',
+       'mwe-pixle2sec' => 'piksele do sekundow',
+       'mwe-rmclip' => 'Klip wótpóraś',
+       'mwe-clip_in' => 'Klip pśidaś',
+       'mwe-clip_out' => 'Klip wótpóraś',
+       'mwe-no_selected_resource' => '<h3>Žedna resursa wubrana</h3> Wubjeŕ klip, aby zmóžnił wobźěłowanje.',
+       'mwe-error_edit_multiple' => '<h3>Někotare resurse wubrane</h3> Wubjeŕ jadnotliwy klip, aby jen wobźěłał.',
+       'mwe-editor_options' => 'Editorowe opcije',
+       'mwe-editor_mode' => 'Editorowy modus',
+       'mwe-simple_editor_desc' => 'jadnory editor (stil iMovie)',
+       'mwe-advanced_editor_desc' => 'rozšyrjony editor (stil Final Cut)',
+       'mwe-other_options' => 'Druge opcije',
+       'mwe-contextmenu_opt' => 'Kontekstowe menije zmóžniś',
+       'mwe-sequencer_credit_line' => 'Wuwity wót <a href="http://kaltura.com">Kaltura, Inc.</a> gromaźe ze załožbu <a href="http://wikimediafoundation.org/wiki/Home">Wikimedia Foundation</a> (<a href="#">dalšne informacije</a>).',
+       'mwe-loading_txt' => 'zacytujo se ...',
+       'mwe-error_load_lib' => 'Zmólka: JavaScript $1 njejo wótwołujobny był abo njedefiněrujo $2',
+       'mwe-loading-add-media-wiz' => 'Zacytujo se asistent za pśidaśe medijow',
+       'mwe-apiproxy-setup' => 'Proksy API zarědowaś',
+       'mwe-load-drag-item' => 'Wlecony zapisk se zacytujo',
+       'mwe-ok' => 'W pórědku',
+       'mwe-cancel' => 'Pśetergnuś',
+       'mwe-setting-up-proxy' => 'Proksy se pśihotujo...',
+       'mwe-re-try' => 'Napšašowanje API wóspjetowaś',
+       'mwe-re-trying' => 'Napšašowanje API so wóspjetujo...',
+       'mwe-proxy-not-ready' => 'Proksy njejo konfigěrowany',
+       'mwe-please-login' => 'Njejsy na $2 <a target="_new" href="$1">pśizjawjony</a> abo mwEmbed njejo zmóžnjony. Rozwěž tuś ten problem a wóspjetuj pótom napšašowanje.',
+       'mwe-remember-loging' => 'Powšykne wěstotne dopominanje: Pśizjaw se jano na websedłach, gaž twójo adresowe pólo zwobraznjujo adresu togo sedła.',
+       'fogg-select_file' => 'Dataju wubraś',
+       'fogg-select_new_file' => 'Nowu dataju wubraś',
+       'fogg-select_url' => 'URL wubraś',
+       'fogg-save_local_file' => 'Ogg składowaś',
+       'fogg-check_for_firefogg' => 'Za Firefogg pśeglědaś ...',
+       'fogg-installed' => 'Firefogg jo instalěrowany.',
+       'fogg-for_improved_uploads' => 'Za pólěpšone nagraśa:',
+       'fogg-please_install' => '<a href="$1">Firefogg instalěrowaś</a>. Wjace <a href="http://commons.wikimedia.org/wiki/Commons:Firefogg">wó Firefogg</a>',
+       'fogg-use_latest_firefox' => 'Pšosym instalěruj njepjerwjej <a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=firefogg">Firefox 3.5</a> (abo wuši). <i>Woglědaj pótom k toś tomu bokoju zasego, aby rozšyrjenje <b>Firefogg</b> instalěrował.</i>',
+       'fogg-passthrough_mode' => 'Twója wubrana dataja jo južo dataja Ogg abo njejo wideojowa dataja',
+       'fogg-transcoding' => 'Wideo do Ogg koděrowaś',
+       'fogg-encoding-done' => 'Koděrowanje skóńcone',
+       'fogg-badtoken' => 'Token njejo płaśiwy',
+       'fogg-preview' => 'Pśeglěd wideo pokazaś',
+       'fogg-hidepreview' => 'Pśeglěd schowaś',
+       'mwe-imported_from' => '$1 jo z [$2 $3] importěrował. Glědaj originalny [$4 resursowy bok] za dalšne informacije.',
+       'mwe-stream_title' => '$1 $2 do $3',
+       'fogg-help-sticky' => 'Pomoc (pśez kliknjenje pśicyniś)',
+       'fogg-cg-preset' => 'Do togo nastajony: <strong>$1</strong>',
+       'fogg-cg-quality' => 'Zakładna kwalita a regulěrowanje rozeznaśa',
+       'fogg-cg-meta' => 'Metadaty za klip',
+       'fogg-cg-range' => 'Koděrowański wobcerk',
+       'fogg-cg-advVideo' => 'Rozšyrjone nastajenja za wideokoděrowanje',
+       'fogg-cg-advAudio' => 'Rozšyrjone nastajenja za awdiokoděrowanje',
+       'fogg-preset-custom' => 'Swójske nastajenja',
+       'fogg-webvideo-desc' => 'Webwideo Theora, Vorbis 400 kbit/s a 400 pks. maksimalna šyrokosć',
+       'fogg-savebandwidth-desc' => 'Theora niskeje šyroskosći pasma, Vorbis 164 kbit/s a 200 pks. maksimalna šyrokosć',
+       'fogg-highquality-desc' => 'Theora wusokeje kwality, Vorbis 1080 pks. maksimalna šyrokosć',
+       'fogg-videoQuality-title' => 'Wideokwalita',
+       'fogg-videoQuality-help' => 'Wužywa se, aby se <i>wizuelna kwalita</i> koděrowanego wideo (njewužywa se, jolic dołojce nastajaš bitowu ratu w rozšyrjonem meniju).',
+       'fogg-starttime-title' => 'Startowa sekunda',
+       'fogg-starttime-help' => 'Jano wót casa w sekundach koděrowaś',
+       'fogg-endtime-title' => 'Kóńcna sekunda',
+       'fogg-endtime-help' => 'Jano do casa w sekundach koděrowaś',
+       'fogg-audioQuality-title' => 'Awdiokwalita',
+       'fogg-audioQuality-help' => 'Wužywa se, aby se <i>akustiska kwalita</i> koděrowanego awdio (njewužywa se, jolic dołojce nastajaš bitowu ratu w rozšyrjonem meniju).',
+       'fogg-videoCodec-title' => 'Wideokodek',
+       'fogg-videoCodec-help' => 'Wužywa se, aby se wideokodek klipa wubrał. Tuchylu se jano Theora pódpěra. <a target="_new" href="http://en.wikipedia.org/wiki/Theora">Wěcej wó kodeku Theora</a>.',
+       'fogg-audioCodec-title' => 'Awdiokodek',
+       'fogg-audioCodec-help' => 'wužywa se, aby se awdiokodeka klipa nastajił. Tuchylu se jano Vorbis pódpěra. More about the <a target="_new" href="http://en.wikipedia.org/wiki/Vorbis">Wěcej wó kodeku Vorbis</a>.',
+       'fogg-width-title' => 'Šyrokosć wideo',
+       'fogg-width-help' => 'Na pódanu šyrokosć skalěrowaś.',
+       'fogg-height-title' => 'Wusokosć wideo',
+       'fogg-height-help' => 'Na pódanu wusokosć skalěrowaś',
+       'fogg-videoBitrate-title' => 'Bitowa rata wideo',
+       'fogg-videoBitrate-help' => 'Bitowa rata wideo nastaja koděrowańsku bitowu ratu za wideo (w kb/s)',
+       'fogg-twopass-title' => 'Koděrowanje w dwěma kšacoma',
+       'fogg-twopass-help' => 'Koděrowanje w dwěma kšacoma zmóžnijo konstantnjejšu kwalitu pśez dwarazowe pśeźěłowanje wideodataje.',
+       'fogg-framerate-title' => 'Wobrazowa frekwenca',
+       'fogg-framerate-help' => 'Wobrazowa frekwenca wideo. <a target="_new" href="http://en.wikipedia.org/wiki/Frame_rate">Wěcej wó wobrazowej frekwency</a>.',
+       'fogg-aspect-title' => 'Wobrazowy poměr',
+       'fogg-aspect-help' => 'Wobrazowy poměr wideo móžo 4:3 abo 16:9 byś. <a target="_new" href="http://en.wikipedia.org/wiki/Aspect_ratio_%28image%29">Wěcej wó wobrazowych poměrach</a>.',
+       'fogg-keyframeInterval-title' => 'Interwal klucowych wobrazow',
+       'fogg-keyframeInterval-help' => 'Interwal klucowych wobrazow we wobrazach. Glědaj: Nejwěcej kodekow wunuźiju klucowe wobraze, jolic rozdźěl mjazy wobrazami jo wětšy ako koděrowańska wjelikosć klucowego wobraza. <a href="http://en.wikipedia.org/wiki/I-frame">Wěcej wó klucowych wobrazach</a>.',
+       'fogg-denoise-title' => 'Filter pśeśiwo šumjenjeju',
+       'fogg-denoise-help' => 'Šumjenje wideo wótpóraś. <a href="http://en.wikipedia.org/wiki/Video_denoising">Wěcej wó wótpóranju šumjenja</a>.',
+       'fogg-novideo-title' => 'Žedne wideo',
+       'fogg-novideo-help' => 'wideo we wudaśu znjemóžniś',
+       'fogg-audioBitrate-title' => 'Bitowa rata awdio',
+       'fogg-samplerate-title' => 'Wóttastowańska frekwenca awdio',
+       'fogg-samplerate-help' => 'wóttastowańsku frekwencu za wudaśe nastajiś (w Hz)',
+       'fogg-noaudio-title' => 'Žedne awdio',
+       'fogg-noaudio-help' => 'awdio we wudaśu znjemóžniś',
+       'fogg-title-title' => 'Titel',
+       'fogg-title-help' => 'Titel za twój klip',
+       'fogg-artist-title' => 'Mě awtora',
+       'fogg-artist-help' => 'Awtor toś togo klipa',
+       'fogg-date-title' => 'Datum',
+       'fogg-date-help' => 'Datum, gaž nawjerśenje jo se napórało abo wózjawiło',
+       'fogg-location-title' => 'Městno',
+       'fogg-location-help' => 'Městno nawjerśenja',
+       'fogg-organization-title' => 'Organizacija',
+       'fogg-organization-help' => 'Mě organizacije (studijo)',
+       'fogg-copyright-title' => 'Awtorske pšawo',
+       'fogg-copyright-help' => 'Awtorske pšawo klipa',
+       'fogg-license-title' => 'Licenca',
+       'fogg-license-help' => 'Licenca klipa (pśedewšym URL Creative Commons).',
+       'fogg-contact-title' => 'Kontakt',
+       'fogg-contact-help' => 'Kontaktowy wótkaz',
+       'mwe-add_media_wizard' => 'Medijowy asistent pśidaś',
+       'mwe-media_search' => 'Medijowe pytanje',
+       'rsd_box_layout' => 'Kašćikowe wugótowanje',
+       'rsd_list_layout' => 'Lisćinowe wugótowanje',
+       'rsd_results_desc' => 'Wuslědki $1 do $2',
+       'rsd_results_desc_total' => 'Wuslědki $1 do $2 z $3',
+       'rsd_results_next' => 'dalej',
+       'rsd_results_prev' => 'pjerwjejšny',
+       'rsd_no_results' => 'Žedne pytańske wuslědki za <b>$1</b>',
+       'mwe-upload_tab' => 'Nagraś',
+       'rsd_layout' => 'Wugótowanje:',
+       'rsd_resource_edit' => 'Resursu wobźěłaś: $1',
+       'mwe-resource_description_page' => 'Wopisański bok resurse',
+       'mwe-link' => 'wótkaz',
+       'rsd_local_resource_title' => 'Titel lokalneje resurse',
+       'rsd_do_insert' => 'Zasajźiś',
+       'mwe-cc_by_title' => 'Pśipokazanje',
+       'mwe-cc_nc_title' => 'Njekomercielny',
+       'mwe-cc_nd_title' => 'Žedne wótwóźone źěła',
+       'mwe-cc_sa_title' => 'Pó rownych źělach',
+       'mwe-cc_pd_title' => 'Zjawnosći pśistupny',
+       'mwe-unknown_license' => 'Njeznata licenca',
+       'mwe-no_import_by_url' => 'Toś ten wužywaŕ <b>njamóžo</b> resurse ze zdalonych URL importěrowaś.<p>Musyš se pśizjawiś?</p><p>Jo pšawo uload_by_url za tebje nastajone?<br />Ma wiki <a href="http://www.mediawiki.org/wiki/Manual:$wgAllowCopyUploads">$wgAllowCopyUploads</a> zmóžnjony?</p>',
+       'mwe-results_from' => 'Wuslědki z <a href="$1" target="_new" >$2</a>',
+       'mwe-missing_desc_see_source' => 'Toś ta resursa njama wopisanje. Pšosym glědaj [$1 orginalne žrědło] a pomož ju wopisaś.',
+       'rsd_config_error' => 'Konfiguracisku zmólku medijowego asistenta pśidaś: $1',
+       'mwe-your_recent_uploads' => 'Twóje aktualne nagraśa do $1',
+       'mwe-upload_a_file' => 'Nowu dataju do $1 nagraś',
+       'mwe-resource_page_desc' => 'Wopsianje resursowego boka:',
+       'mwe-edit_resource_desc' => 'Wopisanje wikitekstoweje resurse wobźěłaś:',
+       'mwe-local_resource_title' => 'Titel lokalneje resurse:',
+       'mwe-watch_this_page' => 'Toś ten bok wobglědowaś',
+       'mwe-do_import_resource' => 'Resursu importěrowaś',
+       'mwe-update_preview' => 'Pśeglěd aktualizěrowaś',
+       'mwe-cancel_import' => 'Importěrowanje pśetergnuś',
+       'mwe-importing_asset' => 'Resursa se importěrujo',
+       'mwe-preview_insert_resource' => 'Pśeglěd zasajźenja resurse: $1',
+       'mwe-checking-resource' => 'Pyta se resursa',
+       'mwe-resource-needs-import' => 'Resursa $1 musy se do $2 importěrowaś',
+       'mwe-ftype-svg' => 'Wektorowa dataja SVG',
+       'mwe-ftype-jpg' => 'Wobrazowa dataja JPEG',
+       'mwe-ftype-png' => 'Wobrazowa dataja PNG',
+       'mwe-ftype-oga' => 'Awdiodataja Ogg',
+       'mwe-ftype-ogg' => 'Wideodataja Ogg',
+       'mwe-ftype-unk' => 'Njeznaty datajowy format',
+       'rsd-wiki_commons-title' => 'Wikimedija Commons',
+       'rsd-wiki_commons' => 'Wikimedija Commons, archiw licho licencěrowanego wopśimjeśa wucbnych medijow (wobraze, awdiomaterial a wideoklipy)',
+       'rsd-this_wiki-title' => 'Toś ten wiki',
+       'rsd-this_wiki-desc' => 'Instalacija lokalnego wikija',
+       'rsd-archive_org-desc' => 'Internetny archiw, digitalna biblioteka kulturnych twórbow',
+       'rsd-flickr-desc' => 'Flickr.com, websedło za zgromadne wužywanje fotow',
+       'rsd-metavid-desc' => 'Metavid.org, zgromaźeństwowy archiw protokolow pósejźenja Doma wótpósłanych a Senata USA',
+       'mwe-select_file' => 'Dataju wubraś',
+       'mwe-more_licence_options' => 'Za dalšne licencowe opcije glědaj <a href="$1">normalny bok nagraśow</a>',
+       'mwe-select_ownwork' => 'Nagrawam dopołnje swójo źěło a licencěrujom jo pód:',
+       'mwe-licence_cc-by-sa' => 'Creative Commons Share Alike (3.0)',
+       'mwe-upload' => 'Dataju nagraś',
+       'mwe-destfilename' => 'Mě celoweje dataje:',
+       'mwe-summary' => 'Zespominanje',
+       'mwe-error_not_loggedin' => 'Zda se, až njejsy pśizjawjony abo njamaš nagraśowe pšawa.',
+       'mwe-watch-this-file' => 'Toś tu dataju wobglědowaś',
+       'mwe-ignore-any-warnings' => 'Warnowanja ignorěrowaś',
+       'mwe-upload-transcode-in-progress' => 'Pśekoděrowanje a nagraśe se rowno wótměwatej (njezacyń toś to wokno)',
+       'mwe-upload-in-progress' => 'Nagraśe se rowno stawa (njezacyń toś to wokno)',
+       'mwe-upload-transcoded-status' => 'Pśekoděrowany',
+       'mwe-uploaded-status' => 'Nagraty',
+       'mwe-upload-stats-fileprogress' => '$1 z $2',
+       'mwe-upload_completed' => 'Twójo nagraśe jo dokóńcone.',
+       'mwe-upload_done' => '<a href="$1">Twójo nagraśe <i>by měło</i> pśistupny byś</a>.',
+       'mwe-upload-unknown-size' => 'Njeznata wjelikosć',
+       'mwe-cancel-confim' => 'Coš napšawdu pśetergnuś?',
+       'mwe-successfulupload' => 'Nagraśe wuspěšne',
+       'mwe-uploaderror' => 'Nagrawańska zmólka',
+       'mwe-uploadwarning' => 'Nagrawańske warnowanje',
+       'mwe-unknown-error' => 'Njeznata zmólka:',
+       'mwe-return-to-form' => 'K formularoju se wrośiś',
+       'mwe-file-exists-duplicate' => 'Toś ta dataja jo duplikat slědujuceje dataje:',
+       'mwe-fileexists' => 'Dataja z toś tym mjenim južo eksistěrujo. Pšosym skontrolěruj <b><tt>$1</tt></b>, jolic njejsy wěsty, lěc coš ju změniś.',
+       'mwe-fileexists-thumb' => '<center><b>Eksistěrujuca dataja</b></center>',
+       'mwe-ignorewarning' => 'Warnowanje ignorěrowaś a dataju weto składowaś.',
+       'mwe-file-thumbnail-no' => 'Datajowe mě zachopina se z <b><tt>$1</tt></b>',
+       'mwe-go-to-resource' => 'K resursowemu bokoju',
+       'mwe-upload-misc-error' => 'Njeznata nagrawańska zmólka',
+       'mwe-wgfogg_warning_bad_extension' => 'Sy wubrał dataju z njepódpěranym rozšyrjenim (<a href="http://commons.wikimedia.org/wiki/Commons:Firefogg#Supported_File_Types">dalšne informacije</a>).',
+       'mwe-upload-multi' => '{{PLURAL:$1|Dataju|Dataji|Dataje|Dataje}} nagraś',
+       'mwe-review-upload' => '{{PLURAL:$1|Datajowe nagraśe|Datajowej nagraśi|Datajowe nagraśa|Datajowe nagraśa}} pśeglědaś',
+       'mwe-credit-title' => 'Titel: $1',
+       'mwe-loading_plugin' => 'Tykac se zacytujo ...',
+       'mwe-select_playback' => 'Nastajenje za playback stajiś',
+       'mwe-link_back' => 'Wótkaz slědk',
+       'mwe-error_swap_vid' => 'Zmólka: mv_embed njejo mógał wideotoflicku za pówjerch mv_embed wuměstniś',
+       'mwe-add_to_end_of_sequence' => 'Kóńcoju sekwence pśidaś',
+       'mwe-missing_video_stream' => 'Wideowa dataja za toś tu tšugu felujo',
+       'mwe-play_clip' => 'Klip wótegraś',
+       'mwe-pause_clip' => 'Klip zastajiś',
+       'mwe-volume_control' => 'Regulěrowanje głosnosći',
+       'mwe-player_options' => 'Opcije wótegrawaka',
+       'mwe-closed_captions' => 'Pódtitele',
+       'mwe-player_fullscreen' => 'Połna wobrazowka',
+       'mwe-next_clip_msg' => 'Pśiducy klip wótegraś',
+       'mwe-prev_clip_msg' => 'Pjerwjejšny klip wótegraś',
+       'mwe-current_clip_msg' => 'Klip dalej wótegraś',
+       'mwe-seek_to' => '$1 pytaś',
+       'mwe-paused' => 'zastajony',
+       'mwe-download_segment' => 'Wuběrk ześěgnuś:',
+       'mwe-download_full' => 'Dopołnu wideowu dataju ześěgnuś:',
+       'mwe-download_right_click' => 'Aby ześěgnuł, klikni z pšaweju tastu a wubjeŕ <i>Wótkaz składowaś ako...</i>',
+       'mwe-download_clip' => 'Wideo ześěgnuś',
+       'mwe-download_text' => 'Tekst (<a style="color:white" title="cmml" href="http://wiki.xiph.org/index.php/CMML">CMML</a> xml) ześěgnuś:',
+       'mwe-download' => 'Ześěgnuś',
+       'mwe-share' => 'Źěliś',
+       'mwe-credits' => 'Źěkowanje',
+       'mwe-clip_linkback' => 'Žrědłowy bok klipow',
+       'mwe-chose_player' => 'Wideowótegrawak wubraś',
+       'mwe-share_this_video' => 'Toś to wideo źěliś',
+       'mwe-video_credits' => 'Źěkowanja za napóranje wideo',
+       'mwe-menu_btn' => 'Meni',
+       'mwe-close_btn' => 'Zacyniś',
+       'mwe-ogg-player-vlc-player' => 'Grajadło VLC',
+       'mwe-ogg-player-videoElement' => 'Wideo native Ogg',
+       'mwe-ogg-player-oggPlugin' => 'Tykac Generic Ogg',
+       'mwe-ogg-player-quicktime-mozilla' => 'Tykac QuickTime',
+       'mwe-ogg-player-quicktime-activex' => 'ActiveX QuickTime',
+       'mwe-ogg-player-cortado' => 'Java Cortado',
+       'mwe-ogg-player-flowplayer' => 'Flowplayer',
+       'mwe-ogg-player-kplayer' => 'Grajadło Kaltura',
+       'mwe-ogg-player-selected' => '(wubrany)',
+       'mwe-ogg-player-omtkplayer' => 'OMTK Flash Vobis',
+       'mwe-generic_missing_plugin' => 'Zda se, až twój wobglědowak njepódpěra slědujucy playbackowy typ: <b>$1</b><br />Wóglědaj se bok wó <a href="http://commons.wikimedia.org/wiki/Commons:Media_help">metodach playbacka</a>, aby ześěgnuł wótegrajadło.<br />',
+       'mwe-for_best_experience' => 'Za lěpše dožywjenje wideoplaybacka pórucujomy:<br /><b><a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=mwEmbed">Firefox 3.5</a>.</b>',
+       'mwe-do_not_warn_again' => 'Tenraz zachyśiś.',
+       'mwe-playerselect' => 'Wótegrawaki',
+       'mwe-read_before_embed' => 'Pšosym cytaj <a href="http://mediawiki.org/wiki/Security_Notes_on_Remote_Embedding" target="_new">wěstotne pśipiski wó zdalonem zasajźenju</a>, nježli až napšawdu zasajźujoš!',
+       'mwe-embed_site_or_blog' => 'Na boku zasajźiś',
+       'mwe-related_videos' => 'Pśiwuzne wideo',
+       'mwe-seeking' => 'pyta se',
+       'mwe-copy-code' => 'Kod kopěrowaś',
+       'mwe-video-h264' => 'Wideo H.264',
+       'mwe-video-flv' => 'Wideo Flash',
+       'mwe-video-ogg' => 'Ogg-wideo',
+       'mwe-video-audio' => 'Ogg-awdio',
+);
+
+/** Greek (Ελληνικά)
+ * @author Crazymadlover
+ * @author Omnipaedista
+ * @author ZaDiak
+ */
+$messages['el'] = array(
+       'mwe-crop' => 'Διαχωρισμός εικόνας',
+       'mwe-apply_crop' => 'Εφαρμογή διαχωρισμού στην εικόνα',
+       'mwe-reset_crop' => 'Επαναφορά διαχωρισμού',
+       'mwe-insert_image_page' => 'Εισαγωγή στη σελίδα',
+       'mwe-insert_into_sequence' => 'Εισαγωγή στην ακολουθία',
+       'mwe-preview_insert' => 'Προεπισκόπηση εισαγωγής',
+       'mwe-cancel_image_insert' => 'Ακύρωση εισαγωγής',
+       'mwe-sc_fileopts' => 'Σύνδεση λεπτομερειών επεξεργασίας',
+       'mwe-sc_inoutpoints' => 'Ρύθμιση μέσα-έξω πόντων',
+       'mwe-sc_overlays' => 'Επικαλύψεις',
+       'mwe-sc_audio' => 'Διαχείριση ήχου',
+       'mwe-sc_duration' => 'Διάρκεια',
+       'mwe-template_properties' => 'Ιδιότητες προτύπου',
+       'mwe-custom_title' => 'Συνήθης τίτλος',
+       'mwe-edit_properties' => 'Επεξεργασία ιδιοτήτων',
+       'mwe-other_properties' => 'Άλλες ιδιότητες',
+       'mwe-resource_page' => 'Σελίδα πηγής:',
+       'mwe-set_in_out_points' => 'Ρύθμιση μέσα-έξω πόντων',
+       'mwe-start_time' => 'Χρόνος εκκίνησης',
+       'mwe-end_time' => 'Χρόνος λήξης',
+       'mwe-preview_inout' => 'Προεπισκόπηση των σημείων εισόδου-εξόδου',
+       'mwe-select_transcript_set' => 'Επιλογή στρωμάτων',
+       'mwe-auto_scroll' => 'αυτόματο κυλίνδρισμα',
+       'mwe-close' => 'κλείσιμο',
+       'mwe-improve_transcript' => 'Βελτίωση',
+       'mwe-transition_in' => 'Ταχύτητα μέσα',
+       'mwe-transition_out' => 'Ταχύτητα έξω',
+       'mwe-remove_transition' => 'Αφαίρεση ταχύτητας',
+       'mwe-menu_clipedit' => 'Επεξεργασία μέσου',
+       'mwe-menu_cliplib' => 'Προσθήκη μέσου',
+       'mwe-menu_resource_overview' => 'Επισκόπηση πηγής',
+       'mwe-menu_options' => 'Επιλογές',
+       'mwe-loading_timeline' => 'Φορτώνει η χρονολογία ...',
+       'mwe-loading_user_rights' => 'Φορτώνουν τα δικαιώματα χρήστη ...',
+       'mwe-edit_clip' => 'Επεξεργασία κλιπ',
+       'mwe-edit_save' => 'Αποθήκευση αλλαγών ακολουθίας',
+       'mwe-saving_wait' => 'Αποθήκευση σε εξέλιξη (παρακαλώ περιμένετε)',
+       'mwe-save_done' => 'Η αποθήκευση ολοκληρώθηκε',
+       'mwe-edit_cancel' => 'Ακύρωση επεξεργασίας ακολουθίας',
+       'mwe-zoom_in' => 'Μεγέθυνση',
+       'mwe-zoom_out' => 'Σμίκρυνση',
+       'mwe-pixle2sec' => 'πίξελ ανά δευτερόλεπτα',
+       'mwe-rmclip' => 'Αφαίρεση κλιπ',
+       'mwe-editor_options' => 'Επιλογές επεξεργαστή',
+       'mwe-editor_mode' => 'Λειτουργία επεξεργαστή',
+       'mwe-simple_editor_desc' => 'απλός επεξεργαστής (iMovie στυλ)',
+       'mwe-advanced_editor_desc' => 'προχωρημένος επεξεργαστής (Final Cut στυλ)',
+       'mwe-other_options' => 'Άλλες επιλογές',
+       'mwe-loading_txt' => 'φόρτωση ...',
+       'fogg-select_file' => 'Επιλογή αρχείου',
+       'fogg-select_new_file' => 'Επιλογή νέου αρχείου',
+       'fogg-select_url' => 'Επιλογή URL',
+       'fogg-save_local_file' => 'Αποθήκευση Οgg',
+       'fogg-installed' => 'Ο Firefogg είναι εγκατεστημένος',
+       'fogg-for_improved_uploads' => 'Για βελτιωμένες φορτώσεις:',
+       'fogg-transcoding' => 'Κωδικοποίηση βίντεο σε Ogg',
+       'fogg-encoding-done' => 'Κωδικοποίηση πλήρης',
+       'fogg-badtoken' => 'Το δείγμα δεν είναι έγκυρο',
+       'mwe-stream_title' => '$1 $2 σε $3',
+       'fogg-cg-range' => 'Εύρος κωδικοποίησης',
+       'fogg-preset-custom' => 'Συνήθεις ρυθμίσεις',
+       'mwe-media_search' => 'Αναζήτηση μέσων',
+       'rsd_box_layout' => 'Διαρρύθμιση κυτίου',
+       'rsd_list_layout' => 'Διαρρύθμιση λίστας',
+       'rsd_results_desc' => 'Αποτελέσματα',
+       'rsd_results_next' => 'επομ',
+       'rsd_results_prev' => 'Προηγούμενος',
+       'rsd_no_results' => 'Κανένα αποτέλεσμα για <b>$1</b>',
+       'mwe-upload_tab' => 'Φόρτωση',
+       'rsd_layout' => 'Διαρρύθμιση:',
+       'rsd_resource_edit' => 'Επεξεργασία πόρου: $1',
+       'mwe-resource_description_page' => 'Σελίδα περιγραφής πόρου',
+       'rsd_local_resource_title' => 'Τοπικός τίτλος πόρου',
+       'rsd_do_insert' => 'Εισάγετε',
+       'mwe-cc_by_title' => 'Απόδοση',
+       'mwe-cc_nc_title' => 'Μηεμπορικό',
+       'mwe-cc_nd_title' => 'Κανένα Παράγωγο Έργο',
+       'mwe-cc_sa_title' => 'Όμοιο Μοίρασμα',
+       'mwe-cc_pd_title' => 'Δημόσιο Domain',
+       'mwe-unknown_license' => 'Άγνωστη άδεια',
+       'mwe-your_recent_uploads' => 'Οι πρόσφατες φορτώσεις σας',
+       'mwe-upload_a_file' => 'Φορτώστε ένα νέο αρχείο',
+       'mwe-resource_page_desc' => 'Περιγραφή σελίδα πόρου:',
+       'mwe-local_resource_title' => 'Τοπικός τίτλος πόρου:',
+       'mwe-watch_this_page' => 'Παρακολούθηση σελίδας',
+       'mwe-do_import_resource' => 'Εισαγωγή πόρων',
+       'mwe-update_preview' => 'Ενημέρωση προεπισκόπησης',
+       'mwe-cancel_import' => 'Ακύρωση εισαγωγής',
+       'mwe-select_file' => 'Επιλογή αρχείου',
+       'mwe-upload' => 'Φόρτωση αρχείου',
+       'mwe-destfilename' => 'Νέο όνομα αρχείου:',
+       'mwe-summary' => 'Περίληψη',
+       'mwe-upload-transcoded-status' => 'Διακωδικοποιημένο',
+       'mwe-uploaded-status' => 'Επιφορτωμένο',
+       'mwe-upload-stats-fileprogres' => '$1 από $2',
+       'mwe-upload_completed' => 'Η φόρτωση είναι πλήρης',
+       'mwe-upload-unknown-size' => 'Άγνωστο μέγεθος',
+       'mwe-successfulupload' => 'Επιτυχής φόρτωση',
+       'mwe-uploaderror' => 'Σφάλμα φόρτωσης',
+       'mwe-uploadwarning' => 'Προειδοποίηση φόρτωσης',
+       'mwe-unknown-error' => 'Άγνωστο σφάλμα:',
+       'mwe-return-to-form' => 'Επιστροφή στη φόρμα',
+       'mwe-fileexists-thumb' => '<center><b>Υπάρχον αρχείο</b></center>',
+       'mwe-go-to-resource' => 'Πήγαινε στη σελίδα πόρου',
+       'mwe-upload-misc-error' => 'Άγνωστο σφάλμα επιφόρτωσης',
+       'mwe-link_back' => 'Σύνδεσε πίσω',
+       'mwe-play_clip' => 'Αναπαραγωγή κλιπ',
+       'mwe-pause_clip' => 'Παύση κλιπ',
+       'mwe-volume_control' => 'Χειρισμός έντασης',
+       'mwe-player_options' => 'Ρυθμίσεις αναπαραγωγέα',
+       'mwe-player_fullscreen' => 'Πλήρης οθόνη',
+       'mwe-seek_to' => 'Αναζήτηση για $1',
+       'mwe-download_segment' => 'Επιλογή λήψης:',
+       'mwe-download_clip' => 'Λήψη βίντεο',
+       'mwe-download' => 'Λήψη',
+       'mwe-share' => 'Μοίρασμα',
+       'mwe-credits' => 'Συστατικά',
+       'mwe-share_this_video' => 'Μοίρασμα βίντεο',
+       'mwe-video_credits' => 'Συστατικά βίντεο',
+       'mwe-menu_btn' => 'Μενού',
+       'mwe-close_btn' => 'Κλείσιμο',
+       'mwe-ogg-player-oggPlugin' => 'Σύνδεση Generic Ogg',
+       'mwe-ogg-player-quicktime-mozilla' => 'Σύνδεση QuickTime',
+       'mwe-ogg-player-quicktime-activex' => 'QuickTime ActiveX',
+       'mwe-ogg-player-cortado' => 'Java Cortado',
+       'mwe-ogg-player-flowplayer' => 'Αναπαραγωγέας ροής',
+       'mwe-ogg-player-selected' => '(επιλέχθηκε)',
+       'mwe-ogg-player-omtkplayer' => 'OMTK Flash Vorbis',
+       'mwe-do_not_warn_again' => 'Διαγραφή για τώρα.',
+       'mwe-playerselect' => 'Παίκτες',
+       'mwe-embed_site_or_blog' => 'Ενσωμάτωση στο σάιτ ή μπλογκ σας',
+       'mwe-related_videos' => 'Σχετικά βίντεο',
+);
+
+/** Esperanto (Esperanto)
+ * @author Lucas
+ * @author Yekrats
+ */
+$messages['eo'] = array(
+       'mwe-crop' => 'Stuci bildon',
+       'mwe-apply_crop' => 'Apliki stucon al bildo',
+       'mwe-cancel_image_insert' => 'Nuligi enmeton',
+       'mwe-sc_duration' => 'Daŭro',
+       'mwe-custom_title' => 'Memkreita titolo',
+       'mwe-close' => 'fermi',
+       'mwe-menu_options' => 'Agordoj',
+       'mwe-zoom_in' => 'Zomi',
+       'mwe-zoom_out' => 'Malzomi',
+       'mwe-editor_options' => 'Opcioj por redaktilo',
+       'mwe-editor_mode' => 'Redakta reĝimo',
+       'mwe-other_options' => 'Aliaj agordoj',
+       'mwe-loading_txt' => 'ŝarĝante ...',
+       'mwe-cancel' => 'Nuligi',
+       'fogg-select_file' => 'Elekti dosieron',
+       'fogg-select_new_file' => 'Elekti novan dosieron',
+       'fogg-select_url' => 'Elekti URL-on',
+       'fogg-installed' => 'Instalis Firefogg',
+       'fogg-use_latest_firefox' => 'Bonvolu antaŭe instali <a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=firefogg">Firefox (Fajrvulpo) 3.5</a> (or later). <i>Poste revenu al ĉi tiu paĝo por instali la  kromprogramon <b>Firefogg</b>.</i>',
+       'fogg-hidepreview' => 'Kaŝi antaŭvidon',
+       'fogg-videoQuality-title' => 'Videa kvalito',
+       'fogg-starttime-title' => 'Komenca sekundo',
+       'fogg-endtime-title' => 'Fina sekundo',
+       'fogg-videoCodec-title' => 'Videokodeko',
+       'fogg-audioCodec-title' => 'Sonkodeko',
+       'fogg-denoise-title' => 'Senbrua filtrilo',
+       'fogg-denoise-help' => 'Senbruigi videan enigon. Pli pri <a href="http://en.wikipedia.org/wiki/Video_denoising">senbruigado de video</a>.',
+       'fogg-novideo-title' => 'Sen video',
+       'fogg-date-help' => 'La dato kiam la dosiero estis farita',
+       'fogg-location-title' => 'Loko',
+       'fogg-license-help' => 'La licenco de la dosiero (prefere URL de Krea Komunejo).',
+       'rsd_results_next' => 'sekva',
+       'rsd_results_prev' => 'antaŭa',
+       'mwe-upload_tab' => 'Alŝuti',
+       'mwe-cc_pd_title' => 'Publika Domajno',
+       'mwe-no_import_by_url' => 'Ĉi tiu uzanto aŭ vikio <b>ne povas</b> importi dosierojn el eksteraj URL-oj.<p>Ĉu vi bezonas ensaluti?</p><p>Ĉu upload_by_url permeso estas ŝalta?<br />Ĉu la vikio ŝaltis <a href="http://www.mediawiki.org/wiki/Manual:$wgAllowCopyUploads">$wgAllowCopyUploads</a> ?</p>',
+       'mwe-watch_this_page' => 'Atenti tiun ĉi paĝon',
+       'mwe-select_file' => 'Elekti dosieron',
+       'mwe-upload' => 'Alŝuti dosieron',
+       'mwe-summary' => 'Resumo',
+       'mwe-upload-stats-fileprogres' => '$1 el $2',
+       'mwe-player_fullscreen' => 'Plenekrana',
+       'mwe-download_full' => 'Elŝuti kompletan filmetan dosieron:',
+       'mwe-download_clip' => 'Elŝuti filmeton',
+       'mwe-download' => 'Elŝuti',
+       'mwe-share' => 'Konigi',
+       'mwe-share_this_video' => 'Konigi ĉi tiun filmeton',
+       'mwe-menu_btn' => 'Menuo',
+       'mwe-close_btn' => 'Fermi',
+       'mwe-ogg-player-selected' => '(elektita)',
+       'mwe-generic_missing_plugin' => 'Via retumilo ne verŝajne subtenas la jenan aŭdvidean dosiertipon: <b>$1</b><br />Vizitu la paĝon pri <a href="http://commons.wikimedia.org/wiki/Commons:Media_help">Aŭdvideaj MetodojMethods</a> por elŝuti la taŭgan kromprogramon..<br />',
+       'mwe-read_before_embed' => 'Bonvolu legi la <a href="http://mediawiki.org/wiki/Security_Notes_on_Remote_Embedding" target="_new">sekurecajn notojn pri ekstera enkorpigado</a> antaŭ fakte enkorpigado!',
+);
+
+/** Spanish (Español)
+ * @author Antur
+ * @author Crazymadlover
+ * @author Locos epraix
+ * @author McDutchie
+ * @author Translationista
+ */
+$messages['es'] = array(
+       'mwe-crop' => 'Recortar imagen',
+       'mwe-apply_crop' => 'Aplicar el recorte a la imagen',
+       'mwe-reset_crop' => 'Reiniciar el recorte',
+       'mwe-insert_image_page' => 'Insertar en la página',
+       'mwe-insert_into_sequence' => 'Insertar en secuencia',
+       'mwe-preview_insert' => 'Previsualisar inserción',
+       'mwe-cancel_image_insert' => 'Cancelar inserción',
+       'mwe-sc_fileopts' => 'Edición de detalles del clip',
+       'mwe-sc_inoutpoints' => 'Establecer puntos de entrada y salida',
+       'mwe-sc_overlays' => 'Superposiciones',
+       'mwe-sc_audio' => 'Control de sonido',
+       'mwe-sc_duration' => 'Duración',
+       'mwe-template_properties' => 'Propiedades de plantilla',
+       'mwe-custom_title' => 'Personalizar título',
+       'mwe-edit_properties' => 'Editar propiedades',
+       'mwe-other_properties' => 'Otras propiedades',
+       'mwe-resource_page' => 'Página de recurso:',
+       'mwe-set_in_out_points' => 'Establecer puntos de entrada y salida',
+       'mwe-start_time' => 'Tiempo de inicio',
+       'mwe-end_time' => 'Tiempo de fin',
+       'mwe-preview_inout' => 'Previsualizar puntos de entrada y salida',
+       'mwe-edit-video-tools' => 'Herramientas de edición de video:',
+       'mwe-duration' => 'Duración:',
+       'mwe-upload-subs-file' => 'Cargar subtítulo',
+       'mwe-add-subs-file-title' => 'Seleccionar el subtítulo a cargar',
+       'mwe-error-only-srt' => 'Sólo se puede cargar archivos srt.',
+       'mwe-watch-video' => 'Ver el video',
+       'mwe-select-other-language' => 'Seleccionar otro idioma',
+       'mwe-saving' => 'guardando...',
+       'mwe-select_transcript_set' => 'Seleccionar capas',
+       'mwe-auto_scroll' => 'desplazamiento automático',
+       'mwe-close' => 'Cerrar',
+       'mwe-improve_transcript' => 'Mejorar',
+       'mwe-no_text_tracks_found' => 'No se encontró pistas de texto',
+       'mwe-add-edit-subs' => 'Añadir/editar subtítulos',
+       'mwe-transition_in' => 'Transición de entrada',
+       'mwe-transition_out' => 'Transición de salida',
+       'mwe-effects' => 'Pila de efectos',
+       'mwe-remove_transition' => 'Remover transición',
+       'mwe-edit_transin' => 'Editar la transición en el clip',
+       'mwe-edit_transout' => 'Editar la transición fuera del clip',
+       'mwe-add-transition' => 'Añadir una transición',
+       'mwe-menu_clipedit' => 'Editar medios',
+       'mwe-menu_transition' => 'Transiciones y efectos',
+       'mwe-menu_cliplib' => 'Agregar medios',
+       'mwe-menu_options' => 'Opciones',
+       'mwe-loading_timeline' => 'Cargando línea temporal...',
+       'mwe-loading_user_rights' => 'Cargando derechos de usuario...',
+       'mwe-no_edit_permissions' => 'No tienes permisos para grabar cambios a esta secuencia',
+       'mwe-edit_clip' => 'Editar clip',
+       'mwe-edit_save' => 'Grabar cambios de secuencia',
+       'mwe-saving_wait' => 'Grabado en proceso (por favor espere)',
+       'mwe-save_done' => 'Grabar completo',
+       'mwe-edit_cancel' => 'Cancelar edición de secuencia',
+       'mwe-edit_cancel_confirm' => 'Estás seguro que deseas cancelar tu edición? Los cambios se perderán.',
+       'mwe-zoom_in' => 'Agrandar',
+       'mwe-zoom_out' => 'Achicar',
+       'mwe-cut_clip' => 'Cortar clips',
+       'mwe-expand_track' => 'Expandir la pista',
+       'mwe-collapse_track' => 'Contraer la pista',
+       'mwe-pixle2sec' => 'píxeles a segundos',
+       'mwe-rmclip' => 'Remover clip',
+       'mwe-editor_options' => 'Opciones de editor',
+       'mwe-editor_mode' => 'Modo editor',
+       'mwe-simple_editor_desc' => 'editor simple(estilo iMovie)',
+       'mwe-advanced_editor_desc' => 'editor avanzado (estilo Final Cut)',
+       'mwe-other_options' => 'Otras opciones',
+       'mwe-contextmenu_opt' => 'Habilitar menúes contextuales',
+       'mwe-sequencer_credit_line' => 'Desarrollado por <a href="http://kaltura.com">Kaltura, Inc.</a> en asociación con <a href="http://wikimediafoundation.org/wiki/Home">Fundación Wikimedia</a> (<a href="#">más información</a>).',
+       'mwe-loading_txt' => 'cargando ...',
+       'mwe-load-drag-item' => 'Cargando el objeto arrastrado',
+       'mwe-ok' => 'OK',
+       'mwe-cancel' => 'Cancelar',
+       'mwe-re-try' => 'Reintentar solicitud de API',
+       'mwe-re-trying' => 'Reintentando solicitud de API',
+       'mwe-proxy-not-ready' => 'Proxy no configurado',
+       'mwe-remember-loging' => 'Recordatorio general de seguridad: Accede a los sitios web sólo cuando la barra de direcciones muestre esa dirección del sitio.',
+       'fogg-select_file' => 'Seleccionar archivo',
+       'fogg-select_new_file' => 'Seleccionar nuevo archivo',
+       'fogg-select_url' => 'Seleccionar URL',
+       'fogg-save_local_file' => 'Grabar Ogg',
+       'fogg-check_for_firefogg' => 'Verificando Firefogg ...',
+       'fogg-installed' => 'Firefogg está instalado',
+       'fogg-for_improved_uploads' => 'Para cargas mejoradas:',
+       'fogg-please_install' => '<a href="$1">Instalar Firefogg</a>. Más <a href="http://commons.wikimedia.org/wiki/Commons:Firefogg">acerca de Firefogg</a>',
+       'fogg-use_latest_firefox' => 'Por favor primero instala <a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=firefogg">Firefox 3.5</a> (o posterior). <i>Luego vuelve a visitar esta página para instalar la extensión <b>Firefogg</b>.</i>',
+       'fogg-passthrough_mode' => 'Tu archivo seleccionado ya es Ogg o no es un archivo de video',
+       'fogg-transcoding' => 'Codificando video a Ogg',
+       'fogg-encoding-done' => 'Codificación completa',
+       'fogg-preview' => 'Previsualizar video',
+       'fogg-hidepreview' => 'Esconder previsualización',
+       'mwe-imported_from' => '$1 importado desde [$2 $3]. Ver el [$4 página de recurso] original para más información.',
+       'mwe-stream_title' => '$1 $2 a $3',
+       'fogg-help-sticky' => 'Ayuda (click para pegar)',
+       'fogg-cg-preset' => 'Predefinido: <strong>$1</strong>',
+       'fogg-cg-quality' => 'Control básico de calidad y resolución.',
+       'fogg-cg-meta' => 'Metadatos para el clip',
+       'fogg-cg-range' => 'Rango de codificación',
+       'fogg-cg-advVideo' => 'Controles avanzados de codificación de video',
+       'fogg-cg-advAudio' => 'Controles avanzados de codificación de audio',
+       'fogg-preset-custom' => 'Personalizar configuraciones',
+       'fogg-videoQuality-title' => 'Calidad de video',
+       'fogg-videoQuality-help' => 'Utilizado para establecer la <i>calidad visual</i> del video codificado (no utilizado si has establecido el bitraje en los controles avanzados de abajo).',
+       'fogg-starttime-title' => 'Segundo de inicio',
+       'fogg-starttime-help' => 'Sólo codificar desde tiempo en segundos',
+       'fogg-endtime-title' => 'Segundo de fin',
+       'fogg-endtime-help' => 'Sólo codificar a tiempo en segundos',
+       'fogg-audioQuality-title' => 'Calidad del audio',
+       'fogg-videoCodec-title' => 'Códec de video',
+       'fogg-audioCodec-title' => 'Códec de audio',
+       'fogg-width-title' => 'Ancho del video',
+       'fogg-width-help' => 'Redimensionar al ancho dado.',
+       'fogg-height-title' => 'Altura del video',
+       'fogg-height-help' => 'Redimensionar a la altura dada.',
+       'fogg-videoBitrate-title' => 'Bitraje del video',
+       'fogg-videoBitrate-help' => 'El bitraje de video establece el bitraje de codificación para el video en (kb/s)',
+       'fogg-framerate-title' => 'Velocidad del fotograma',
+       'fogg-aspect-title' => 'Relación de aspecto',
+       'fogg-keyframeInterval-title' => 'Intervalo del fotograma',
+       'fogg-keyframeInterval-help' => 'El intervalo de fotogramas clave en cuadros. Observación: La mayoría de los códecs fuerzan los fotogramas clave si la diferencia entre cuadros es mayor que el tamaño de codificación de fotogramas clave. Más información se encuentra disponible en <a href="http://es.wikipedia.org/wiki/Fotograma">fotogramas</a>',
+       'fogg-denoise-title' => 'Filtro de eliminación de ruidos',
+       'fogg-novideo-title' => 'No hay video',
+       'fogg-novideo-help' => 'deshabilitar el video en la salida',
+       'fogg-audioBitrate-title' => 'Bitraje de audio',
+       'fogg-samplerate-title' => 'Velocidad de muestreo de audio',
+       'fogg-noaudio-title' => 'No hay sonido',
+       'fogg-noaudio-help' => 'Desabilitar el sonido en la salida',
+       'fogg-title-title' => 'Título',
+       'fogg-title-help' => 'Un título para tu clip',
+       'fogg-artist-title' => 'Nombre del creador',
+       'fogg-artist-help' => 'El creador de este clip',
+       'fogg-date-title' => 'Fecha',
+       'fogg-date-help' => 'Fecha en que la secuencia fue creada o lanzada al público',
+       'fogg-location-title' => 'Ubicación',
+       'fogg-location-help' => 'Ubicación de la secuencia',
+       'fogg-organization-title' => 'Organización',
+       'fogg-organization-help' => 'Nombre de la organización (estudio)',
+       'fogg-copyright-title' => 'Derechos de reproducción',
+       'fogg-copyright-help' => 'Derechos de reproducción del clip',
+       'fogg-license-title' => 'Licencia',
+       'fogg-license-help' => 'La licencia del clip (preferiblemente un URL de Creative Commons).',
+       'fogg-contact-title' => 'Contacto',
+       'fogg-contact-help' => 'Vínculo del contacto',
+       'mwe-add_media_wizard' => 'Agregar tutorial de media',
+       'mwe-media_search' => 'Búsqueda en medios',
+       'rsd_box_layout' => 'Composición de la caja',
+       'rsd_list_layout' => 'Composición del listado',
+       'rsd_results_desc' => 'Resultados $1 a $2',
+       'rsd_results_desc_total' => 'Resultados $1 a $2 de $3',
+       'rsd_results_next' => 'siguiente',
+       'rsd_results_prev' => 'anterior',
+       'rsd_no_results' => 'Sin resultados de búsqueda para <b>$1</b>',
+       'mwe-upload_tab' => 'Cargar',
+       'rsd_layout' => 'Composición:',
+       'rsd_resource_edit' => 'Editar recurso: $1',
+       'mwe-resource_description_page' => 'Página de descripción del recurso',
+       'mwe-link' => 'vínculo',
+       'rsd_local_resource_title' => 'Título del recurso local',
+       'rsd_do_insert' => 'Hacer inserción',
+       'mwe-cc_by_title' => 'Atribución',
+       'mwe-cc_nc_title' => 'No comercial',
+       'mwe-cc_nd_title' => 'Sin derivadas',
+       'mwe-cc_sa_title' => 'Compartir bajo la misma licencia',
+       'mwe-cc_pd_title' => 'Dominio público',
+       'mwe-unknown_license' => 'Licencia desconocida',
+       'mwe-your_recent_uploads' => 'Tus cargas recientes a $1',
+       'mwe-upload_a_file' => 'Subir un nuevo archivo a $1',
+       'mwe-resource_page_desc' => 'Descripción de la página de recurso:',
+       'mwe-edit_resource_desc' => 'Editar descripción de recursos de texto wiki:',
+       'mwe-local_resource_title' => 'Título del recurso local:',
+       'mwe-watch_this_page' => 'Vigilar esta página',
+       'mwe-do_import_resource' => 'Importar recurso',
+       'mwe-update_preview' => 'Actualizar previsualización',
+       'mwe-cancel_import' => 'Cancelar importación',
+       'mwe-checking-resource' => 'Buscando recurso:',
+       'mwe-resource-needs-import' => 'El recurso $1 necesita ser importado a $2',
+       'mwe-ftype-svg' => 'archivo vectorial SVG',
+       'mwe-ftype-jpg' => 'Archivo de imagen JPEG',
+       'mwe-ftype-png' => 'Archivo de imagen PNG',
+       'mwe-ftype-oga' => 'Archivo de audio Ogg',
+       'mwe-ftype-ogg' => 'Archivo de video Ogg',
+       'mwe-ftype-unk' => 'Formato de archivo desconocido',
+       'rsd-this_wiki-title' => 'Este wiki',
+       'mwe-select_file' => 'Seleccionar archivo',
+       'mwe-select_ownwork' => 'Estoy cargando mi trabajo por completo y lo estoy licenciando bajo:',
+       'mwe-upload' => 'Subir archivo',
+       'mwe-destfilename' => 'Archivo de destino:',
+       'mwe-summary' => 'Resumen',
+       'mwe-error_not_loggedin' => 'No pareces haber iniciado sesión o tener privilegios de carga',
+       'mwe-watch-this-file' => 'Seguir este archivo',
+       'mwe-ignore-any-warnings' => 'Ignorar las advertencias',
+       'mwe-upload-in-progress' => 'Carga en proceso (no cierre esta ventana)',
+       'mwe-upload-transcoded-status' => 'Transcodificado',
+       'mwe-uploaded-status' => 'Cargado',
+       'mwe-upload-stats-fileprogres' => '$1 de $2',
+       'mwe-upload_completed' => 'Tu carga está completa',
+       'mwe-upload-unknown-size' => 'Tamaño desconocido',
+       'mwe-cancel-confim' => 'Estás seguro que deseas cancelar?',
+       'mwe-successfulupload' => 'Carga exitosa',
+       'mwe-uploaderror' => 'Error en carga',
+       'mwe-uploadwarning' => 'Advertencia en carga',
+       'mwe-unknown-error' => 'Error desconocido:',
+       'mwe-return-to-form' => 'Retornar al formulario',
+       'mwe-file-exists-duplicate' => 'Este archivo es un duplicado del siguiente archivo:',
+       'mwe-fileexists' => 'Un archivo con este nombre ya existe. Por favor verifica <b><tt>$1</tt></b> si no est.ás seguro si deseas cambiarlo.',
+       'mwe-fileexists-thumb' => '<center><b>Archivo existente</b></center>',
+       'mwe-ignorewarning' => 'Ignorar advertencia y grabar de todos modos',
+       'mwe-file-thumbnail-no' => 'El nombre de archivo comienza con <b><tt>$1</tt></b>',
+       'mwe-go-to-resource' => 'Ir a la página del recurso',
+       'mwe-upload-misc-error' => 'Error desconocido en la subida',
+       'mwe-loading_plugin' => 'Cargando plugin ...',
+       'mwe-select_playback' => 'Configurar preferencia de reproducción',
+       'mwe-add_to_end_of_sequence' => 'Agregar al final de la secuencia',
+       'mwe-play_clip' => 'Reproducir clip',
+       'mwe-pause_clip' => 'Pausar clip',
+       'mwe-volume_control' => 'Control de volumen',
+       'mwe-player_options' => 'Opciones de reproductor',
+       'mwe-closed_captions' => 'Subtítulos',
+       'mwe-player_fullscreen' => 'Pantalla completa',
+       'mwe-next_clip_msg' => 'Reproducir siguiente clip',
+       'mwe-prev_clip_msg' => 'Reproducir clip anterior',
+       'mwe-current_clip_msg' => 'Continuar reproduciendo este clip',
+       'mwe-seek_to' => 'Buscar $1',
+       'mwe-paused' => 'en pausa',
+       'mwe-download_segment' => 'Descargar selección:',
+       'mwe-download_full' => 'Descargar archivo de video completo:',
+       'mwe-download_right_click' => 'Para descargar, haga click con el botón derecho del ratón y seleccione <i>Guardar enlace como...</i>',
+       'mwe-download_clip' => 'Descargar archivo',
+       'mwe-download_text' => 'Descargar texto (<a style="color:white" title="cmml" href="http://wiki.xiph.org/index.php/CMML">CMML</a> xml):',
+       'mwe-download' => 'Descargar',
+       'mwe-share' => 'Compartir',
+       'mwe-credits' => 'Créditos',
+       'mwe-clip_linkback' => 'Página fuente de clip',
+       'mwe-chose_player' => 'Elegir reproductor de video',
+       'mwe-share_this_video' => 'Compartir este video',
+       'mwe-video_credits' => 'Créditos de video',
+       'mwe-menu_btn' => 'Menú',
+       'mwe-close_btn' => 'Cerrar',
+       'mwe-ogg-player-vlc-player' => 'Reproductor de VLC',
+       'mwe-ogg-player-videoElement' => 'Video Ogg nativo',
+       'mwe-ogg-player-oggPlugin' => 'Plugin Ogg genérico',
+       'mwe-ogg-player-quicktime-mozilla' => 'Plugin QuickTime',
+       'mwe-ogg-player-quicktime-activex' => 'QuickTime ActiveX',
+       'mwe-ogg-player-cortado' => 'Java Cortado',
+       'mwe-ogg-player-flowplayer' => 'Flowplayer',
+       'mwe-ogg-player-selected' => '(seleccionado)',
+       'mwe-ogg-player-omtkplayer' => 'OMTK Flash Vorbis',
+       'mwe-generic_missing_plugin' => 'Tu navegador parece no soportar el siguiente tipo de reproducción: <b>$1</b><br />Visite pa página <a href="http://commons.wikimedia.org/wiki/Commons:Media_help">Playback Methods</a> para descargar un reproductor.<br />',
+       'mwe-for_best_experience' => 'Para una mejor experiencia de reproducción de video, recomendamos: <br /><b><a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=mwEmbed">Firefox 3.5</a>.</b>',
+       'mwe-do_not_warn_again' => 'Descartar por ahora.',
+       'mwe-playerselect' => 'Reproductores',
+       'mwe-embed_site_or_blog' => 'Insertar en una página',
+       'mwe-related_videos' => 'Videos relacionados',
+       'mwe-seeking' => 'buscando',
+       'mwe-copy-code' => 'Copiar código',
+);
+
+/** Basque (Euskara)
+ * @author An13sa
+ */
+$messages['eu'] = array(
+       'mwe-crop' => 'Irudia moztu',
+       'mwe-sc_duration' => 'Iraupena',
+       'mwe-start_time' => 'Hasiera ordua',
+       'mwe-end_time' => 'Amaiera ordua',
+       'mwe-edit-tools' => 'Tresnak editatu',
+       'mwe-duration' => 'Iraupena:',
+       'mwe-upload-subs-file' => 'Azpitituluak igo',
+       'mwe-add-subs-file-title' => 'Aukeratu igotzeko azpitituluak',
+       'mwe-watch-video' => 'Bideoa ikusi',
+       'mwe-select-other-language' => 'Beste hizkuntza bat aukeratu',
+       'mwe-close' => 'itxi',
+       'mwe-improve_transcript' => 'Hobetu',
+       'mwe-loading_txt' => 'Kargatzen ...',
+       'mwe-ok' => 'Ados',
+       'mwe-cancel' => 'Ezeztatu',
+       'fogg-select_file' => 'Fitxategia aukeratu',
+       'fogg-select_new_file' => 'Fitxategi berria aukeratu',
+       'fogg-select_url' => 'URLa aukeratu',
+       'fogg-preview' => 'Bideoa aurreikusi',
+       'fogg-hidepreview' => 'Aurreikuspena ezkutatu',
+       'fogg-videoQuality-title' => 'Bideoaren kalitatea',
+       'fogg-audioQuality-title' => 'Audioaren kalitatea',
+       'fogg-width-title' => 'Bideoaren zabalera',
+       'fogg-height-title' => 'Bideoaren altuera',
+       'fogg-title-title' => 'Izenburua',
+       'fogg-date-title' => 'Data',
+       'fogg-location-title' => 'Kokapena',
+       'fogg-copyright-title' => 'Copyrighta',
+       'fogg-license-title' => 'Lizentzia',
+       'rsd_results_next' => 'hurrengoa',
+       'rsd_results_prev' => 'aurrekoa',
+       'mwe-upload_tab' => 'Igo',
+       'mwe-unknown_license' => 'Lizentzia ezezaguna',
+       'mwe-ftype-svg' => 'SVG bektore fitxategia',
+       'mwe-ftype-jpg' => 'JPEG irudi fitxategia',
+       'mwe-ftype-png' => 'PNG irudi fitxategia',
+       'mwe-ftype-oga' => 'Ogg audio fitxategia',
+       'mwe-ftype-ogg' => 'Ogg bideo fitxategia',
+       'mwe-ftype-unk' => 'Fitxategi formatu ezezaguna',
+       'rsd-wiki_commons-title' => 'Wikimedia Commons',
+       'rsd-this_wiki-title' => 'Wiki hau',
+       'mwe-select_file' => 'Fitxategia aukeratu',
+       'mwe-upload' => 'Fitxategia igo',
+       'mwe-summary' => 'Laburpena',
+       'mwe-watch-this-file' => 'Fitxategia jarraitu',
+       'mwe-uploaded-status' => 'Igoa',
+       'mwe-upload-unknown-size' => 'Tamaina ezezaguna',
+       'mwe-player_fullscreen' => 'Pantaila osoan',
+       'mwe-paused' => 'pausatua',
+       'mwe-download' => 'Jaitsi',
+       'mwe-share' => 'Partekatu',
+       'mwe-credits' => 'Kredituak',
+       'mwe-menu_btn' => 'Menua',
+       'mwe-close_btn' => 'Itxi',
+);
+
+/** Finnish (Suomi)
+ * @author Crt
+ * @author Silvonen
+ * @author Str4nd
+ */
+$messages['fi'] = array(
+       'mwe-crop' => 'Rajaa kuva',
+       'mwe-apply_crop' => 'Käytä rajausta kuvaan',
+       'mwe-reset_crop' => 'Poista rajaus',
+       'mwe-insert_image_page' => 'Lisää sivulle',
+       'mwe-insert_into_sequence' => 'Lisää kappaleeseen',
+       'mwe-preview_insert' => 'Esikatsele lisäystä',
+       'mwe-cancel_image_insert' => 'Peruuta lisäys',
+       'mwe-sc_audio' => 'Äänenhallinta',
+       'mwe-sc_duration' => 'Kesto',
+       'mwe-edit_properties' => 'Muokkaa ominaisuuksia',
+       'mwe-start_time' => 'Aloitusaika',
+       'mwe-end_time' => 'Lopetusaika',
+       'mwe-saving' => 'tallennetaan...',
+       'mwe-auto_scroll' => 'automaattinen vieritys',
+       'mwe-close' => 'sulje',
+       'mwe-menu_options' => 'Asetukset',
+       'mwe-simple_editor_desc' => 'yksinkertainen editori (iMovie-tyyli)',
+       'mwe-other_options' => 'Muut valinnat',
+       'mwe-sequencer_credit_line' => 'Kehittänyt <a href="http://kaltura.com">Kaltura, Inc.</a> yhteistyössä <a href="http://wikimediafoundation.org/wiki/Home">Wikimedia Foundationin</a> kanssa (<a href="#">lisätietoja</a>).',
+       'mwe-cancel' => 'Peruuta',
+       'fogg-select_file' => 'Valitse tiedosto',
+       'fogg-select_new_file' => 'Valitse uusi tiedosto',
+       'fogg-select_url' => 'Valitse URL',
+       'fogg-save_local_file' => 'Tallenna Ogg',
+       'fogg-installed' => 'Firefogg on asennettu',
+       'fogg-for_improved_uploads' => 'Parannettua tallentamista varten:',
+       'fogg-please_install' => '<a href="$1">Asenna Firefogg</a> – <a href="http://commons.wikimedia.org/wiki/Commons:Firefogg">Tietoja Firefoggista</a>.',
+       'fogg-use_latest_firefox' => 'Asenna ensin <a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=firefogg">Firefox 3.5</a> (tai uudempi). <i>Tule sen jälkeen uudelleen tälle sivulle ja asenna <b>Firefogg</b>-laajennus.</i>',
+       'fogg-preview' => 'Videon esikatselu',
+       'fogg-hidepreview' => 'Piilota esikatselu',
+       'fogg-audioQuality-title' => 'Äänenlaatu',
+       'fogg-novideo-title' => 'Ei videota',
+       'fogg-noaudio-title' => 'Ei ääntä',
+       'fogg-title-title' => 'Otsikko',
+       'fogg-date-title' => 'Päiväys',
+       'fogg-location-title' => 'Sijainti',
+       'fogg-license-title' => 'Lisenssi',
+       'mwe-media_search' => 'Mediahaku',
+       'rsd_results_desc' => 'Tulokset $1-$2',
+       'rsd_results_next' => 'seuraava',
+       'rsd_results_prev' => 'edellinen',
+       'mwe-link' => 'linkki',
+       'mwe-unknown_license' => 'Tuntematon lisenssi',
+       'mwe-upload_a_file' => 'Tallenna uusi tiedosto kohteeseen $1',
+       'mwe-watch_this_page' => 'Tarkkaile tätä sivua',
+       'mwe-update_preview' => 'Päivitä esikatselu',
+       'mwe-cancel_import' => 'Peruuta tuonti',
+       'mwe-ftype-svg' => 'SVG-vektoritiedosto',
+       'mwe-ftype-jpg' => 'JPEG-kuvatiedosto',
+       'mwe-ftype-png' => 'PNG-kuvatiedosto',
+       'mwe-ftype-oga' => 'Ogg-äänitiedosto',
+       'mwe-ftype-ogg' => 'Ogg-videotiedosto',
+       'mwe-ftype-unk' => 'Tuntematon tiedostomuoto',
+       'rsd-wiki_commons-title' => 'Wikimedia Commons',
+       'rsd-this_wiki-title' => 'Tämä wiki',
+       'mwe-select_file' => 'Valitse tiedosto',
+       'mwe-upload' => 'Tallenna tiedosto',
+       'mwe-summary' => 'Yhteenveto',
+       'mwe-upload-stats-fileprogress' => '$1 / $2',
+       'mwe-upload-unknown-size' => 'Tuntematon koko',
+       'mwe-cancel-confim' => 'Oletko varma, että haluat peruuttaa?',
+       'mwe-uploaderror' => 'Tallennusvirhe',
+       'mwe-uploadwarning' => 'Tallennusvaroitus',
+       'mwe-unknown-error' => 'Tuntematon virhe:',
+       'mwe-return-to-form' => 'Palaa lomakkeeseen',
+       'mwe-upload-misc-error' => 'Tuntematon tallennusvirhe',
+       'mwe-player_options' => 'Soittimen asetukset',
+       'mwe-player_fullscreen' => 'Koko näyttö',
+       'mwe-download_full' => 'Lataa koko videotiedosto:',
+       'mwe-download_clip' => 'Lataa video',
+       'mwe-download' => 'Lataa',
+       'mwe-share' => 'Jaa',
+       'mwe-menu_btn' => 'Valikko',
+       'mwe-close_btn' => 'Sulje',
+       'mwe-ogg-player-flowplayer' => 'Flowplayer',
+       'mwe-ogg-player-selected' => '(valittu)',
+       'mwe-generic_missing_plugin' => 'Selaimesi ei näytä tukevan seuraavaa toistomuotoa: <b>$1</b><br />Käy <a href="http://commons.wikimedia.org/wiki/Commons:Media_help">ohjesivulla</a> ladataksesi soittimen.<br />',
+       'mwe-for_best_experience' => 'Suosituksena parempaa videotoistokokemusta varten:<br /><b><a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=mwEmbed">Firefox 3.5</a>.</b>',
+       'mwe-playerselect' => 'Soittimet',
+       'mwe-copy-code' => 'Kopioi koodi',
+);
+
+/** French (Français)
+ * @author IAlex
+ * @author Jean-Frédéric
+ * @author McDutchie
+ * @author Peter17
+ * @author PieRRoMaN
+ */
+$messages['fr'] = array(
+       'mwe-crop' => "Rogner l'image",
+       'mwe-apply_crop' => "Appliquer la rognure à l'image",
+       'mwe-reset_crop' => 'Réinitialiser la rognure',
+       'mwe-insert_image_page' => 'Insérer dans la page',
+       'mwe-insert_into_sequence' => 'Insérer dans la séquence',
+       'mwe-preview_insert' => "Prévisualiser l'insertion",
+       'mwe-cancel_image_insert' => "Annuler l'insertion",
+       'mwe-sc_fileopts' => 'Modifier le détail du clip',
+       'mwe-sc_inoutpoints' => "Définir des points d'entrée-sortie",
+       'mwe-sc_overlays' => 'Revêtements',
+       'mwe-sc_audio' => 'Contrôle audio',
+       'mwe-sc_duration' => 'Durée',
+       'mwe-template_properties' => 'Propriétés du modèle',
+       'mwe-custom_title' => 'Titre personnalisé',
+       'mwe-edit_properties' => 'Modifier les propriétés',
+       'mwe-other_properties' => 'Autres propriétés',
+       'mwe-resource_page' => 'Page de la ressource :',
+       'mwe-set_in_out_points' => "Définir des points d'entrée-sortie",
+       'mwe-start_time' => 'Heure de début',
+       'mwe-end_time' => 'Heure de fin',
+       'mwe-preview_inout' => "Prévisualiser les points d'entrée-sortie",
+       'mwe-edit-tools' => 'Outils de modification',
+       'mwe-inline-description' => 'Légende',
+       'mwe-edit-video-tools' => 'Outils de modification des vidéos :',
+       'mwe-duration' => 'Durée :',
+       'mwe-upload-subs-file' => 'Téléverser un sous-titre',
+       'mwe-add-subs-file-title' => 'Sélectionner le sous-titre à téléverser',
+       'mwe-error-only-srt' => 'Seuls les fichiers srt peuvent être téléversés actuellement.',
+       'mwe-watch-video' => 'Regarder la vidéo',
+       'mwe-select-other-language' => 'Sélectionner une autre langue',
+       'mwe-saving' => 'sauvegarde...',
+       'mwe-select_transcript_set' => 'Sélectionner les sous-titres',
+       'mwe-auto_scroll' => 'défilement automatique',
+       'mwe-close' => 'fermer',
+       'mwe-improve_transcript' => 'Améliorer',
+       'mwe-no_text_tracks_found' => 'Pas de trace de texte trouvée',
+       'mwe-add-edit-subs' => 'Ajouter/modifier des sous-titres',
+       'mwe-transition_in' => 'Transition entrante',
+       'mwe-transition_out' => 'Transition sortante',
+       'mwe-effects' => "Pile d'effets",
+       'mwe-remove_transition' => 'Supprimer la transition',
+       'mwe-edit_transin' => 'Modifier la transition vers le clip',
+       'mwe-edit_transout' => 'Modifier la transition hors du clip',
+       'mwe-add-transition' => 'Ajouter une traduction',
+       'mwe-menu_clipedit' => 'Modifier le media',
+       'mwe-menu_transition' => 'Transitions et effets',
+       'mwe-menu_cliplib' => 'Ajouter un media',
+       'mwe-menu_resource_overview' => "Vue d'ensemble de la ressource",
+       'mwe-menu_options' => 'Options',
+       'mwe-loading_timeline' => 'Chargement de la chronologie ...',
+       'mwe-loading_user_rights' => "Chargement des droits d'utilisateur ...",
+       'mwe-no_edit_permissions' => "Vous n'avez pas l'autorisation de sauvegarder les changements apportés à cette séquence",
+       'mwe-edit_clip' => 'Modifier le clip',
+       'mwe-edit_save' => 'Sauvegarder les modifications de la séquence',
+       'mwe-saving_wait' => 'Sauvegarde en cours (veuillez patienter)',
+       'mwe-save_done' => 'Sauvegarde terminée',
+       'mwe-edit_cancel' => 'Annuler la modification de la séquence',
+       'mwe-edit_cancel_confirm' => 'Êtes-vous sûr de vouloir annuler votre modification ? Les changements seront perdus.',
+       'mwe-zoom_in' => 'Zoom avant',
+       'mwe-zoom_out' => 'Zoom arrière',
+       'mwe-cut_clip' => 'Couper les clips',
+       'mwe-expand_track' => 'Étendre la piste',
+       'mwe-collapse_track' => 'Réduire la piste',
+       'mwe-play_from_position' => 'Lire à partir de la position de lecture',
+       'mwe-pixle2sec' => 'pixels vers secondes',
+       'mwe-rmclip' => 'Supprimer le clip',
+       'mwe-clip_in' => 'attacher',
+       'mwe-clip_out' => 'détacher',
+       'mwe-no_selected_resource' => "<h3>Aucune ressource sélectionnée</h3> Sélectionnez un clip pour activer l'édition",
+       'mwe-error_edit_multiple' => '<h3>Plusieurs ressources sélectionnées</h3> Sélectionnez un seul clip pour le modifier',
+       'mwe-editor_options' => "Options de l'éditeur",
+       'mwe-editor_mode' => "Mode de l'éditeur",
+       'mwe-simple_editor_desc' => 'éditeur simple (style iMovie)',
+       'mwe-advanced_editor_desc' => 'éditeur avancé (style Final Cut)',
+       'mwe-other_options' => 'Autres options',
+       'mwe-contextmenu_opt' => 'Activer les menus contextuels',
+       'mwe-sequencer_credit_line' => 'Développé par <a href="http://kaltura.com">Kaltura, Inc.</a> en partenariat avec la <a href="http://wikimediafoundation.org/wiki/Home">Wikimedia Foundation</a> (<a href="#">plus d\'information</a>).',
+       'mwe-loading_txt' => 'chargement ...',
+       'mwe-error_load_lib' => "Erreur : JavaScript $1 n'a pas pu être trouvé ou ne définit pas $2",
+       'mwe-loading-add-media-wiz' => "Chargement de l'assistant d'ajout de média",
+       'mwe-apiproxy-setup' => 'Configuration du proxy API',
+       'mwe-load-drag-item' => 'Chargement de l’élément dépose',
+       'mwe-ok' => 'OK',
+       'mwe-cancel' => 'Annuler',
+       'mwe-setting-up-proxy' => 'Paramétrage du proxy...',
+       'mwe-re-try' => 'Réessayer la requête API',
+       'mwe-re-trying' => 'Nouvelle tentative de requête API...',
+       'mwe-proxy-not-ready' => 'Le proxy n’est pas configuré',
+       'mwe-please-login' => 'Vous n’êtes pas <a target="_new" href="$1">connecté</a> sur $2 ou mwEmbed n’a pas été activé. Corrigez le problème, puis retentez votre requête.',
+       'mwe-remember-loging' => 'Rappel de sécurité : ne vous connectez à un site internet que lorsque l’adresse de ce site est affichée dans votre barre d’adresse.',
+       'fogg-select_file' => 'Sélectionnez un fichier',
+       'fogg-select_new_file' => 'Sélectionnez un nouveau fichier',
+       'fogg-select_url' => 'Sélectionnez une URL',
+       'fogg-save_local_file' => 'Sauvegarder au format Ogg',
+       'fogg-check_for_firefogg' => 'Vérification de Firefogg ...',
+       'fogg-installed' => 'Firefogg est installé',
+       'fogg-for_improved_uploads' => 'Pour des téléversements améliorés :',
+       'fogg-please_install' => '<a href="$1">Installer Firefogg</a>. Plus d\'infos <a href="http://commons.wikimedia.org/wiki/Commons:Firefogg">sur Firefogg</a>',
+       'fogg-use_latest_firefox' => 'Veuillez d\'abord installer <a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=firefogg">Firefox 3.5</a> (ou plus récent). <i>Puis revenez sur cette page pour installer l\'extension <b>Firefogg</b>.</i>',
+       'fogg-passthrough_mode' => "Le fichier que vous avez sélectionné est déjà au format Ogg ou n'est pas un fichier vidéo",
+       'fogg-transcoding' => "Encodage d'une vidéo au format Ogg",
+       'fogg-encoding-done' => 'Encodage terminé',
+       'fogg-badtoken' => "Le jeton n'est pas valide",
+       'fogg-preview' => 'Prévisualiser la vidéo',
+       'fogg-hidepreview' => 'Masquer la prévisualisation',
+       'mwe-imported_from' => "$1 a importé depuis [$2 $3]. Voir la [$4 page de la ressource] originale pour plus d'information.",
+       'mwe-stream_title' => '$1 $2 vers $3',
+       'fogg-help-sticky' => 'Aide (cliquer pour maintenir)',
+       'fogg-cg-preset' => 'Prédéfini : <strong>$1</strong>',
+       'fogg-cg-quality' => 'Qualité basique et contrôle de la résolution',
+       'fogg-cg-meta' => 'Métadonnées pour le clip',
+       'fogg-cg-range' => "Portée de l'encodage",
+       'fogg-cg-advVideo' => "Contrôles avancée de l'encodage vidéo",
+       'fogg-cg-advAudio' => "Contrôles avancés de l'encodage audio",
+       'fogg-preset-custom' => 'Paramètres personnalisés',
+       'fogg-webvideo-desc' => 'Video web Theroa, Vorbis 400 kbit/s et 400px de largeur maximale',
+       'fogg-savebandwidth-desc' => 'Theora à bande passante faible, Vorbis 164 kbit/s et 200px de largeur maximale',
+       'fogg-highquality-desc' => 'Theora à haute qualité, Vorbis 1080px de largeur maximale',
+       'fogg-videoQuality-title' => 'Qualité vidéo',
+       'fogg-videoQuality-help' => 'Utilisé pour définir la <i>qualité visuelle</i> de la vidéo encodée (non utilisé si vous définissez le débit binaire dans les contrôles avancés ci-dessous).',
+       'fogg-starttime-title' => 'Seconde de début',
+       'fogg-starttime-help' => "Encoder seulement à partir d'une durée en secondes",
+       'fogg-endtime-title' => 'Seconde de fin',
+       'fogg-endtime-help' => 'Encoder seulement vers une durée en secondes',
+       'fogg-audioQuality-title' => 'Qualité audio',
+       'fogg-audioQuality-help' => "Utilisé pour définir la <i>qualité acoustique</i> de l'audio encodé (non utilisé si vous définissez le débit binaire dans les contrôles avancés ci-dessous).",
+       'fogg-videoCodec-title' => 'Codec vidéo',
+       'fogg-videoCodec-help' => 'Utilisé pour sélectionner le codec du clip vidéo. Actuellement, seul Theora est disponible. Plus d\'infos sur le <a target="_new" href="http://fr.wikipedia.org/wiki/Theora">codec Theora</a>.',
+       'fogg-audioCodec-title' => 'Codec audio',
+       'fogg-audioCodec-help' => 'Utilisé pour définir le codec du clip audio. Actuellement, seul Vorbis est disponible. Plus d\'infos sur le <a target="_new" href="http://fr.wikipedia.org/wiki/Vorbis">codec Vorbis</a>.',
+       'fogg-width-title' => 'Largeur de la vidéo',
+       'fogg-width-help' => 'Redimensionner à la largeur spécifiée.',
+       'fogg-height-title' => 'Hauteur de la vidéo',
+       'fogg-height-help' => 'Redimensionner à la hauteur spécifiée.',
+       'fogg-videoBitrate-title' => 'Débit binaire de la vidéo',
+       'fogg-videoBitrate-help' => "Le débit binaire de la vidéo définit le débit de l'encodage pour la vidéo en kb/s",
+       'fogg-twopass-title' => 'Encodage à deux passes',
+       'fogg-twopass-help' => "L'encodage à deux passes permet une qualité plus constante en effectuant deux parcours du fichier vidéo",
+       'fogg-framerate-title' => "Fréquence d'images",
+       'fogg-framerate-help' => 'Le nombre d\'images par seconde de la vidéo. Plus d\'infos sur <a target="_new" href="http://fr.wikipedia.org/wiki/Images_par_seconde">la fréquence d\'images</a>.',
+       'fogg-aspect-title' => 'Rapport largeur/hauteur',
+       'fogg-aspect-help' => 'Le rapport largeur/hauteur de la vidéo peut être une fraction 4:3 ou 16:9. Plus d\'infos sur <a target="_new" href="http://fr.wikipedia.org/wiki/Rapport_largeur/hauteur">les rapports largeur/hauteur</a>.',
+       'fogg-keyframeInterval-title' => 'Intervalle des images-clés',
+       'fogg-keyframeInterval-help' => "L'intervalle des images-clés dans les images. Note : la plupart des codecs imposent les images-clés si la différence entre les images est plus grande que la taille d'encodage de l'image-clé. Plus d'infos sur <a href=\"http://en.wikipedia.org/wiki/Video_compression_picture_types\">les images-clés</a>.",
+       'fogg-denoise-title' => 'Filtre anti-bruit',
+       'fogg-denoise-help' => 'Débruitage de la vidéo en entrée. Plus d\'infos sur <a href="http://en.wikipedia.org/wiki/Video_denoising">débruitage</a>.',
+       'fogg-novideo-title' => 'Pas de vidéo',
+       'fogg-novideo-help' => 'désactiver la vidéo dans la sortie',
+       'fogg-audioBitrate-title' => 'Débit binaire audio',
+       'fogg-samplerate-title' => "Taux d'échantillonnage audio",
+       'fogg-samplerate-help' => "définir le taux d'échantillonnage de la sortie (en Hz).",
+       'fogg-noaudio-title' => "Pas d'audio",
+       'fogg-noaudio-help' => "désactiver l'audio dans la sortie",
+       'fogg-title-title' => 'Titre',
+       'fogg-title-help' => 'Un titre pour votre clip',
+       'fogg-artist-title' => 'Nom du créateur',
+       'fogg-artist-help' => 'Le créateur de ce clip',
+       'fogg-date-title' => 'Date',
+       'fogg-date-help' => 'La date à laquelle le métrage a été créé ou publié',
+       'fogg-location-title' => 'Localisation',
+       'fogg-location-help' => 'La localisation du métrage',
+       'fogg-organization-title' => 'Société',
+       'fogg-organization-help' => 'Nom de la société (studio)',
+       'fogg-copyright-title' => 'Copyright',
+       'fogg-copyright-help' => 'Le copyright du clip',
+       'fogg-license-title' => 'Licence',
+       'fogg-license-help' => 'La licence de ce clip (préférablement une URL Creative Commons).',
+       'fogg-contact-title' => 'Contact',
+       'fogg-contact-help' => 'Lien du contact',
+       'mwe-add_media_wizard' => "Assistant d'ajout de média",
+       'mwe-media_search' => 'Recherche de média',
+       'rsd_box_layout' => 'Disposition de la boîte',
+       'rsd_list_layout' => 'Disposition de la liste',
+       'rsd_results_desc' => 'Résultats $1 à $2',
+       'rsd_results_desc_total' => 'Résultats $1 à $2 de $3',
+       'rsd_results_next' => 'suivant',
+       'rsd_results_prev' => 'précédent',
+       'rsd_no_results' => 'Aucun résultat pour <b>$1</b>',
+       'mwe-upload_tab' => 'Téléversement',
+       'rsd_layout' => 'Apparence :',
+       'rsd_resource_edit' => 'Modifier la ressource : $1',
+       'mwe-resource_description_page' => 'Page de description de la ressource',
+       'mwe-link' => 'lien',
+       'rsd_local_resource_title' => 'Titre de la ressource locale',
+       'rsd_do_insert' => "Faire l'insertion",
+       'mwe-cc_by_title' => 'Attribution',
+       'mwe-cc_nc_title' => 'Non commercial',
+       'mwe-cc_nd_title' => 'Pas de travaux dérivés',
+       'mwe-cc_sa_title' => "Partage à l'identique",
+       'mwe-cc_pd_title' => 'Domaine public',
+       'mwe-unknown_license' => 'Licence inconnue',
+       'mwe-no_import_by_url' => 'Cet utilisateur ou ce wiki <b>ne peut pas</b> importer des assets depuis les URLs distantes.<p>Avez-vous besoin de vous connecter ?</p><p>Est-ce que vous disposez de la permission \'\'upload_by_url\'\' ?<br />Est-ce que <a href="http://www.mediawiki.org/wiki/Manual:$wgAllowCopyUploads">$wgAllowCopyUploads</a> est activé sur le wiki ?</p>',
+       'mwe-results_from' => 'Résultats depuis <a href="$1" target="_new" >$2</a>',
+       'mwe-missing_desc_see_source' => "Il manque une description pour cet asset. Consultez la [$1 source d'origine] et aidez à le décrire.",
+       'rsd_config_error' => "Erreur de configuration de l'assistant d'ajout de média : $1",
+       'mwe-your_recent_uploads' => 'Vos derniers téléversements sur $1',
+       'mwe-upload_a_file' => 'Téléverser un nouveau fichier sur $1',
+       'mwe-resource_page_desc' => 'Page de  description de la ressource :',
+       'mwe-edit_resource_desc' => 'Modifier le wiki texte de la description de la ressource :',
+       'mwe-local_resource_title' => 'Titre de la ressource locale :',
+       'mwe-watch_this_page' => 'Suivre cette page',
+       'mwe-do_import_resource' => 'Importer la ressource',
+       'mwe-update_preview' => 'Mettre à jour la prévisualisation',
+       'mwe-cancel_import' => "Annuler l'importation",
+       'mwe-importing_asset' => "Import de l'asset",
+       'mwe-preview_insert_resource' => "Prévisualiser l'insertion de la ressource : $1",
+       'mwe-checking-resource' => 'Vérification de la ressource',
+       'mwe-resource-needs-import' => 'La ressource $1 doit être importée sur $2',
+       'mwe-ftype-svg' => 'Fichier vectoriel SVG',
+       'mwe-ftype-jpg' => 'Fichier image JPEG',
+       'mwe-ftype-png' => 'Fichier image PNG',
+       'mwe-ftype-oga' => 'Fichier audio Ogg',
+       'mwe-ftype-ogg' => 'Fichier vidéo Ogg',
+       'mwe-ftype-unk' => 'Format de fichier inconnu',
+       'rsd-wiki_commons-title' => 'Wikimedia Commons',
+       'rsd-wiki_commons' => 'Wikimedia Commons, un dépôt de contenu pédagogique sous licence libre (images, clips audio et vidéo)',
+       'rsd-this_wiki-title' => 'Ce wiki',
+       'rsd-this_wiki-desc' => 'Le wiki local',
+       'rsd-archive_org-desc' => 'L’Internet Archive, une bibliothèque numérique d’objets culturels',
+       'rsd-flickr-desc' => 'Flicr.com, un site de partage de photo en ligne',
+       'rsd-metavid-desc' => 'Metavid.org, une archive communautaire des séances de la chambre des représentants et du sénat des États-Unis',
+       'mwe-select_file' => 'Sélectionnez un fichier',
+       'mwe-more_licence_options' => 'Pour plus d\'options de licences, consultez la <a href="$1">page de téléversement normal</a>',
+       'mwe-select_ownwork' => 'Je téléverse uniquement mes propres œuvres, et les place sous licence :',
+       'mwe-licence_cc-by-sa' => "Creative Commons Partage à l'identique (3.0)",
+       'mwe-upload' => 'Téléverser un fichier',
+       'mwe-destfilename' => 'Nom du fichier de destination :',
+       'mwe-summary' => 'Résumé',
+       'mwe-error_not_loggedin' => "Il semble que vous ne soyez pas connecté ou que vous n'ayez pas le droit de téléverser.",
+       'mwe-watch-this-file' => 'Suivre ce fichier',
+       'mwe-ignore-any-warnings' => 'Ignorer les avertissements',
+       'mwe-upload-transcode-in-progress' => 'Transcodage et téléversement en cours (ne pas fermer cette fenêtre)',
+       'mwe-upload-in-progress' => 'Téléversement en cours (ne pas fermer cette fenêtre)',
+       'mwe-upload-transcoded-status' => 'Transcodé',
+       'mwe-uploaded-status' => 'Téléversé',
+       'mwe-upload-stats-fileprogress' => '$1 de $2',
+       'mwe-upload_completed' => 'Votre téléversement est terminé',
+       'mwe-upload_done' => '<a href="$1">Votre téléversement <i>devrait être</i> accessible</a>.',
+       'mwe-upload-unknown-size' => 'Taille inconnue',
+       'mwe-cancel-confim' => 'Êtes-vous sûr de vouloir annuler ?',
+       'mwe-successfulupload' => 'Téléversement réussi',
+       'mwe-uploaderror' => 'Erreur lors du téléversement',
+       'mwe-uploadwarning' => 'Avertissement lors du téléversement',
+       'mwe-unknown-error' => 'Erreur inconnue :',
+       'mwe-return-to-form' => 'Retourner au formulaire',
+       'mwe-file-exists-duplicate' => 'Ce fichier est un doublon du fichier suivant :',
+       'mwe-fileexists' => "Un fichier existe déjà sous ce nom. Veuillez vérifier <b><tt>$1</tt></b> si vous n'êtes pas sûr de vouloir le changer.",
+       'mwe-fileexists-thumb' => '<center><b>Fichier existant</b></center>',
+       'mwe-ignorewarning' => "Ignorer l'avertissement et sauvegarder le fichier quand même",
+       'mwe-file-thumbnail-no' => 'Le nom de fichier commence par <b><tt>$1</tt></b>',
+       'mwe-go-to-resource' => 'Aller à la page de la ressource',
+       'mwe-upload-misc-error' => 'Erreur inconnue lors du téléversement',
+       'mwe-wgfogg_warning_bad_extension' => 'Vous avez sélectionné un fichier qui comporte une extension non supportée (<a href="http://commons.wikimedia.org/wiki/Commons:Firefogg#Supported_File_Types">plus d\'informations</a>).',
+       'mwe-upload-multi' => 'Téléverser {{PLURAL:$1|le fichier|les fichiers}}',
+       'mwe-review-upload' => 'Vérifier {{PLURAL:$1|le téléversement de fichier|les téléversements de fichiers}}',
+       'mwe-credit-title' => 'Titre : $1',
+       'mwe-loading_plugin' => 'chargement du greffon ...',
+       'mwe-select_playback' => 'Définir les préférences de lecture',
+       'mwe-link_back' => 'Lien retour',
+       'mwe-error_swap_vid' => "Erreur : mv_embed n'a pas réussi à échanger l'attribut de la vidéo pour l'interface mv_embed",
+       'mwe-add_to_end_of_sequence' => 'Ajouter à la fin de la séquence',
+       'mwe-missing_video_stream' => 'Le fichier vidéo pour ce flux est manquant',
+       'mwe-play_clip' => 'Lire le clip',
+       'mwe-pause_clip' => 'Mettre le clip en pause',
+       'mwe-volume_control' => 'Contrôle du volume',
+       'mwe-player_options' => 'Options du lecteur',
+       'mwe-closed_captions' => 'Sous-titres',
+       'mwe-player_fullscreen' => 'Plein écran',
+       'mwe-next_clip_msg' => 'Lire le clip suivant',
+       'mwe-prev_clip_msg' => 'Lire le clip précédent',
+       'mwe-current_clip_msg' => 'Poursuivre la lecture de ce clip',
+       'mwe-seek_to' => 'Atteindre $1',
+       'mwe-paused' => 'en pause',
+       'mwe-download_segment' => 'Télécharger la sélection :',
+       'mwe-download_full' => 'Télécharger le fichier de la vidéo complète :',
+       'mwe-download_right_click' => 'Pour télécharger, cliquez-droit et sélectionnez <i>Enregistrer la cible du lien sous...</i>',
+       'mwe-download_clip' => 'Télécharger la vidéo',
+       'mwe-download_text' => 'Télécharger le texte (<a style="color:white" title="cmml" href="http://wiki.xiph.org/index.php/CMML">CMML</a> xml) :',
+       'mwe-download' => 'Télécharger',
+       'mwe-share' => 'Partager',
+       'mwe-credits' => 'Crédits',
+       'mwe-clip_linkback' => 'Page source du clip',
+       'mwe-chose_player' => 'Choisir le lecteur vidéo',
+       'mwe-share_this_video' => 'Partager cette vidéo',
+       'mwe-video_credits' => 'Crédits de la vidéo',
+       'mwe-menu_btn' => 'Menu',
+       'mwe-close_btn' => 'Fermer',
+       'mwe-ogg-player-vlc-player' => 'Lecteur VLC',
+       'mwe-ogg-player-videoElement' => 'Vidéo Ogg en natif',
+       'mwe-ogg-player-oggPlugin' => 'Module générique Ogg',
+       'mwe-ogg-player-quicktime-mozilla' => 'Module QuickTime',
+       'mwe-ogg-player-quicktime-activex' => 'ActiveX QuickTime',
+       'mwe-ogg-player-cortado' => 'Java Cortado',
+       'mwe-ogg-player-flowplayer' => 'Flowplayer',
+       'mwe-ogg-player-kplayer' => 'Lecteur Kaltura',
+       'mwe-ogg-player-selected' => '(sélectionné)',
+       'mwe-ogg-player-omtkplayer' => 'OMTK Flash Vorbis',
+       'mwe-generic_missing_plugin' => 'Votre navigateur ne semble pas compatible avec le type de lecture suivant : <b>$1</b><br />Visitez la page des <a href="http://commons.wikimedia.org/wiki/Commons:Media_help">méthodes de visionnage</a> pour télécharger un lecteur.<br />',
+       'mwe-for_best_experience' => 'Pour un meilleur visionnage nous recommandons :<br /><b><a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=mwEmbed">Firefox 3.5</a>.</b>',
+       'mwe-do_not_warn_again' => 'Interrompre pour le moment.',
+       'mwe-playerselect' => 'Lecteurs',
+       'mwe-read_before_embed' => 'Veuillez <a href="http://mediawiki.org/wiki/Security_Notes_on_Remote_Embedding" target="_new">lire ceci</a> avant de procéder !',
+       'mwe-embed_site_or_blog' => 'Intégrer dans une page',
+       'mwe-related_videos' => 'Vidéos associées',
+       'mwe-seeking' => 'recherche',
+       'mwe-copy-code' => 'Copier le code',
+       'mwe-video-h264' => 'vidéo H.264',
+       'mwe-video-flv' => 'vidéo Flash',
+       'mwe-video-ogg' => 'vidéo Ogg',
+       'mwe-video-audio' => 'Audio Ogg',
+);
+
+/** Galician (Galego)
+ * @author McDutchie
+ * @author Toliño
+ */
+$messages['gl'] = array(
+       'mwe-crop' => 'Cortar a imaxe',
+       'mwe-apply_crop' => 'Aplicar o corte á imaxe',
+       'mwe-reset_crop' => 'Restablecer o corte',
+       'mwe-insert_image_page' => 'Inserir na páxina',
+       'mwe-insert_into_sequence' => 'Inserir na secuencia',
+       'mwe-preview_insert' => 'Vista previa da inserción',
+       'mwe-cancel_image_insert' => 'Cancelar a inserción',
+       'mwe-sc_fileopts' => 'Editar os detalles do vídeo',
+       'mwe-sc_inoutpoints' => 'Establecer os puntos de entrada-saída',
+       'mwe-sc_overlays' => 'Sobreposicións',
+       'mwe-sc_audio' => 'Control de audio',
+       'mwe-sc_duration' => 'Duración',
+       'mwe-template_properties' => 'Propiedades do modelo',
+       'mwe-custom_title' => 'Título personalizado',
+       'mwe-edit_properties' => 'Editar as propiedades',
+       'mwe-other_properties' => 'Outras propiedades',
+       'mwe-resource_page' => 'Páxina de recursos:',
+       'mwe-set_in_out_points' => 'Establecer os puntos de entrada-saída',
+       'mwe-start_time' => 'Hora de inicio',
+       'mwe-end_time' => 'Hora de fin',
+       'mwe-preview_inout' => 'Vista previa dos puntos de entrada-saída',
+       'mwe-edit-tools' => 'Ferramentas de edición',
+       'mwe-inline-description' => 'Lenda',
+       'mwe-edit-video-tools' => 'Ferramentas de edición de vídeo:',
+       'mwe-duration' => 'Duración:',
+       'mwe-upload-subs-file' => 'Cargar un subtítulo',
+       'mwe-add-subs-file-title' => 'Seleccione os subtítulos a cargar',
+       'mwe-error-only-srt' => 'Nestes intres só se poden cargar ficheiros srt.',
+       'mwe-watch-video' => 'Reproducir o vídeo',
+       'mwe-select-other-language' => 'Seleccionar outra lingua',
+       'mwe-saving' => 'gardando...',
+       'mwe-select_transcript_set' => 'Seleccionar os subtítulos',
+       'mwe-auto_scroll' => 'desprazamento automático',
+       'mwe-close' => 'pechar',
+       'mwe-improve_transcript' => 'Mellorar',
+       'mwe-no_text_tracks_found' => 'Non se atopou ningunha pista de texto',
+       'mwe-add-edit-subs' => 'Engadir/editar subtítulos',
+       'mwe-transition_in' => 'Transición de entrada',
+       'mwe-transition_out' => 'Transición de saída',
+       'mwe-effects' => 'Pila de efectos',
+       'mwe-remove_transition' => 'Eliminar a transición',
+       'mwe-edit_transin' => 'Editar a transición no vídeo',
+       'mwe-edit_transout' => 'Editar a transición fóra do vídeo',
+       'mwe-add-transition' => 'Engadir unha transición',
+       'mwe-menu_clipedit' => 'Editar o soporte',
+       'mwe-menu_transition' => 'Transicións e efectos',
+       'mwe-menu_cliplib' => 'Engadir un soporte',
+       'mwe-menu_resource_overview' => 'Vista xeral dos recursos',
+       'mwe-menu_options' => 'Opcións',
+       'mwe-loading_timeline' => 'Cargando a liña do tempo...',
+       'mwe-loading_user_rights' => 'Cargando os dereitos de usuario...',
+       'mwe-no_edit_permissions' => 'Non ten os permisos necesarios para gardar os cambios feitos nesta secuencia',
+       'mwe-edit_clip' => 'Editar o vídeo',
+       'mwe-edit_save' => 'Gardar os cambios feitos na secuencia',
+       'mwe-saving_wait' => 'Gardando (por favor, espere)',
+       'mwe-save_done' => 'Gardado',
+       'mwe-edit_cancel' => 'Cancelar a edición da secuencia',
+       'mwe-edit_cancel_confirm' => 'Está seguro de querer cancelar a súa edición? Perderanse todos os cambios feitos.',
+       'mwe-zoom_in' => 'Ampliar',
+       'mwe-zoom_out' => 'Reducir',
+       'mwe-cut_clip' => 'Cortar os vídeos',
+       'mwe-expand_track' => 'Expandir a pista',
+       'mwe-collapse_track' => 'Contraer a pista',
+       'mwe-play_from_position' => 'Reproducir desde a posición de lectura',
+       'mwe-pixle2sec' => 'píxeles a segundos',
+       'mwe-rmclip' => 'Eliminar o vídeo',
+       'mwe-clip_in' => 'achegar',
+       'mwe-clip_out' => 'separar',
+       'mwe-no_selected_resource' => '<h3>Non se seleccionou ningún recurso</h3> Seleccione un vídeo para permitir a edición.',
+       'mwe-error_edit_multiple' => '<h3>Seleccionáronse varios recursos</h3> Seleccione soamente un vídeo para editalo.',
+       'mwe-editor_options' => 'Opcións do editor',
+       'mwe-editor_mode' => 'Modo do editor',
+       'mwe-simple_editor_desc' => 'editor simple (estilo iMovie)',
+       'mwe-advanced_editor_desc' => 'editor avanzado (estilo Final Cut)',
+       'mwe-other_options' => 'Outras opcións',
+       'mwe-contextmenu_opt' => 'Activar os menús contextuais',
+       'mwe-sequencer_credit_line' => 'Desenvolvido por <a href="http://kaltura.com">Kaltura, Inc.</a> en colaboración coa <a href="http://wikimediafoundation.org/wiki/Portada_galega">Fundación Wikimedia</a> (<a href="#">máis información</a>).',
+       'mwe-loading_txt' => 'cargando...',
+       'mwe-error_load_lib' => 'Erro: o JavaScript $1 non se puido atopar ou non definía $2',
+       'mwe-loading-add-media-wiz' => 'Cargando o asistente de engadido de soportes',
+       'mwe-apiproxy-setup' => 'Configurando o proxy API',
+       'mwe-load-drag-item' => 'Cargando o elemento arrastrado',
+       'mwe-ok' => 'De acordo',
+       'mwe-cancel' => 'Cancelar',
+       'mwe-setting-up-proxy' => 'Configurando o proxy...',
+       'mwe-re-try' => 'Reintentar a solicitude API',
+       'mwe-re-trying' => 'Reintentando a solicitude API...',
+       'mwe-proxy-not-ready' => 'O proxy non está configurado',
+       'mwe-please-login' => 'Non <a target="_new" href="$1">accedeu ao sistema</a> de $2 ou o mwEmbed non está activado. Resolva o problema e intente de novo a solicitude.',
+       'mwe-remember-loging' => 'Advertencia de seguridade xeral: non acceda ao sistema de ningunha páxina web cando a súa barra de enderezos mostre outro enderezo que non se corresponda co dese sitio.',
+       'fogg-select_file' => 'Seleccione un ficheiro',
+       'fogg-select_new_file' => 'Seleccione un ficheiro novo',
+       'fogg-select_url' => 'Seleccione un enderezo URL',
+       'fogg-save_local_file' => 'Gardar en formato Ogg',
+       'fogg-check_for_firefogg' => 'Examinando en busca do Firefogg...',
+       'fogg-installed' => 'O Firefogg está instalado',
+       'fogg-for_improved_uploads' => 'Para cargas melloradas:',
+       'fogg-please_install' => '<a href="$1">Instalar o Firefogg</a>. Máis información <a href="http://commons.wikimedia.org/wiki/Commons:Firefogg">acerca do Firefogg</a>',
+       'fogg-use_latest_firefox' => 'Por favor, instale primeiro o <a href="http://gl.www.mozilla.com/gl/">Firefox 3.5</a> (ou superior). <i>Logo diso, volte a esta páxina para instalar a extensión <b>Firefogg</b>.</i>',
+       'fogg-passthrough_mode' => 'O ficheiro que seleccionou xa está en formato Ogg ou non é un ficheiro de vídeo',
+       'fogg-transcoding' => 'Codificando o vídeo en formato Ogg',
+       'fogg-encoding-done' => 'Codificación completa',
+       'fogg-badtoken' => 'O token non é válido',
+       'fogg-preview' => 'Vista previa do vídeo',
+       'fogg-hidepreview' => 'Agochar a vista previa',
+       'mwe-imported_from' => '$1 importou desde [$2 $3]. Olle a [$4 páxina de recursos] orixinal para obter máis información.',
+       'mwe-stream_title' => '$1 $2 a $3',
+       'fogg-help-sticky' => 'Axuda (faga clic para pegar)',
+       'fogg-cg-preset' => 'Prefixar: <strong>$1</strong>',
+       'fogg-cg-quality' => 'Calidade básica e control de resolución',
+       'fogg-cg-meta' => 'Metadatos do vídeo',
+       'fogg-cg-range' => 'Rango de codificación',
+       'fogg-cg-advVideo' => 'Controis avanzados de codificación de vídeo',
+       'fogg-cg-advAudio' => 'Controis avanzados de codificación de audio',
+       'fogg-preset-custom' => 'Configuracións personalizadas',
+       'fogg-webvideo-desc' => 'Vídeo web Theora, Vorbis 400 kbit/s e un máximo de 400px de ancho',
+       'fogg-savebandwidth-desc' => 'Ancho de banda baixo Theora, Vorbis 164 kbit/s e un máximo de 200px de ancho',
+       'fogg-highquality-desc' => 'Theora de alta calidade, Vorbis 1080px de ancho máximo',
+       'fogg-videoQuality-title' => 'Calidade do vídeo',
+       'fogg-videoQuality-help' => 'Empregado para definir a <i>calidade visual</i> do vídeo codificado (non se usa se define a taxa de bits nos controis avanzados de embaixo).',
+       'fogg-starttime-title' => 'Segundo de inicio',
+       'fogg-starttime-help' => 'Codificar só a partir dun tempo en segundos',
+       'fogg-endtime-title' => 'Segundo de fin',
+       'fogg-endtime-help' => 'Codificar só ata un tempo en segundos',
+       'fogg-audioQuality-title' => 'Calidade do son',
+       'fogg-audioQuality-help' => 'Empregado para definir a <i>calidade acústica</i> do son codificado (non se usa se define a taxa de bits nos controis avanzados de embaixo).',
+       'fogg-videoCodec-title' => 'Códec do vídeo',
+       'fogg-videoCodec-help' => 'Empregado para seleccionar o códec do vídeo. Actualmente, só Theora é compatible. Máis información sobre o <a target="_new" href="http://en.wikipedia.org/wiki/Theora">códec Theora</a>.',
+       'fogg-audioCodec-title' => 'Códec do son',
+       'fogg-audioCodec-help' => 'Empregado para definir o códec do son. Actualmente, só Vorbis é compatible. Máis información sobre o <a target="_new" href="http://en.wikipedia.org/wiki/Vorbis">códec Vorbis</a>.',
+       'fogg-width-title' => 'Ancho do vídeo',
+       'fogg-width-help' => 'Redimensionar ao ancho dado.',
+       'fogg-height-title' => 'Altura do vídeo',
+       'fogg-height-help' => 'Redimensionar á altura dada.',
+       'fogg-videoBitrate-title' => 'Taxa de bits do vídeo',
+       'fogg-videoBitrate-help' => 'A taxa de bits do vídeo define a taxa de bits da codificación do vídeo en kb/s',
+       'fogg-twopass-title' => 'Codificación en dous pasos',
+       'fogg-twopass-help' => 'A codificación en dous pasos permite obter unha calidade máis constante facendo dúas pasaxes sobre o ficheiro de vídeo',
+       'fogg-framerate-title' => 'Taxa de fotogramas',
+       'fogg-framerate-help' => 'A taxa de fotogramas. Máis información sobre a <a target="_new" href="http://en.wikipedia.org/wiki/Frame_rate">taxa de fotogramas</a>.',
+       'fogg-aspect-title' => 'Proporción de aspecto',
+       'fogg-aspect-help' => 'A proporción de aspecto do vídeo pode ser tanto a fracción 4:3 como 16:9. Máis información sobre a <a target="_new" href="http://en.wikipedia.org/wiki/Aspect_ratio_%28image%29">proporción de aspecto</a>.',
+       'fogg-keyframeInterval-title' => 'Intervalo de cadros clave',
+       'fogg-keyframeInterval-help' => 'O intervalo de cadros clave nos fotogramas. Nota: a meirande parte dos codecs forzan os cadros clave se a diferenza entre os fotogramas é maior que o tamaño da codificación dos cadros clave. Máis información sobre os <a href="http://en.wikipedia.org/wiki/I-frame">cadros clave</a>.',
+       'fogg-denoise-title' => 'Filtro redutor de ruído',
+       'fogg-denoise-help' => 'Reducir o ruído do vídeo. Máis información sobre a <a href="http://en.wikipedia.org/wiki/Video_denoising">redución de ruído</a>.',
+       'fogg-novideo-title' => 'Sen vídeo',
+       'fogg-novideo-help' => 'desactivar o vídeo na saída',
+       'fogg-audioBitrate-title' => 'Taxa de bits do son',
+       'fogg-samplerate-title' => 'Taxa de mostraxe do son',
+       'fogg-samplerate-help' => 'definir a taxa de mostraxe de saída (en Hz).',
+       'fogg-noaudio-title' => 'Sen son',
+       'fogg-noaudio-help' => 'desactivar o son na saída',
+       'fogg-title-title' => 'Título',
+       'fogg-title-help' => 'Un título para o seu vídeo',
+       'fogg-artist-title' => 'Nome do creador',
+       'fogg-artist-help' => 'O creador deste vídeo',
+       'fogg-date-title' => 'Data',
+       'fogg-date-help' => 'A data en que a metraxe foi creada ou publicada',
+       'fogg-location-title' => 'Localización',
+       'fogg-location-help' => 'Localización da metraxe',
+       'fogg-organization-title' => 'Organización',
+       'fogg-organization-help' => 'Nome da organización (estudio)',
+       'fogg-copyright-title' => 'Dereitos de autor',
+       'fogg-copyright-help' => 'Os dereitos de autor do vídeo',
+       'fogg-license-title' => 'Licenza',
+       'fogg-license-help' => 'A licenza do vídeo (preferiblemente un URL Creative Commons).',
+       'fogg-contact-title' => 'Contacto',
+       'fogg-contact-help' => 'Ligazón de contacto',
+       'mwe-add_media_wizard' => 'Asistente para engadir medios',
+       'mwe-media_search' => 'Procura de medios',
+       'rsd_box_layout' => 'Disposición da caixa',
+       'rsd_list_layout' => 'Disposición da lista',
+       'rsd_results_desc' => 'Resultados do $1 ao $2',
+       'rsd_results_desc_total' => 'Resultados do $1 ao $2 dun total de $3',
+       'rsd_results_next' => 'seguinte',
+       'rsd_results_prev' => 'anterior',
+       'rsd_no_results' => 'Non hai resultados de busca para "<b>$1</b>"',
+       'mwe-upload_tab' => 'Cargar',
+       'rsd_layout' => 'Disposición:',
+       'rsd_resource_edit' => 'Editar o recurso: $1',
+       'mwe-resource_description_page' => 'Páxina de descrición do recurso',
+       'mwe-link' => 'ligazón',
+       'rsd_local_resource_title' => 'Título do recurso local',
+       'rsd_do_insert' => 'Facer a inserción',
+       'mwe-cc_by_title' => 'Recoñecemento',
+       'mwe-cc_nc_title' => 'Non comercial',
+       'mwe-cc_nd_title' => 'Non obras derivadas',
+       'mwe-cc_sa_title' => 'Compartir igual',
+       'mwe-cc_pd_title' => 'Dominio público',
+       'mwe-unknown_license' => 'Licenza descoñecida',
+       'mwe-no_import_by_url' => 'Este usuario ou wiki <b>non pode</b> importar valores desde enderezos URL remotos.<p>Necesita acceder ao sistema?</p><p>Dispón dos permisos "upload_by_url"?<br />Ten o wiki activada a función <a href="http://www.mediawiki.org/wiki/Manual:$wgAllowCopyUploads">$wgAllowCopyUploads</a>?</p>',
+       'mwe-results_from' => 'Resultados desde <a href="$1" target="_new" >$2</a>',
+       'mwe-missing_desc_see_source' => 'A este valor fáltalle unha descrición. Por favor, olle a [$1 fonte orixinal] e axude a describilo.',
+       'rsd_config_error' => 'Erro de configuración do asistente para engadir medios: $1',
+       'mwe-your_recent_uploads' => 'As súas cargas recentes en $1',
+       'mwe-upload_a_file' => 'Cargar un novo ficheiro en $1',
+       'mwe-resource_page_desc' => 'Páxina de descrición do recurso:',
+       'mwe-edit_resource_desc' => 'Editar o texto wiki da descrición do recurso:',
+       'mwe-local_resource_title' => 'Título do recurso local:',
+       'mwe-watch_this_page' => 'Vixiar esta páxina',
+       'mwe-do_import_resource' => 'Importar o recurso',
+       'mwe-update_preview' => 'Actualizar a vista previa',
+       'mwe-cancel_import' => 'Cancelar a importación',
+       'mwe-importing_asset' => 'Importación do valor',
+       'mwe-preview_insert_resource' => 'Vista previa da inserción do recurso: $1',
+       'mwe-checking-resource' => 'Comprobando os recursos',
+       'mwe-resource-needs-import' => 'O recurso $1 necesita ser importado en $2',
+       'mwe-ftype-svg' => 'Ficheiro vectorial SVG',
+       'mwe-ftype-jpg' => 'Ficheiro de imaxe JPEG',
+       'mwe-ftype-png' => 'Ficheiro de imaxe PNG',
+       'mwe-ftype-oga' => 'Ficheiro de son Ogg',
+       'mwe-ftype-ogg' => 'Ficheiro de vídeo Ogg',
+       'mwe-ftype-unk' => 'Formato de ficheiro descoñecido',
+       'rsd-wiki_commons-title' => 'Wikimedia Commons',
+       'rsd-wiki_commons' => 'Wikimedia Commons, un depósito de contidos multimedia educativos e libres de licenza (imaxes, sons e vídeos)',
+       'rsd-this_wiki-title' => 'Este wiki',
+       'rsd-this_wiki-desc' => 'A instalación do wiki local',
+       'rsd-archive_org-desc' => 'O Internet Archive, unha biblioteca dixital de artefactos culturais',
+       'rsd-flickr-desc' => 'Flickr.com, unha páxina web onde compartir fotos en liña',
+       'rsd-metavid-desc' => 'Metavid.org, un depósito comunitario das reunións na Cámara e mais no Senado dos EUA',
+       'mwe-select_file' => 'Seleccione un ficheiro',
+       'mwe-more_licence_options' => 'Para máis opcións de licenza, consulte a <a href="$1">páxina de carga normal</a>',
+       'mwe-select_ownwork' => 'Estou a cargar unicamente as miñas propias obras, baixo a licenza:',
+       'mwe-licence_cc-by-sa' => 'Creative Commons Share Alike (3.0)',
+       'mwe-upload' => 'Cargar un ficheiro',
+       'mwe-destfilename' => 'Nome do ficheiro de destino:',
+       'mwe-summary' => 'Resumo',
+       'mwe-error_not_loggedin' => 'Parece non ter accedido ao sistema ou non ter privilexios de carga.',
+       'mwe-watch-this-file' => 'Vixiar este ficheiro',
+       'mwe-ignore-any-warnings' => 'Ignorar os avisos',
+       'mwe-upload-transcode-in-progress' => 'Transcodificación e carga en curso (non peche esta ventá)',
+       'mwe-upload-in-progress' => 'Carga en progreso (non peche esta ventá)',
+       'mwe-upload-transcoded-status' => 'Transcodificado',
+       'mwe-uploaded-status' => 'Cargado',
+       'mwe-upload-stats-fileprogress' => '$1 de $2',
+       'mwe-upload_completed' => 'Completouse a súa carga',
+       'mwe-upload_done' => '<a href="$1">A súa carga <i>debería ser</i> accesible</a>.',
+       'mwe-upload-unknown-size' => 'Tamaño descoñecido',
+       'mwe-cancel-confim' => 'Está seguro de querer cancelar?',
+       'mwe-successfulupload' => 'Carga exitosa',
+       'mwe-uploaderror' => 'Erro ao cargar',
+       'mwe-uploadwarning' => 'Advertencia ao cargar',
+       'mwe-unknown-error' => 'Erro descoñecido:',
+       'mwe-return-to-form' => 'Voltar ao formulario',
+       'mwe-file-exists-duplicate' => 'Este ficheiro é un duplicado destoutro:',
+       'mwe-fileexists' => 'Xa existe un ficheiro con ese nome. Por favor, verifique <b><tt>$1</tt></b> se non está seguro de que quere cambialo.',
+       'mwe-fileexists-thumb' => '<center><b>Ficheiro existente</b></center>',
+       'mwe-ignorewarning' => 'Ignorar a advertencia e gardar o ficheiro de calquera xeito',
+       'mwe-file-thumbnail-no' => 'O nome do ficheiro comeza por <b><tt>$1</tt></b>',
+       'mwe-go-to-resource' => 'Ir á páxina do recurso',
+       'mwe-upload-misc-error' => 'Erro de carga descoñecido',
+       'mwe-wgfogg_warning_bad_extension' => 'Seleccionou un ficheiro cunha extensión non soportada (<a href="http://commons.wikimedia.org/wiki/Commons:Firefogg#Supported_File_Types">máis información</a>).',
+       'mwe-upload-multi' => 'Cargar {{PLURAL:$1|o ficheiro|os ficheiros}}',
+       'mwe-review-upload' => 'Revisar {{PLURAL:$1|a carga do ficheiro|as cargas dos ficheiros}}',
+       'mwe-credit-title' => 'Título: $1',
+       'mwe-loading_plugin' => 'cargando o complemento...',
+       'mwe-select_playback' => 'Configurar as preferencias de reprodución',
+       'mwe-link_back' => 'Ligazón de volta',
+       'mwe-error_swap_vid' => 'Erro: mv_embed foi incapaz de cambiar a etiqueta do vídeo para a interface mv_embed',
+       'mwe-add_to_end_of_sequence' => 'Engadir ao final da secuencia',
+       'mwe-missing_video_stream' => 'Falta o ficheiro de vídeo para ese fluxo',
+       'mwe-play_clip' => 'Reproducir o vídeo',
+       'mwe-pause_clip' => 'Pór o vídeo en pausa',
+       'mwe-volume_control' => 'Control do volume',
+       'mwe-player_options' => 'Opcións do reprodutor',
+       'mwe-closed_captions' => 'Subtítulos',
+       'mwe-player_fullscreen' => 'Pantalla completa',
+       'mwe-next_clip_msg' => 'Reproducir o seguinte vídeo',
+       'mwe-prev_clip_msg' => 'Reproducir o vídeo anterior',
+       'mwe-current_clip_msg' => 'Continuar a reprodución deste vídeo',
+       'mwe-seek_to' => 'Buscar $1',
+       'mwe-paused' => 'en pausa',
+       'mwe-download_segment' => 'Descargar a selección:',
+       'mwe-download_full' => 'Descargar o ficheiro de vídeo completo:',
+       'mwe-download_right_click' => 'Para descargar, faga clic dereito e seleccione <i>Gardar a ligazón como...</i>',
+       'mwe-download_clip' => 'Descargar o vídeo',
+       'mwe-download_text' => 'Descargar o texto (<a style="color:white" title="cmml" href="http://wiki.xiph.org/index.php/CMML">CMML</a> xml):',
+       'mwe-download' => 'Descargar',
+       'mwe-share' => 'Compartir',
+       'mwe-credits' => 'Créditos',
+       'mwe-clip_linkback' => 'Páxina de orixe do vídeo',
+       'mwe-chose_player' => 'Escolla o reprodutor de vídeo',
+       'mwe-share_this_video' => 'Compartir este vídeo',
+       'mwe-video_credits' => 'Créditos do vídeo',
+       'mwe-menu_btn' => 'Menú',
+       'mwe-close_btn' => 'Pechar',
+       'mwe-ogg-player-vlc-player' => 'Reprodutor VLC',
+       'mwe-ogg-player-videoElement' => 'Vídeo Ogg nativo',
+       'mwe-ogg-player-oggPlugin' => 'Complemento xenérico Ogg',
+       'mwe-ogg-player-quicktime-mozilla' => 'Complemento QuickTime',
+       'mwe-ogg-player-quicktime-activex' => 'ActiveX QuickTime',
+       'mwe-ogg-player-cortado' => 'Java Cortado',
+       'mwe-ogg-player-flowplayer' => 'Flowplayer',
+       'mwe-ogg-player-kplayer' => 'Reprodutor Kaltura',
+       'mwe-ogg-player-selected' => '(seleccionado)',
+       'mwe-ogg-player-omtkplayer' => 'OMTK Flash Vorbis',
+       'mwe-generic_missing_plugin' => 'Parece que o seu navegador non é compatible co tipo de reprodución: <b>$1</b><br />Visite a páxina de <a href="http://commons.wikimedia.org/wiki/Commons:Axuda multimedia">métodos de reprodución</a> para descargar un reprodutor.<br />',
+       'mwe-for_best_experience' => 'Para unha mellor experiencia de reprodución de vídeo, recomendamos:<br /><b><a href="http://gl.www.mozilla.com/gl">Firefox 3.5</a>.</b>',
+       'mwe-do_not_warn_again' => 'Agochar polo de agora.',
+       'mwe-playerselect' => 'Reprodutores',
+       'mwe-read_before_embed' => 'Por favor, <a href="http://mediawiki.org/wiki/Security_Notes_on_Remote_Embedding" target="_new">olle isto</a> antes da incrustación!',
+       'mwe-embed_site_or_blog' => 'Integrar nunha páxina',
+       'mwe-related_videos' => 'Vídeos relacionados',
+       'mwe-seeking' => 'procurando',
+       'mwe-copy-code' => 'Copiar o código',
+       'mwe-video-h264' => 'Vídeo H.264',
+       'mwe-video-flv' => 'Vídeo Flash',
+       'mwe-video-ogg' => 'Vídeo Ogg',
+       'mwe-video-audio' => 'Audio Ogg',
+);
+
+/** Ancient Greek (Ἀρχαία ἑλληνικὴ)
+ * @author Crazymadlover
+ * @author Omnipaedista
+ */
+$messages['grc'] = array(
+       'rsd_results_next' => 'ἑπομέναι',
+       'rsd_results_prev' => 'προηγούμεναι',
+       'mwe-upload' => 'Ἐπιφορτίζειν ἀρχεῖον',
+       'mwe-summary' => 'Σύνοψις',
+);
+
+/** Swiss German (Alemannisch)
+ * @author Als-Holder
+ * @author McDutchie
+ * @author Purodha
+ */
+$messages['gsw'] = array(
+       'mwe-crop' => 'Bild zueschnyde',
+       'mwe-apply_crop' => 'Bild zueschnyde',
+       'mwe-reset_crop' => 'Zueschnitt zrucksetze',
+       'mwe-insert_image_page' => 'In Syte yyfiege',
+       'mwe-insert_into_sequence' => 'In dr Abschnitt yyfiege',
+       'mwe-preview_insert' => 'Vorschau vu dr Yyfiegig',
+       'mwe-cancel_image_insert' => 'S Yyfiege ruckgängig mache',
+       'mwe-sc_fileopts' => 'Clipdetail bearbeite',
+       'mwe-sc_inoutpoints' => 'Aa-Uus-Pinkt setze',
+       'mwe-sc_overlays' => 'Overlays',
+       'mwe-sc_audio' => 'Audioyystellige',
+       'mwe-sc_duration' => 'Duur',
+       'mwe-template_properties' => 'Vorlageeigeschafte',
+       'mwe-custom_title' => 'Aapasste Titel',
+       'mwe-edit_properties' => 'Eigeschafte bearbeite',
+       'mwe-other_properties' => 'Andri Eigeschafte',
+       'mwe-resource_page' => 'Quällsyte:',
+       'mwe-set_in_out_points' => 'Aa-Uus-Pinkt setze',
+       'mwe-start_time' => 'Aafangszyt',
+       'mwe-end_time' => 'Ändzyt',
+       'mwe-preview_inout' => 'Vorschau vu dr Aa-Uus-Pinkt',
+       'mwe-edit-tools' => 'Bearbeitigs-Wärchzyyg',
+       'mwe-inline-description' => 'Bschryybig',
+       'mwe-edit-video-tools' => 'Video-Bearbeitigswärchzyyg:',
+       'mwe-duration' => 'Duur:',
+       'mwe-upload-subs-file' => 'Untertitel uffelade',
+       'mwe-add-subs-file-title' => 'Untertitel zum Uffelade uuswehle',
+       'mwe-error-only-srt' => 'Nume srt-Dateie chenne bis jetz uufeglade wäre.',
+       'mwe-watch-video' => 'Video bschaue',
+       'mwe-select-other-language' => 'Anderi Sproch wehle',
+       'mwe-saving' => 'Am Spychere ...',
+       'mwe-select_transcript_set' => 'Untertitel uuswehle',
+       'mwe-auto_scroll' => 'Automatischs Scrolle',
+       'mwe-close' => 'zuemache',
+       'mwe-improve_transcript' => 'Verbessere',
+       'mwe-no_text_tracks_found' => 'Kei Textabschnitt gfunde',
+       'mwe-add-edit-subs' => 'Untertitel yyfiege/bearbeite',
+       'mwe-transition_in' => 'Ibergang aa',
+       'mwe-transition_out' => 'Ibergang ab',
+       'mwe-effects' => 'Effäkt-Stacks',
+       'mwe-remove_transition' => 'Ibergang useneh',
+       'mwe-edit_transin' => 'Ibergang im Clip bearbeite',
+       'mwe-edit_transout' => 'Ibergang usserhalb vum Clip bearbeite',
+       'mwe-add-transition' => 'Ibergang zuefiege',
+       'mwe-menu_clipedit' => 'Medie bearbeite',
+       'mwe-menu_transition' => 'Ibergäng un Effäkt',
+       'mwe-menu_cliplib' => 'Medie zuefiege',
+       'mwe-menu_resource_overview' => 'Quälleibersicht',
+       'mwe-menu_options' => 'Optione',
+       'mwe-loading_timeline' => 'Am Lade vun ere Zytzylete ...',
+       'mwe-loading_user_rights' => 'Am Lade vu Benutzerrächt ...',
+       'mwe-no_edit_permissions' => 'Du derfsch Änderige in däm Abschnitt nit spychere',
+       'mwe-edit_clip' => 'Clip bearbeite',
+       'mwe-edit_save' => 'Änderige am Abschnitt spychere',
+       'mwe-saving_wait' => 'Grad am Spychere (bitte wart no)',
+       'mwe-save_done' => 'Spychere fertig',
+       'mwe-edit_cancel' => 'Bearbeitig vu däm Abschnitt abbräche',
+       'mwe-edit_cancel_confirm' => 'Bisch sicher, ass Du Dyni bearbeitig witt abbräche? Alli Änderige gehn derno verlore.',
+       'mwe-zoom_in' => 'Vergreßere',
+       'mwe-zoom_out' => 'Verchleinere',
+       'mwe-cut_clip' => 'Clips uusschnitte',
+       'mwe-expand_track' => 'Spur uusklappe',
+       'mwe-collapse_track' => 'Spur yyklappe',
+       'mwe-play_from_position' => 'Abspile ab dr Playline-Position',
+       'mwe-pixle2sec' => 'Pixel je Sekund',
+       'mwe-rmclip' => 'Clip uuseneh',
+       'mwe-clip_in' => 'Clip zuefiege',
+       'mwe-clip_out' => 'Clip uuseneh',
+       'mwe-no_selected_resource' => '<h3>Kei Quälle uusgwehlt</h3> Wehl e Clip uus go s Bearbeite meglig mache.',
+       'mwe-error_edit_multiple' => '<h3>Meh wie ei Quälle uusgwehlt</h3> Wehl ei einzige Clip zuem Bearbeite uus.',
+       'mwe-editor_options' => 'Yystellige zum Bearbeite',
+       'mwe-editor_mode' => 'Bearbeitigsmodus',
+       'mwe-simple_editor_desc' => 'Eifachi Bearbeitig (iMovie-Stil)',
+       'mwe-advanced_editor_desc' => 'Fortgschritteni Bearbeitig (Final Cut-Stil)',
+       'mwe-other_options' => 'Anderi Optione',
+       'mwe-contextmenu_opt' => 'Kontext-Menüs zueloo',
+       'mwe-sequencer_credit_line' => 'Entwicklet dur <a href="http://kaltura.com">Kaltura, Inc.</a> zämme mit dr <a href="http://wikimediafoundation.org/wiki/Home">Wikimedia Foundation</a> (<a href="#">meh Informatione</a>).',
+       'mwe-loading_txt' => 'Am Lade ...',
+       'mwe-error_load_lib' => 'Fähler: s JavaScript $1 het nit chenne glade wäre oder s losst $2 nit zue',
+       'mwe-loading-add-media-wiz' => 'Am Lade vum Medie-Wizard zuefiege',
+       'mwe-apiproxy-setup' => 'API-Proxy-Konfiguration',
+       'mwe-load-drag-item' => 'Am Lade vu mitgschleipfte Poschte',
+       'mwe-ok' => 'OK',
+       'mwe-cancel' => 'Abbräche',
+       'mwe-setting-up-proxy' => 'Am Yystelle vun eme Proxy ...',
+       'mwe-re-try' => 'API-Aafrog widerhole',
+       'mwe-re-trying' => 'Am Widerhole vun ere API-Aafrog ...',
+       'mwe-proxy-not-ready' => 'Proxy isch nit konfiguriert',
+       'mwe-please-login' => 'Du bisch nit <a target="_new" href="$1">aagmäldet</a> uf $2 oder mwEmbed isch nit aagschalte. Les s Probläm un versuech d Aafrog derno nonemol.',
+       'mwe-remember-loging' => 'Generälli Sicherheits-Erinnerig: Mäld di numme uf Websyte aa, wänn Dyyni Adrässleischte d Adrässe vu däre Syte aazeigt.',
+       'fogg-select_file' => 'Datei uuswehle',
+       'fogg-select_new_file' => 'Neji Datei uuswehle',
+       'fogg-select_url' => 'URL uuswehle',
+       'fogg-save_local_file' => 'Ogg spychere',
+       'fogg-check_for_firefogg' => 'Am Priefe vu Firefogg ...',
+       'fogg-installed' => 'Firefogg isch inschtalliert',
+       'fogg-for_improved_uploads' => 'Fir e verbesseret Uffelade:',
+       'fogg-please_install' => '<a href="$1">Firefogg inschtalliere</a>. Meh <a href="http://commons.wikimedia.org/wiki/Commons:Firefogg">Informatione iber Firefogg</a>',
+       'fogg-use_latest_firefox' => 'Bitte ischtallier zerscht <a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=firefogg">Firefox 3.5</a> (oder e nejeri Version). <i>DErno gang wider uf die Syte go d <b>Firefogg</b>-Erwyterig inschtalliere.</i>',
+       'fogg-passthrough_mode' => 'D Datei, wu Du uusgwehlt hesch, isch schon im Ogg-Format oder s het kei Video din',
+       'fogg-transcoding' => 'Am Umwandle vum Video in s Ogg-Format',
+       'fogg-encoding-done' => 'Umwandlig fertig',
+       'fogg-badtoken' => 'Zeiche isch nit giltig',
+       'fogg-preview' => 'Videovorschau',
+       'fogg-hidepreview' => 'Vorschau uusblände',
+       'mwe-imported_from' => '$1 isch vu [$2 $3] importiert wore. Lueg d orginal [$4 Quällsyte] fir meh Informatione.',
+       'mwe-stream_title' => '$1 $2 bis $3',
+       'fogg-help-sticky' => 'Hilf (drucke zum Feschthebe)',
+       'fogg-cg-preset' => 'Voryystellige: <strong>$1</strong>',
+       'fogg-cg-quality' => 'Grundyystellige fir d Qualitets- un Lesigskontroll',
+       'fogg-cg-meta' => 'Metadate fir dr Clip',
+       'fogg-cg-range' => 'Spannwyti umwandle',
+       'fogg-cg-advVideo' => 'Fortgschritteni Yystellige fir d Videoumwandlig',
+       'fogg-cg-advAudio' => 'Fortgschritteni Yystellige fir d Audio-Umwandlig',
+       'fogg-preset-custom' => 'Aapassti Yystellige',
+       'fogg-webvideo-desc' => 'Webvideo Theora, Vorbis 400 kbit/s un 400px maximali Greßi',
+       'fogg-savebandwidth-desc' => 'Nideri Bandbreiti Theora, Vorbis 164 kbit/s un 200px maximali Greßi',
+       'fogg-highquality-desc' => 'Hochi Qualitet Theora, Vorbis 1080px maximali Greßi',
+       'fogg-videoQuality-title' => 'Videoqualitet',
+       'fogg-videoQuality-help' => 'Wird brucht go d <i>visuälli Qualitet</i> vum verschlisslete Video yystele (wird nit brucht, wänn d Bit-Rot in dr fortgschrittene Yystellige unten yygstellt wird).',
+       'fogg-starttime-title' => 'Startsekund',
+       'fogg-starttime-help' => 'Nume vu Zyt in Sekunde verschlissle',
+       'fogg-endtime-title' => 'Stopsekund',
+       'fogg-endtime-help' => 'Nume verschlissle no Zyt in Sekunde',
+       'fogg-audioQuality-title' => 'Audioqualitet',
+       'fogg-audioQuality-help' => 'Wird brucht go di <i>akkustisch Qualitet</i> vum verschlisslete Audio yystelle (wird nit brucht, wänn d Bit-Rot in dr fortgschrittene Yystellige unten yygstellt wird).',
+       'fogg-videoCodec-title' => 'Videocodec',
+       'fogg-videoCodec-help' => 'Wird brucht go s Clip-Viodeocodes uuswehle. Zur Zyt wird nume Theora unterstitzt. Meh iber s <a target="_new" href="http://en.wikipedia.org/wiki/Theora">Theoracodec</a>.',
+       'fogg-audioCodec-title' => 'Audiocodec',
+       'fogg-audioCodec-help' => 'Wird brucht go s Clip-Audiocopdes yystelle. Zur Zyt wird nume unterstitzt. Meh iber s <a target="_new" href="http://en.wikipedia.org/wiki/Vorbis">Vorbiscodec</a>',
+       'fogg-width-title' => 'Videogreßi',
+       'fogg-width-help' => 'Aapasse an d Breiti, wu aagee isch.',
+       'fogg-height-title' => 'Videohechi',
+       'fogg-height-help' => 'Aapasse an d Hechi, wu aagee isch.',
+       'fogg-videoBitrate-title' => 'Video-Bitrote',
+       'fogg-videoBitrate-help' => 'Video_Bitrote stellt d Bitrote fir d Verschlisslig fir e Video (in kb/s)',
+       'fogg-twopass-title' => 'Zweigängigi Verschlisslig',
+       'fogg-twopass-help' => 'Zweigängigi Verschlisslig macht e konschtanteri Qualitet meglig dur e zweifachi Verschlisslig vu dr Videodatei',
+       'fogg-framerate-title' => 'Bildfrequänz',
+       'fogg-framerate-help' => 'D Video-Bildfrequänz. Meh iber d <a target="_new" href="http://en.wikipedia.org/wiki/Frame_rate">Bildfrequänz</a>.',
+       'fogg-aspect-title' => 'Bildformat',
+       'fogg-aspect-help' => 'S Video-Bildformat cha fraktioniert wäre in 4:3 oder 16:9. Meh iber s <a target="_new" href="http://en.wikipedia.org/wiki/Aspect_ratio_%28image%29">Bildformat</a>.',
+       'fogg-keyframeInterval-title' => 'Schlisselbild-Intervall',
+       'fogg-keyframeInterval-help' => 'S Schlisselbild-Intervall in Bilder. Obacht: Di meischte Codes erzwinge Schlisselbilder, wänn dr Unterschid zwische dr Bilder greßer isch wie d Scghlisselbild-Verschlissligs-Greßi. Meh iber <a href="http://en.wikipedia.org/wiki/I-frame">Schlisselbilder</a>.',
+       'fogg-denoise-title' => 'Ruschfilter',
+       'fogg-denoise-help' => 'Rusche us em Yygab-Video useneh. Meh iber s <a href="http://en.wikipedia.org/wiki/Video_denoising">Rusche useneh</a>.',
+       'fogg-novideo-title' => 'Kei Video',
+       'fogg-novideo-help' => 'Video in dr Uusgab uusschalte',
+       'fogg-audioBitrate-title' => 'Audio-Bitrote',
+       'fogg-samplerate-title' => 'Audio-Samplingrote',
+       'fogg-samplerate-help' => 'Samplerote in dr Uusgab yystelle (in Hz).',
+       'fogg-noaudio-title' => 'Kei Audio',
+       'fogg-noaudio-help' => 'Audio in dr Uusgab uusschalte',
+       'fogg-title-title' => 'Titel',
+       'fogg-title-help' => 'E Titel fir Dyy Clip',
+       'fogg-artist-title' => 'Namesetzer',
+       'fogg-artist-help' => 'Dää, wu dää Clip gmacht het',
+       'fogg-date-title' => 'Datum',
+       'fogg-date-help' => 'S Datum, wu s Filmmatrial gmacht oder uusegee woren isch',
+       'fogg-location-title' => 'Ort',
+       'fogg-location-help' => 'Ort vum Filmmatrial',
+       'fogg-organization-title' => 'Organisation',
+       'fogg-organization-help' => 'Name vu dr Organisation (Studio)',
+       'fogg-copyright-title' => 'Urheberrächt',
+       'fogg-copyright-help' => 'Urheberrächt vum Clip',
+       'fogg-license-title' => 'Lizänz',
+       'fogg-license-help' => 'D Lizänz vum Clip (am beschte e Creative-Commons-URL)',
+       'fogg-contact-title' => 'Kontakt',
+       'fogg-contact-help' => 'Kontaktgleich',
+       'mwe-add_media_wizard' => 'Medie-Wizard zuefiege',
+       'mwe-media_search' => 'Mediesuechi',
+       'rsd_box_layout' => 'Chaschtelayout',
+       'rsd_list_layout' => 'Lischtelayout',
+       'rsd_results_desc' => 'Ergebnis $1 bis $2',
+       'rsd_results_desc_total' => 'Ergebnis $1 bis $2 vu $3',
+       'rsd_results_next' => 'nekschti',
+       'rsd_results_prev' => 'vorigi',
+       'rsd_no_results' => 'Kei Suechergebnis fir <b>$1</b>',
+       'mwe-upload_tab' => 'Uffelade',
+       'rsd_layout' => 'Layout:',
+       'rsd_resource_edit' => 'Quälle bearbeite: $1',
+       'mwe-resource_description_page' => 'Bschrybigssyte',
+       'mwe-link' => 'Gleich',
+       'rsd_local_resource_title' => 'Lokale Quälltitel',
+       'rsd_do_insert' => 'Yyfiege',
+       'mwe-cc_by_title' => 'Namenännig',
+       'mwe-cc_nc_title' => 'Kei kommerziälli Nutzig',
+       'mwe-cc_nd_title' => 'Kei Bearbeitig',
+       'mwe-cc_sa_title' => 'Wytergab unter glyche Bedingige',
+       'mwe-cc_pd_title' => 'Public Domain',
+       'mwe-unknown_license' => 'Uubekannti Lizänz',
+       'mwe-no_import_by_url' => 'Dää Benutzer oder des Wiki <b>cha nyt</b> vu extärne URL importiere.<p>Muesch Di aamälde?</p><p>Hesch Du s Rächt vu URL z uffezlade?<br />Isch in däm Wiki<a href="http://www.mediawiki.org/wiki/Manual:$wgAllowCopyUploads">$wgAllowCopyUploads</a> zuegloo?</p>',
+       'mwe-results_from' => 'Ergebnis vu <a href="$1" target="_new" >$2</a>',
+       'mwe-missing_desc_see_source' => 'Zue däre Aalag fählt e Bschrybig. Bitte lueg d [$1 Orginalquälle] aa un hilf si z bschrybe.',
+       'rsd_config_error' => 'Fähler bi dr Konfiguration vu dr Yyfiegig vum Medie-Wizard: $1',
+       'mwe-your_recent_uploads' => 'D Dateie, wu Du zletscht uf $1 uffeglade hesch',
+       'mwe-upload_a_file' => 'Neji Datei uf $1 uffelade',
+       'mwe-resource_page_desc' => 'Bschryybig:',
+       'mwe-edit_resource_desc' => 'D Bschryybig vum Wikitext bearbeite:',
+       'mwe-local_resource_title' => 'Lokale Name:',
+       'mwe-watch_this_page' => 'Die Syte beobachte',
+       'mwe-do_import_resource' => 'Importiere',
+       'mwe-update_preview' => 'Vorschau aktualisiere',
+       'mwe-cancel_import' => 'Import abbräche',
+       'mwe-importing_asset' => 'Am Importiere',
+       'mwe-preview_insert_resource' => 'Vorschau vu dr Yyfiegig: $1',
+       'mwe-checking-resource' => 'Am Quälle sueche',
+       'mwe-resource-needs-import' => 'Quälle $1 miesst in $2 importiert wäre',
+       'mwe-ftype-svg' => 'SVG-Vektordatei',
+       'mwe-ftype-jpg' => 'JPEG-Bilddatei',
+       'mwe-ftype-png' => 'PNG-Bilddatei',
+       'mwe-ftype-oga' => 'Ogg-Audiodatei',
+       'mwe-ftype-ogg' => 'Ogg-Videodatei',
+       'mwe-ftype-unk' => 'Nit bekannt Dateiformat',
+       'rsd-wiki_commons-title' => 'Wikimedia Commons (Allmänd)',
+       'rsd-wiki_commons' => 'Wikimedia Commons (Allmänd), e Archiv vu frejlizänsierte Lehrmedie (Bilder, Ton- un Videoufnahme)',
+       'rsd-this_wiki-title' => 'Des Wiki',
+       'rsd-this_wiki-desc' => 'Di lokal Wiki-Inschtallation',
+       'rsd-archive_org-desc' => 'S Internet-Archiv, e digitali Biecherei vu Kulturzygnis',
+       'rsd-flickr-desc' => 'Flickr.com, e Syte fir di gmeinsam Online-Nutzig vu Foto',
+       'rsd-metavid-desc' => 'Metavid.org, e Gmeinschaftsarchiv vu dr Verhandlige vum US-Representantehuus un em US-Senat',
+       'mwe-select_file' => 'Datei uuswehle',
+       'mwe-more_licence_options' => 'Fir meh Lizänzmegligkeite lueg di <a href="$1">normal Syte zem Uffelade</a>',
+       'mwe-select_ownwork' => 'Ich bi nume am Uffelade vum myym eigen Wärch, un stell s unter d Lizänz:',
+       'mwe-licence_cc-by-sa' => 'Creative Commons Wytergab unter glyche Bedingige (3.0)',
+       'mwe-upload' => 'Datei uffelade',
+       'mwe-destfilename' => 'Neje Name:',
+       'mwe-summary' => 'Zämmefassig',
+       'mwe-error_not_loggedin' => 'Du bisch schyns nit aagmäldet oder Du hesch nit di notwändige Rächt zum Uffelade.',
+       'mwe-watch-this-file' => 'Die Datei aaluege',
+       'mwe-ignore-any-warnings' => 'Alli Warnige ignoriere',
+       'mwe-upload-transcode-in-progress' => 'Am Uffelade un Umwandle (des Fänschter nit zuemache)',
+       'mwe-upload-in-progress' => 'Am Uffelade (des Fänschter nit zuemache)',
+       'mwe-upload-transcoded-status' => 'Umgwandlet',
+       'mwe-uploaded-status' => 'Uffeglade',
+       'mwe-upload-stats-fileprogress' => '$1 vu $2',
+       'mwe-upload_completed' => 'Dyy Uffelade isch fertig',
+       'mwe-upload_done' => '<a href="$1">Dyy uffegladeni Datei <i>sott</i> z Verfiegig stoh</a>.',
+       'mwe-upload-unknown-size' => 'Dateigreßi nit bekannt',
+       'mwe-cancel-confim' => 'Witt wirkli abbräche?',
+       'mwe-successfulupload' => 'Erfolgryych uffeglade',
+       'mwe-uploaderror' => 'Fähler bim Uffelade',
+       'mwe-uploadwarning' => 'Warnig bim Uffelade',
+       'mwe-unknown-error' => 'Fähler nit bekannt:',
+       'mwe-return-to-form' => 'Zruck zum Formular',
+       'mwe-file-exists-duplicate' => 'Die Datei isch e Duplikat vu däre Datei:',
+       'mwe-fileexists' => 'S het scho ne Datei mit däm Name. Bitte prief <b><tt>$1</tt></b>, wänn du nit sicher bisch, eb Du dr Name witt ändere.',
+       'mwe-fileexists-thumb' => '<center><b>Datei, wu s git</b></center>',
+       'mwe-ignorewarning' => 'Warnig ignoriere un d Datei einewäg spychere',
+       'mwe-file-thumbnail-no' => 'Dr Dateiname fangt aa mit <b><tt>$1</tt></b>',
+       'mwe-go-to-resource' => 'Zruck zue dr Ursprungssyte',
+       'mwe-upload-misc-error' => 'Nit bekannte Fähler bim Uffelade',
+       'mwe-wgfogg_warning_bad_extension' => 'Du hesch e Datei uusgwehlt mit ere nit unterstitzte Erwyterig (<a href="http://commons.wikimedia.org/wiki/Commons:Firefogg#Supported_File_Types">meh Informatione</a>).',
+       'mwe-upload-multi' => '{{PLURAL:$1|Datei|Dateie}} uffelade',
+       'mwe-review-upload' => '{{PLURAL:$1|Datei-Uffeladig|Datei-Uffeadige}} priefe',
+       'mwe-credit-title' => 'Titel: $1',
+       'mwe-loading_plugin' => 'Am Lade vum Plugin ...',
+       'mwe-select_playback' => 'Yystellige fir s Abspile setze',
+       'mwe-link_back' => 'Gleich (Link) retur',
+       'mwe-error_swap_vid' => 'Fähler: mv_embed het s Video-Tag fir d mv_embed-Oberflechi nit chenne uustusche',
+       'mwe-add_to_end_of_sequence' => 'Am Änd vum Abschnitt yyfiege',
+       'mwe-missing_video_stream' => 'D Videodatei fir dää Strang fählt',
+       'mwe-play_clip' => 'Clip abspile',
+       'mwe-pause_clip' => 'Clip aahalte',
+       'mwe-volume_control' => 'Yystellig fir d Lutsterki',
+       'mwe-player_options' => 'Yystellige fir s Abspilprogramm',
+       'mwe-closed_captions' => 'Untertitel',
+       'mwe-player_fullscreen' => 'Vollbildschrim',
+       'mwe-next_clip_msg' => 'Dr negscht Clip abspile',
+       'mwe-prev_clip_msg' => 'Dr vorig Clip abspile',
+       'mwe-current_clip_msg' => 'Dää Clip wyter abspile',
+       'mwe-seek_to' => '$1 sueche',
+       'mwe-paused' => 'pausiert',
+       'mwe-download_segment' => 'Uuswahl zum Abelade:',
+       'mwe-download_full' => 'Di ganz Videodatei abelade:',
+       'mwe-download_right_click' => 'Zum Abelade druck uf di rächt Muustaschte un wehl <i>Gleich spychere unter...</i> uus',
+       'mwe-download_clip' => 'Video abelade',
+       'mwe-download_text' => 'Tekscht abelade (<a style="color:white" title="cmml" href="http://wiki.xiph.org/index.php/CMML">CMML</a> xml):',
+       'mwe-download' => 'Abelade',
+       'mwe-share' => 'Ufteile',
+       'mwe-credits' => 'Anerkännige',
+       'mwe-clip_linkback' => 'Clip-Quällsyte',
+       'mwe-chose_player' => 'Videospiler uuswehle',
+       'mwe-share_this_video' => 'Des Video teile',
+       'mwe-video_credits' => 'Videokredit',
+       'mwe-menu_btn' => 'Uuswahl',
+       'mwe-close_btn' => 'Zuemache',
+       'mwe-ogg-player-vlc-player' => 'VLC-Player',
+       'mwe-ogg-player-videoElement' => 'Nativ Ogg-Video',
+       'mwe-ogg-player-oggPlugin' => 'Generisch Ogg-Plugin',
+       'mwe-ogg-player-quicktime-mozilla' => 'QuickTime-Plugin',
+       'mwe-ogg-player-quicktime-activex' => 'QuickTime ActiveX',
+       'mwe-ogg-player-cortado' => 'Java Cortado',
+       'mwe-ogg-player-flowplayer' => 'Flowplayer',
+       'mwe-ogg-player-kplayer' => 'Kaltura-Player',
+       'mwe-ogg-player-selected' => '(uusgwehlt)',
+       'mwe-ogg-player-omtkplayer' => 'OMTK Flash Vorbis',
+       'mwe-generic_missing_plugin' => 'Dyy Browser unterstitzt schyns dää Abspiltyp nit: <b>$1</b><br />Gang uf d <a href="http://commons.wikimedia.org/wiki/Commons:Media_help">Abspil-Methode</a>-Syte go ne Abpilprogramm abelede.<br />',
+       'mwe-for_best_experience' => 'Fir e besseri Abspilqualitet vu däm Video empfähle mir:<br /><b><a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=mwEmbed">Firefox 3.5</a>.</b>',
+       'mwe-do_not_warn_again' => 'Fir desmol ablähne.',
+       'mwe-playerselect' => 'Abspilprogramm',
+       'mwe-read_before_embed' => 'Bitte lis d <a href="http://mediawiki.org/wiki/Security_Notes_on_Remote_Embedding" target="_new">Sicherheitsnotize iber s Yyfiege</a> voreb Du s wirkli yyfiege tuesch!',
+       'mwe-embed_site_or_blog' => 'Yybunde in e Syte',
+       'mwe-related_videos' => 'Verwandti Video',
+       'mwe-seeking' => 'Am Sueche',
+       'mwe-copy-code' => 'Code kopiere',
+       'mwe-video-h264' => 'H.264-Video',
+       'mwe-video-flv' => 'Flash-Video',
+       'mwe-video-ogg' => 'Ogg-Video',
+       'mwe-video-audio' => 'Ogg-Audiodatei',
+);
+
+/** Hebrew (עברית)
+ * @author Rotemliss
+ * @author YaronSh
+ */
+$messages['he'] = array(
+       'mwe-crop' => 'חיתוך תמונה',
+       'mwe-apply_crop' => 'החלת החיתוך על התמונה',
+       'mwe-reset_crop' => 'איפוס החיתוך',
+       'mwe-insert_image_page' => 'הוספה לדף',
+       'mwe-insert_into_sequence' => 'הוספה לתוך הרצף',
+       'mwe-preview_insert' => 'תצוגה מקדימה של התוספת',
+       'mwe-cancel_image_insert' => 'ביטול ההוספה',
+       'mwe-sc_fileopts' => 'עריכת פרטי הקטע',
+       'mwe-sc_inoutpoints' => 'הגדרת נקודות כניסה ויציאה',
+       'mwe-sc_overlays' => 'שכבות',
+       'mwe-sc_audio' => 'בקרת שמע',
+       'mwe-sc_duration' => 'משך',
+       'mwe-template_properties' => 'מאפייני התבנית',
+       'mwe-custom_title' => 'כותרת מותאמת אישית',
+       'mwe-edit_properties' => 'עריכת המאפיינים',
+       'mwe-other_properties' => 'מאפיינים אחרים',
+       'mwe-resource_page' => 'דף המשאב:',
+       'mwe-set_in_out_points' => 'הגדרת נקודות כניסה-יציאה',
+       'mwe-start_time' => 'זמן ההתחלה',
+       'mwe-end_time' => 'זמן הסיום',
+       'mwe-preview_inout' => 'תצוגה מקדימה של נקודות הכניסה-יציאה',
+       'mwe-select_transcript_set' => 'בחירת כתוביות',
+       'mwe-auto_scroll' => 'גלילה אוטומטית',
+       'mwe-close' => 'סגירה',
+       'mwe-improve_transcript' => 'שיפור',
+       'mwe-no_text_tracks_found' => 'לא נמצאו עקבות טקסט',
+       'mwe-transition_in' => 'מעברון כניסה',
+       'mwe-transition_out' => 'מעברון יציאה',
+       'mwe-effects' => 'מכלול האפקטים',
+       'mwe-remove_transition' => 'הסרת המעברון',
+       'mwe-edit_transin' => 'עריכת המעברון אל תוך הסרטון',
+       'mwe-edit_transout' => 'עריכת המעברון אל מחוץ לסרטון',
+       'mwe-menu_clipedit' => 'עריכת המדיה',
+       'mwe-menu_transition' => 'מעברונים ואפקטים',
+       'mwe-menu_cliplib' => 'הוספת מדיה',
+       'mwe-menu_resource_overview' => 'סקירת המשאבים',
+       'mwe-menu_options' => 'אפשרויות',
+       'mwe-loading_timeline' => 'מתבצעת טעינת ציר הזמן ...',
+       'mwe-loading_user_rights' => 'מתבצעת טעינת הרשאות המשתמש ...',
+       'mwe-no_edit_permissions' => 'אין לכם הרשאות לשמור את השינויים לרצף זה',
+       'mwe-edit_clip' => 'עריכת הסרטון',
+       'mwe-edit_save' => 'שמירת השינויים ברצף',
+       'mwe-saving_wait' => 'השמירה מתבצעת (נא להמתין)',
+       'mwe-save_done' => 'השמירה הושלמה',
+       'mwe-edit_cancel' => 'ביטול עריכת הרצף',
+       'mwe-edit_cancel_confirm' => 'האם אתם בטוחים שברצונם לבטל את עריכתכם? השינויים יאבדו.',
+       'mwe-zoom_in' => 'התקרבות',
+       'mwe-zoom_out' => 'התרחקות',
+       'mwe-cut_clip' => 'גזירת סרטונים',
+       'mwe-expand_track' => 'הרחבת הרצועה',
+       'mwe-collapse_track' => 'צמצום הרצועה',
+       'mwe-play_from_position' => 'נגינה מהמיקום בשורת הנגינה',
+       'mwe-pixle2sec' => 'פיקסלים לשניות',
+       'mwe-rmclip' => 'הסרת סרטון',
+       'mwe-no_selected_resource' => '<h3>לא נבחר משאב</h3> יש לבחור סרטון כדי לאפשר עריכה.',
+       'mwe-error_edit_multiple' => '<h3>נבחרו מספר מקורות</h3> יש לבחור בקטע בודד כדי לערוך אותו.',
+       'mwe-editor_options' => 'אפשרויות העורך',
+       'mwe-editor_mode' => 'מצב עורך',
+       'mwe-simple_editor_desc' => 'עורך פשוט (בסגנון iMovie)',
+       'mwe-advanced_editor_desc' => 'עורך מתקדם (בסגנון Final Cut)',
+       'mwe-other_options' => 'אפשרויות אחרות',
+       'mwe-contextmenu_opt' => 'הפעלת תפריטי ההקשר',
+       'mwe-sequencer_credit_line' => 'פותח על ידי <a href="http://kaltura.com">Kaltura בע"מ</a> בשיתוף עם <a href="http://wikimediafoundation.org/wiki/Home">קרן ויקימדיה</a> (<a href="#">למידע נוסף</a>).',
+       'mwe-loading_txt' => 'בטעינה ...',
+       'mwe-error_load_lib' => 'שגיאה: לא ניתן היה לטעון את ספריית ה־JavaScript בשם $1 או שהיא אינה מגדירה את $2',
+       'fogg-select_file' => 'בחירת קובץ',
+       'fogg-select_new_file' => 'בחירת קובץ חדש',
+       'fogg-select_url' => 'בחירת כתובת',
+       'fogg-save_local_file' => 'שמירת ה־Ogg',
+       'fogg-check_for_firefogg' => 'מתבצעת בדיקה האם מותקן Firefogg ...',
+       'fogg-installed' => 'Firefogg מותקן',
+       'fogg-for_improved_uploads' => 'להעלאות משופרות:',
+       'fogg-please_install' => '<a href="$1">להתקנת Firefogg</a>. עוד <a href="http://commons.wikimedia.org/wiki/Commons:Firefogg">אודות Firefogg</a>',
+       'fogg-use_latest_firefox' => 'ראשית יש להתקין את <a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=firefogg">Firefox 3.5</a> (ומעלה). <b>לאחר מכן יש לבקר בדף זה שוב כדי להתקין את ההרחבה <i>Firefogg</i>.</b>',
+       'fogg-passthrough_mode' => 'הקובץ שנבחר הוא כבר קובץ Ogg או שאינו קובץ וידאו',
+       'fogg-transcoding' => 'קידוד הווידאו ל־Ogg',
+       'fogg-encoding-done' => 'הקידוד הושלם',
+       'fogg-badtoken' => 'האסימון אינו תקין',
+       'fogg-help-sticky' => 'עזרה (לחצו להצמדה)',
+       'fogg-cg-preset' => 'הגדרה מראש: <strong>$1</strong>',
+       'fogg-cg-meta' => 'נתונים אודות קטע הווידאו',
+       'fogg-cg-range' => 'טווח הקידוד',
+       'fogg-cg-advVideo' => 'פקדי הצפנת וידאו מתקדמים',
+       'fogg-cg-advAudio' => 'פקדי הצפנת שמע מתקדמים',
+       'fogg-preset-custom' => 'הגדרות מותאמות אישית',
+       'mwe-add_media_wizard' => 'אשף הוספת המדיה',
+       'mwe-media_search' => 'חיפוש מדיה',
+       'rsd_box_layout' => 'פריסת תיבה',
+       'rsd_list_layout' => 'פריסת רשימה',
+       'rsd_results_desc' => 'תוצאות $1 עד $2',
+       'rsd_results_next' => 'הבא',
+       'rsd_results_prev' => 'הקודם',
+       'rsd_no_results' => 'אין תוצאות חיפוש עבור <b>$1</b>',
+       'mwe-upload_tab' => 'העלאה',
+       'rsd_layout' => 'פריסה:',
+       'rsd_resource_edit' => 'עריכת משאב: $1',
+       'mwe-resource_description_page' => 'דף תאור המשאב',
+       'rsd_local_resource_title' => 'כותרת המשאב המקומי',
+       'rsd_do_insert' => 'ביצוע ההוספה',
+       'mwe-unknown_license' => 'רשיון בלתי ידוע',
+       'mwe-results_from' => 'תוצאות מ־<a href="$1" target="_new" >$2</a>',
+       'rsd_config_error' => 'שגיאה בהגדרות אשף הוספת המדיה: $1',
+       'mwe-upload_a_file' => 'העלאת קובץ חדש ל$1',
+       'mwe-watch_this_page' => 'מעקב אחרי דף זה',
+       'mwe-do_import_resource' => 'ייבוא משאב',
+       'mwe-update_preview' => 'עדכון התצוגה המקדימה',
+       'mwe-cancel_import' => 'ביטול הייבוא',
+       'mwe-select_file' => 'בחירת קובץ',
+       'mwe-upload' => 'העלאת קובץ',
+       'mwe-destfilename' => 'שם קובץ היעד:',
+       'mwe-summary' => 'תקציר',
+       'mwe-uploaded-status' => 'הועלה',
+       'mwe-upload-stats-fileprogress' => '$1 מתוך $2',
+       'mwe-upload_completed' => 'ההעלאה שלכם הושלמה',
+       'mwe-upload-unknown-size' => 'גודל בלתי ידוע',
+       'mwe-cancel-confim' => 'האם אתם בטוחים שברצונכם לבטל?',
+       'mwe-successfulupload' => 'ההעלאה הושלמה בהצלחה',
+       'mwe-uploaderror' => 'שגיאה בעת ההעלאה',
+       'mwe-uploadwarning' => 'אזהרת העלאה',
+       'mwe-unknown-error' => 'שגיאה בלתי מוכרת:',
+       'mwe-return-to-form' => 'חזרה לטופס',
+       'mwe-file-exists-duplicate' => 'קובץ זה הוא כפול לקובץ הבא:',
+       'mwe-fileexists-thumb' => '<center><b>קובץ קיים</b></center>',
+       'mwe-ignorewarning' => 'התעלמות מהאזהרות ושמירת הקובץ בכל מקרה',
+       'mwe-file-thumbnail-no' => 'שם הקובץ מתחיל ב־<b><tt>$1</tt></b>',
+       'mwe-go-to-resource' => 'מעבר לדף המשאב',
+       'mwe-link_back' => 'קישור חזרה',
+       'mwe-add_to_end_of_sequence' => 'בסוף הרצף',
+       'mwe-missing_video_stream' => 'קובץ הווידאו עבור זרם זה חסר',
+       'mwe-play_clip' => 'נגינת הסרטון',
+       'mwe-pause_clip' => 'השהיית הסרטון',
+       'mwe-volume_control' => 'בקרת עוצמת השמע',
+       'mwe-player_options' => 'אפשרויות הנגן',
+       'mwe-player_fullscreen' => 'מסך מלא',
+       'mwe-next_clip_msg' => 'נגינת הסרטון הבא',
+       'mwe-prev_clip_msg' => 'נגינת הסרטון הקודם',
+       'mwe-current_clip_msg' => 'המשך נגינת הסרטון',
+       'mwe-download_full' => 'הורדת קובץ הווידאו המלא:',
+       'mwe-download_clip' => 'הורדת הווידאו',
+       'mwe-download' => 'הורדה',
+       'mwe-share' => 'שיתוף',
+       'mwe-credits' => 'תודות',
+       'mwe-clip_linkback' => 'דף המקור של הסרטון',
+       'mwe-chose_player' => 'בחירת נגן וידאו',
+       'mwe-share_this_video' => 'שיתוף וידאו זה',
+       'mwe-menu_btn' => 'תפריט',
+       'mwe-close_btn' => 'סגירה',
+       'mwe-ogg-player-oggPlugin' => 'תוסף Ogg גנרי',
+       'mwe-ogg-player-quicktime-mozilla' => 'תוסף QuickTime',
+       'mwe-ogg-player-selected' => '(נבחר)',
+       'mwe-do_not_warn_again' => 'התעלמות לעת עתה.',
+       'mwe-playerselect' => 'נגנים',
+       'mwe-embed_site_or_blog' => 'הטמעה באתר או בבלוג שלכם',
+       'mwe-related_videos' => 'סרטונים קשורים',
+);
+
+/** Upper Sorbian (Hornjoserbsce)
+ * @author Michawiki
+ */
+$messages['hsb'] = array(
+       'mwe-crop' => 'Wobraz přitřihać',
+       'mwe-apply_crop' => 'Přitřihanje na wobraz nałožić',
+       'mwe-reset_crop' => 'Přitřihanje cofnyć',
+       'mwe-insert_image_page' => 'Do strony zasunyć',
+       'mwe-insert_into_sequence' => 'Do sekwency zasunyć',
+       'mwe-preview_insert' => 'Přehlad zasunjenja',
+       'mwe-cancel_image_insert' => 'Zasunjenje přetorhnyć',
+       'mwe-sc_fileopts' => 'Wobdźěłanje klipowych podrobnosćow',
+       'mwe-sc_inoutpoints' => 'Spočatne a kónčne dypki stajić',
+       'mwe-sc_overlays' => 'Zablendowanja',
+       'mwe-sc_audio' => 'Awdiowodźenje',
+       'mwe-sc_duration' => 'Traće',
+       'mwe-template_properties' => 'Kajkosće předłohi',
+       'mwe-custom_title' => 'Swójski titul',
+       'mwe-edit_properties' => 'Kajkosće wobdźěłać',
+       'mwe-other_properties' => 'Druhe kajkosće',
+       'mwe-resource_page' => 'Resursowa strona:',
+       'mwe-set_in_out_points' => 'Spočatne a kónčne dypki stajić',
+       'mwe-start_time' => 'Startowy čas',
+       'mwe-end_time' => 'Kónčny čas',
+       'mwe-preview_inout' => 'Spočatne a kónčne dypki jako přehlad pokazać',
+       'mwe-edit-tools' => 'Wobdźěłowanske nastroje',
+       'mwe-inline-description' => 'Nadpismo',
+       'mwe-edit-video-tools' => 'Nastroje za wobdźěłowanje widejow:',
+       'mwe-duration' => 'Traće:',
+       'mwe-upload-subs-file' => 'Podtitul nahrać',
+       'mwe-add-subs-file-title' => 'Podtitul za nahraće wubrać',
+       'mwe-error-only-srt' => 'Jenož srt-dataje hodźa so direktnje nahrać.',
+       'mwe-watch-video' => 'Wideo wobkedźbować',
+       'mwe-select-other-language' => 'Druhu rěč wubrać',
+       'mwe-saving' => 'składuje so...',
+       'mwe-select_transcript_set' => 'Podtitule wubrać',
+       'mwe-auto_scroll' => 'awtomatisce kulić',
+       'mwe-close' => 'začinić',
+       'mwe-improve_transcript' => 'Polěpšić',
+       'mwe-no_text_tracks_found' => 'Žane tekstowe ćěrje njebuchu namakane',
+       'mwe-add-edit-subs' => 'Podtitule přidać/wobdźěłać',
+       'mwe-transition_in' => 'Zablendować',
+       'mwe-transition_out' => 'Wublendować',
+       'mwe-effects' => 'Stapl efektow',
+       'mwe-remove_transition' => 'Přechad wotstronić',
+       'mwe-edit_transin' => 'Přechod do klipa wobdźěłać',
+       'mwe-edit_transout' => 'Přechod z klipa wobdźěłać',
+       'mwe-add-transition' => 'Přechad přidać',
+       'mwe-menu_clipedit' => 'Medije wobdźěłać',
+       'mwe-menu_transition' => 'Přechady a efekty',
+       'mwe-menu_cliplib' => 'Medije přidać',
+       'mwe-menu_resource_overview' => 'Resursowy přehlad',
+       'mwe-menu_options' => 'Opcije',
+       'mwe-loading_timeline' => 'Časowa lajsta ...',
+       'mwe-loading_user_rights' => 'Wužiwarske prawa so začituja ...',
+       'mwe-no_edit_permissions' => 'Nimaš prawa, zo by změny na tutej sekwency składował',
+       'mwe-edit_clip' => 'Klip wobdźěłać',
+       'mwe-edit_save' => 'Změny sekwency składować',
+       'mwe-saving_wait' => 'Składuje so runje (prošu čakać)',
+       'mwe-save_done' => 'Składowanje zakónčene',
+       'mwe-edit_cancel' => 'Wobdźěłowanje sekwency přetorhnyć',
+       'mwe-edit_cancel_confirm' => 'Chceš woprawdźe swoje wobdźěłanje zaćisnyć? Změny so zhubja.',
+       'mwe-zoom_in' => 'Powjetšić',
+       'mwe-zoom_out' => 'Pomjeńšić',
+       'mwe-cut_clip' => 'Klipy třihać',
+       'mwe-expand_track' => 'Ćěr rozfałdować',
+       'mwe-collapse_track' => 'Ćěr fałdować',
+       'mwe-play_from_position' => 'Wot aktuelneje pozicije wohtrać',
+       'mwe-pixle2sec' => 'piksele do sekundow',
+       'mwe-rmclip' => 'Klip wotstronić',
+       'mwe-clip_in' => 'klip přidać',
+       'mwe-clip_out' => 'klip wotstronić',
+       'mwe-no_selected_resource' => '<h3>Žana resursa wubrana</h3> Wubjer klip, zo by wobdźěłowanje zmóžnił.',
+       'mwe-error_edit_multiple' => '<h3>Wjacore resursy wubrane</h3> Wubjer jednotliwy klip za wobdźěłanje.',
+       'mwe-editor_options' => 'Editorowe opcije',
+       'mwe-editor_mode' => 'Editorowy modus',
+       'mwe-simple_editor_desc' => 'jednory editor (stil iMovie)',
+       'mwe-advanced_editor_desc' => 'rozšěrjeny editor (stil Final Cut)',
+       'mwe-other_options' => 'Druhe opcije',
+       'mwe-contextmenu_opt' => 'Kontekstowe menije zmóžnić',
+       'mwe-sequencer_credit_line' => 'Wuwity wot <a href="http://kaltura.com">Kaltura, Inc.</a> w partnerstwje ze załožbu <a href="http://wikimediafoundation.org/wiki/Home">Wikimedia Foundation</a> (<a href="#">dalše informacije</a>).',
+       'mwe-loading_txt' => 'začituje so ...',
+       'mwe-size-gigabytes' => '$1 GB',
+       'mwe-size-megabytes' => '$1 MB',
+       'mwe-size-kilobytes' => '$1 KB',
+       'mwe-size-bytes' => '$1 B',
+       'mwe-error_load_lib' => 'Zmylk: JavaScript $1 njeda so wotwołać abo njedefinuje $2',
+       'mwe-loading-add-media-wiz' => 'Zacituje so asistent za přidaće medijow',
+       'mwe-apiproxy-setup' => 'Proksy API zarjadować',
+       'mwe-load-drag-item' => 'Wlečeny zapisk so začituje',
+       'mwe-ok' => 'W porjadku',
+       'mwe-cancel' => 'Přetorhnyć',
+       'mwe-setting-up-proxy' => 'Proksy so připrawja...',
+       'mwe-re-try' => 'Naprašowanje API wospjetować',
+       'mwe-re-trying' => 'Naprašowanje API so wospjetuje...',
+       'mwe-proxy-not-ready' => 'Proksy njeje konfigurowany',
+       'mwe-please-login' => 'Njejsy na $2 <a target="_new" href="$1">přizjewjeny</a> abo mwEmbed njeje zmóžnjeny. Rozrisaj tutón problem a wospjetuj potom naprašowanje.',
+       'mwe-remember-loging' => 'Powšitkowne wěstotne dopomnjeće: Přizjew so jenož na websydłach, hdyž twoje adresowe polo adresu sydła zwobraznjuje.',
+       'fogg-select_file' => 'Dataju wubrać',
+       'fogg-select_new_file' => 'Nowu dataju wubrać',
+       'fogg-select_url' => 'URL wubrać',
+       'fogg-save_local_file' => 'Ogg składować',
+       'fogg-check_for_firefogg' => 'Pruwowanje za Firefogg ...',
+       'fogg-installed' => 'Firefogg so instaluje',
+       'fogg-for_improved_uploads' => 'Za polěpšene nahraća:',
+       'fogg-please_install' => '<a href="$1">Firefogg instalować</a>. Wjace <a href="http://commons.wikimedia.org/wiki/Commons:Firefogg">wo Firefoggu</a>',
+       'fogg-use_latest_firefox' => 'Prošu instalu najprjedy <a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=firefogg">Firefox 3.5</a> (abo wyše). <i>Potom wopytaj tutu strona znowa, zo by rozšěrjenje <b>Firefogg</b> instalował.</i>',
+       'fogg-passthrough_mode' => 'Twoja wubrana dataja je hižo Ogg abo njeje widejowa dataja',
+       'fogg-transcoding' => 'Kodowanje wideja do Ogg',
+       'fogg-encoding-done' => 'Kodowanje hotowe',
+       'fogg-badtoken' => 'Znamješko płaćiwe njeje',
+       'fogg-preview' => 'Přehlad wideja wobhladać',
+       'fogg-hidepreview' => 'Přehlad schować',
+       'mwe-imported_from' => '$1 z [$2 $3] importowany. Hlej originalnu [$4 resursowu stronu] za dalše informacije.',
+       'mwe-stream_title' => '$1 $2 do $3',
+       'fogg-help-sticky' => 'Pomoc (přez kliknjenje přilěpić)',
+       'fogg-cg-preset' => 'Prjedy nastajeny: <strong>$1</strong>',
+       'fogg-cg-quality' => 'Zakładna kwalita a regulowanje rozeznaća',
+       'fogg-cg-meta' => 'Metadaty za klip',
+       'fogg-cg-range' => 'Wobłuk kodowanja',
+       'fogg-cg-advVideo' => 'Rozšěrjene nastajenja za widejokodowanje',
+       'fogg-cg-advAudio' => 'Rozšěrjene nastajenja za awdiokodowanje',
+       'fogg-preset-custom' => 'Swójske nastajenja',
+       'fogg-webvideo-desc' => 'Webwidejo Theora, Vorbis 400 kbit/s a 400 pks maksimalna šěrokosć',
+       'fogg-savebandwidth-desc' => 'Niska šěrokosć pasma Theora, Vorbis 164 kbit/s a 200 pks maksimalna šěrokosć',
+       'fogg-highquality-desc' => 'Wysoka kwalita Theoro, Vorbis 1080 pks maksimalna šěrokosć',
+       'fogg-videoQuality-title' => 'Widejokwalita',
+       'fogg-videoQuality-help' => 'Wužiwa so, zo by so <i>wizuelna kwalita</i> zakodowaneho wideja nastajiła (njewužiwa so, jeli sy bitowu ratu deleka w rozšěrjenym meniju nastajił).',
+       'fogg-starttime-title' => 'Startowa sekunda',
+       'fogg-starttime-help' => 'Jenož wot časa w sekundach kodować',
+       'fogg-endtime-title' => 'Kónčna sekunda',
+       'fogg-endtime-help' => 'Jenož hač k časej w sekundach kodować',
+       'fogg-audioQuality-title' => 'Awdiokwalita',
+       'fogg-audioQuality-help' => 'Wužiwa so, zo by so <i>akustiska kwalita</i> zakodowaneho awdio nastajiła (njewužiwa so, jeli nastaješ bitowu ratu deleka w rozšěrjenym meniju).',
+       'fogg-videoCodec-title' => 'Widejokodek',
+       'fogg-videoCodec-help' => 'Wužiwa so, zo by so widejokodek klipa wubrał. Tuchwilu so jenož Theora podpěruje. <a target="_new" href="http://en.wikipedia.org/wiki/Theora">Wjace wo kodeku Theora</a>. (jendźelsce)',
+       'fogg-audioCodec-title' => 'Awdiokodek',
+       'fogg-audioCodec-help' => 'Wužiwa so, zo by so awdiokodek klipa wubrał. Tuchwilu so jenož Vorbis podpěruje. <a target="_new" href="http://en.wikipedia.org/wiki/Vorbis">Wjace wo kodeku Vorbis</a>. (jendźelsce)',
+       'fogg-width-title' => 'Šěrokosć wideja',
+       'fogg-width-help' => 'Na podatu šěrokosć skalować',
+       'fogg-height-title' => 'Wysokosć wideja',
+       'fogg-height-help' => 'Na podatu wysokosć skalować.',
+       'fogg-videoBitrate-title' => 'Bitowa rata widejo',
+       'fogg-videoBitrate-help' => 'Bitowa rata widejo nastaja kodowansku bitowu ratu za widejo (w kb/s)',
+       'fogg-twopass-title' => 'Kodowanje w dwěmaj krokomaj',
+       'fogg-twopass-help' => 'Kodowanje w dwěmaj krokomaj zmóžnja konstantnišu kwalitu přez dwukróćne předźěłowanje widejodataje.',
+       'fogg-framerate-title' => 'Wobrazowa frekwenca',
+       'fogg-framerate-help' => 'Wobrazowa wospjetowanska frekwenca wideja. Dalše informacije wo <a target="_new" href="http://en.wikipedia.org/wiki/Frame_rate">wobrazowej wospjetowanskej frekwency</a>.',
+       'fogg-aspect-title' => 'Wobrazowy poměr',
+       'fogg-aspect-help' => 'Wobrazowy poměr wideja móže 4:3 abo 16:9 być. Dalše informacije wo <a target="_new" href="http://en.wikipedia.org/wiki/Aspect_ratio_%28image%29">wobrazowych poměrach</a>.',
+       'fogg-keyframeInterval-title' => 'Interwal klučowych wobrazow',
+       'fogg-keyframeInterval-help' => 'Interwal klučowych wobrazow we wobrazach. Kedźbu: Najwjace kodekow wunuzuja klučowe wobrazy, jeli rozdźěl mjez wobrazami je wjetši hač kodowanska wulkosć klučoweho wobraza. <a href="http://en.wikipedia.org/wiki/I-frame">Wjace wo klučowych wobrazach</a> (jendźelsce)',
+       'fogg-denoise-title' => 'Filter přećiwo šumjenju',
+       'fogg-denoise-help' => 'Šumjenje wideja wotstronić. <a href="http://en.wikipedia.org/wiki/Video_denoising">Wjace wo wotstronjenju šumjenja</a> (jendźelsce)',
+       'fogg-novideo-title' => 'Žane widejo',
+       'fogg-novideo-help' => 'Widejo we wudaću znjemóžnić',
+       'fogg-audioBitrate-title' => 'Bitowa rata awdio',
+       'fogg-samplerate-title' => 'Wottastowanska frekwenca awdio',
+       'fogg-samplerate-help' => 'wottstastowanska frekwenca wudaća nastajić (w Hz).',
+       'fogg-noaudio-title' => 'Žane awdio',
+       'fogg-noaudio-help' => 'awdio we wudaću znjemóžnić',
+       'fogg-title-title' => 'Titul',
+       'fogg-title-help' => 'Titul za twój klip',
+       'fogg-artist-title' => 'Mjeno tworićela',
+       'fogg-artist-help' => 'Tworićel tutoho klipa',
+       'fogg-date-title' => 'Datum',
+       'fogg-date-help' => 'Datum, hdyž je so natočenje wutworiło abo přewostajiło',
+       'fogg-location-title' => 'Městno',
+       'fogg-location-help' => 'Městno natočenja',
+       'fogg-organization-title' => 'Organizacija',
+       'fogg-organization-help' => 'Mjeno organizacije (studijo)',
+       'fogg-copyright-title' => 'Awtorske prawo',
+       'fogg-copyright-help' => 'Awtorske prawo tutoho klipa',
+       'fogg-license-title' => 'Licenca',
+       'fogg-license-help' => 'Licenca klipa (po móžnosći URL Creative Commons).',
+       'fogg-contact-title' => 'Kontakt',
+       'fogg-contact-help' => 'Kontaktny wotkaz',
+       'mwe-add_media_wizard' => 'Medijowy asistent přidać',
+       'mwe-media_search' => 'Medijowe pytanje',
+       'rsd_box_layout' => 'Kašćikowe wuhotowanje',
+       'rsd_list_layout' => 'Lisćinowe wuhotowanje',
+       'rsd_results_desc' => 'Wuslědki $1 do $2',
+       'rsd_results_desc_total' => 'Wuslědki $1 do $2 z $3',
+       'rsd_results_next' => 'dalši',
+       'rsd_results_prev' => 'předchadny',
+       'rsd_no_results' => 'Žane pytanske wuslědki za <b>$1</b>',
+       'mwe-upload_tab' => 'Nahrać',
+       'rsd_layout' => 'Wuhotowanje:',
+       'rsd_resource_edit' => 'Resursu wobdźěłać: $1',
+       'mwe-resource_description_page' => 'Wopisanska strona resursy',
+       'mwe-link' => 'wotkaz',
+       'rsd_local_resource_title' => 'Titul lokalneje resursy',
+       'rsd_do_insert' => 'Zasunjenje přewjesć',
+       'mwe-cc_title' => 'Creative Commons',
+       'mwe-cc_by_title' => 'Připokazanje',
+       'mwe-cc_nc_title' => 'Njekomercielny',
+       'mwe-cc_nd_title' => 'Žane wotwodźene dźěła',
+       'mwe-cc_sa_title' => 'Po jenakich dźělach',
+       'mwe-cc_pd_title' => 'Powšitkownosći wužitny',
+       'mwe-unknown_license' => 'Njeznata licenca',
+       'mwe-no_import_by_url' => 'Tutón wužiwar abo wiki <b>njemóže</b> resursy z internetnych URL importować.<p>Dyrbiš so přizjewić?</p><p>Je prawo upload_by_url za tebje nastajene?<br />Ma wiki <a href="http://www.mediawiki.org/wiki/Manual:$wgAllowCopyUploads">$wgAllowCopyUploads</a> zmóžnjene?</p>',
+       'mwe-results_from' => 'Wuslědki z <a href="$1" target="_new" >$2</a>',
+       'mwe-missing_desc_see_source' => 'Tuta resursa wopisanje nima. Prošu hlej [$1 originalne žórło] a pomhaj ju wopisać.',
+       'rsd_config_error' => 'Konfiguraciski zmylk asistenta přidawanja medijow: $1',
+       'mwe-your_recent_uploads' => 'Twoje tuchwilne nahraća do $1',
+       'mwe-upload_a_file' => 'Nowu dataju do $1 nahrać',
+       'mwe-resource_page_desc' => 'Wopisanje resursoweje strony:',
+       'mwe-edit_resource_desc' => 'Wopisanje wikitekstoweje resursy wobdźěłać:',
+       'mwe-local_resource_title' => 'Titul lokalneje resursy:',
+       'mwe-watch_this_page' => 'tutu stronu wobkedźbować',
+       'mwe-do_import_resource' => 'Resursu importować',
+       'mwe-update_preview' => 'Přehlad aktualizować',
+       'mwe-cancel_import' => 'Importowanje přetorhnyć',
+       'mwe-importing_asset' => 'Resursa so importuje',
+       'mwe-preview_insert_resource' => 'Přehlad zasunjenja resursy pokazać: $1',
+       'mwe-checking-resource' => 'Pyta so resursa',
+       'mwe-resource-needs-import' => 'Resursa $1 dyrbi so do $2 importować',
+       'mwe-ftype-svg' => 'Wektorowa dataja SVG',
+       'mwe-ftype-jpg' => 'Wobrazowa dataja JPEG',
+       'mwe-ftype-png' => 'Wobrazowa dataja PNG',
+       'mwe-ftype-oga' => 'Awdiodataja Ogg',
+       'mwe-ftype-ogg' => 'Widejodataja Ogg',
+       'mwe-ftype-unk' => 'Njeznaty datajowy format',
+       'rsd-wiki_commons-title' => 'Wikimedija Commons',
+       'rsd-wiki_commons' => 'Wikimedija Commons, archiw swobodnje licencowaneho wobsah wučbnych medijow (wobrazy, awdiomaterial a wideoklipy)',
+       'rsd-this_wiki-title' => 'Tutón wiki',
+       'rsd-this_wiki-desc' => 'Instalacija lokalneho wikija',
+       'rsd-archive_org-desc' => 'Internetny archiw, digitalna biblioteka kulturnych twórbow',
+       'rsd-flickr-desc' => 'Flickr.com, websydło za zhromadne wužiwanje fotow',
+       'rsd-metavid-desc' => 'Metavid.org, zhromadźenstwowy archiw protokolow posedźenja Dom zapósłancow a Senata USA',
+       'mwe-select_file' => 'Dataju wubrać',
+       'mwe-more_licence_options' => 'Za dalše licencne opcije, hlej <a href="$1">normalnu nahraćowu stronu</a>',
+       'mwe-select_ownwork' => 'Nahrawam swoje dźěło a licencuju jo pod:',
+       'mwe-licence_cc-by-sa' => 'Creative Commons Share Alike (3.0)',
+       'mwe-upload' => 'Dataju nahrać',
+       'mwe-destfilename' => 'Cilowe datajowe mjeno:',
+       'mwe-summary' => 'Zjeće',
+       'mwe-error_not_loggedin' => 'Zda so, zo njejsy přizjewjeny abo nimaš nahraćowe prawa.',
+       'mwe-watch-this-file' => 'Tutu dataju wobkedźbować',
+       'mwe-ignore-any-warnings' => 'Warnowanja ignorować',
+       'mwe-upload-transcode-in-progress' => 'Transkodowanje a nahraće so runje wotměwatej (tute wokno njezačinić)',
+       'mwe-upload-in-progress' => 'Nahraće so runje wotměwa (tute wokno njezačinić)',
+       'mwe-upload-transcoded-status' => 'Transkodowany',
+       'mwe-uploaded-status' => 'Nahraty',
+       'mwe-upload-stats-fileprogress' => '$1 z $2',
+       'mwe-upload_completed' => 'Twoje nahraće je dospołne',
+       'mwe-upload_done' => '<a href="$1">Twoje nahraće <i>měło</i> přistupne być</a>.',
+       'mwe-upload-unknown-size' => 'Njeznata wulkosć',
+       'mwe-cancel-confim' => 'Chceš woprawdźe přetorhnyć?',
+       'mwe-successfulupload' => 'Nahraće wuspěšne',
+       'mwe-uploaderror' => 'Nahraćowy zmylk',
+       'mwe-uploadwarning' => 'Nahraćowe warnowanje',
+       'mwe-unknown-error' => 'Njeznaty zmylk:',
+       'mwe-return-to-form' => 'Wróćo k formularej',
+       'mwe-file-exists-duplicate' => 'Tuta dataja je duplikat slědowaceje dataje:',
+       'mwe-fileexists' => 'Dataja z tutym mjenom hižo eksistuje. Prošu skontroluj <b><tt>$1</tt></b>, jeli njesy sej wěsty, hač chceš ju změnić.',
+       'mwe-fileexists-thumb' => '<center><b>Eksistowaca dataja</b></center>',
+       'mwe-ignorewarning' => 'Warnowanje ignorować a dataju najebać toho składować',
+       'mwe-file-thumbnail-no' => 'Datajowe mjeno započina so z <b><tt>$1</tt></b>',
+       'mwe-go-to-resource' => 'K resursowej stronje',
+       'mwe-upload-misc-error' => 'Njeznaty nahraćowy zmylk',
+       'mwe-wgfogg_warning_bad_extension' => 'Sy dataju z njepodpěrowanym sufiksom wubrał (<a href="http://commons.wikimedia.org/wiki/Commons:Firefogg#Supported_File_Types">dalše informacije</a>).',
+       'mwe-upload-multi' => '{{PLURAL:$1|Dataju|Dataji|Dataje|Dataje}} nahrać',
+       'mwe-review-upload' => '{{PLURAL:$1|Datajowe nahraće|Datajowej nahraći|Datajowe nahraća|Datajowe nahraća}} přepruwować',
+       'mwe-credit-title' => 'Titul: $1',
+       'mwe-loading_plugin' => 'tykač so začituje ...',
+       'mwe-select_playback' => 'Nastajenje za playback stajić',
+       'mwe-link_back' => 'Wotkaz wróćo',
+       'mwe-error_swap_vid' => 'Zmylk: mv_embed njemóžeše widejotafličku za powjerch mv_embed wuměnić',
+       'mwe-add_to_end_of_sequence' => 'Na kóncu sekwency přidać',
+       'mwe-missing_video_stream' => 'Widejowa dataja za tutón prud faluje',
+       'mwe-play_clip' => 'Klip wothrać',
+       'mwe-pause_clip' => 'Klip zastajić',
+       'mwe-volume_control' => 'Regulowanje sylnosće zwuka',
+       'mwe-player_options' => 'Opcije wothrawaka',
+       'mwe-closed_captions' => 'Podtitule',
+       'mwe-player_fullscreen' => 'Połna wobrazowka',
+       'mwe-next_clip_msg' => 'Přichodny klip wothrać',
+       'mwe-prev_clip_msg' => 'Předchadny klip wothrać',
+       'mwe-current_clip_msg' => 'Tutón klip dale wothrać',
+       'mwe-seek_to' => '$1 pytać',
+       'mwe-paused' => 'zastajeny',
+       'mwe-download_segment' => 'Wuběr sćahnyć:',
+       'mwe-download_full' => 'Dospołnu widejowu dataju sćahnyć:',
+       'mwe-download_right_click' => 'Zo by sćahnył, klikń z prawej tastu a wubjer <i>Wotkaz składować jako...</i>',
+       'mwe-download_clip' => 'Widejo sćahnyć',
+       'mwe-download_text' => 'Tekst (<a style="color:white" title="cmml" href="http://wiki.xiph.org/index.php/CMML">CMML</a> xml) sćahnyć:',
+       'mwe-download' => 'Sćahnyć',
+       'mwe-share' => 'Dźělić',
+       'mwe-credits' => 'Dźakprajenje',
+       'mwe-clip_linkback' => 'Žórłow strona klipa',
+       'mwe-chose_player' => 'Widejowy wothrawak wubrać',
+       'mwe-share_this_video' => 'Tute widejo zhromadnje wužiwać',
+       'mwe-video_credits' => 'Dźakprajenja za wutworjenje wideja',
+       'mwe-menu_btn' => 'Meni',
+       'mwe-close_btn' => 'Začinić',
+       'mwe-ogg-player-vlc-player' => 'Wothrawak VLC',
+       'mwe-ogg-player-videoElement' => 'Widejo Native Ogg',
+       'mwe-ogg-player-oggPlugin' => 'Tykač Generic Ogg',
+       'mwe-ogg-player-quicktime-mozilla' => 'Tykač QuickTime',
+       'mwe-ogg-player-quicktime-activex' => 'ActiveX QuickTime',
+       'mwe-ogg-player-cortado' => 'Java Cortado',
+       'mwe-ogg-player-flowplayer' => 'Flowplayer',
+       'mwe-ogg-player-kplayer' => 'Wothrawak Kaltura',
+       'mwe-ogg-player-selected' => '(wubrany)',
+       'mwe-ogg-player-omtkplayer' => 'OMTK Flash Vorbis',
+       'mwe-generic_missing_plugin' => 'Zda so, zo twój wobhladowak slědowacy typ playbacka njepodpěruje: <b>$1</b><br />Wopytaj stronu <a href="http://commons.wikimedia.org/wiki/Commons:Media_help">metodow playbacka</a>, zo by wothrawak sćahnył.<br />',
+       'mwe-for_best_experience' => 'Za lěpše wideodožiwjenje playbacka poručamy:<br /><b><a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=mwEmbed">Firefox 3.5</a>.</b>',
+       'mwe-do_not_warn_again' => 'Za nětko wotpokazać.',
+       'mwe-playerselect' => 'Wothrawaki',
+       'mwe-read_before_embed' => 'Prošu <a href="http://mediawiki.org/wiki/Security_Notes_on_Remote_Embedding" target="_new">čitaj to</a> do zasadźenja!',
+       'mwe-embed_site_or_blog' => 'Na stronje zasadźić',
+       'mwe-related_videos' => 'Přiwuzne wideja',
+       'mwe-seeking' => 'pyta so',
+       'mwe-copy-code' => 'Kod kopěrować',
+       'mwe-video-h264' => 'Wideo H.264',
+       'mwe-video-flv' => 'Widejo Flash',
+       'mwe-video-ogg' => 'Ogg-widejo',
+       'mwe-video-audio' => 'Ogg-awdio',
+);
+
+/** Hungarian (Magyar)
+ * @author Dani
+ * @author Glanthor Reviol
+ * @author McDutchie
+ */
+$messages['hu'] = array(
+       'mwe-crop' => 'Kép vágása',
+       'mwe-apply_crop' => 'Vágás alkalmazása a képre',
+       'mwe-reset_crop' => 'Vágás alaphelyzetbe állítása',
+       'mwe-insert_image_page' => 'Beillesztés a lapra',
+       'mwe-insert_into_sequence' => 'Beillesztés a jelenetbe',
+       'mwe-preview_insert' => 'Beillesztés előnézete',
+       'mwe-cancel_image_insert' => 'Beillesztés elvetése',
+       'mwe-sc_fileopts' => 'A klip részleteinek szerkesztése',
+       'mwe-sc_inoutpoints' => 'Kezdő- és végpontok beállítása',
+       'mwe-sc_overlays' => 'Rétegek',
+       'mwe-sc_audio' => 'Hangvezérlés',
+       'mwe-sc_duration' => 'Hossz',
+       'mwe-template_properties' => 'Sablon tulajdonságai',
+       'mwe-custom_title' => 'Egyéni cím',
+       'mwe-edit_properties' => 'Tulajdonságok szerkesztése',
+       'mwe-other_properties' => 'Egyéb tulajdonságok',
+       'mwe-resource_page' => 'Erőforrás lap:',
+       'mwe-set_in_out_points' => 'Kezdő- és végpontok beállítása',
+       'mwe-start_time' => 'Kezdés ideje',
+       'mwe-end_time' => 'Befejezés ideje',
+       'mwe-preview_inout' => 'Kezdő- és végpontok megtekintése',
+       'mwe-edit-tools' => 'Szerkesztőeszközök',
+       'mwe-inline-description' => 'Cím',
+       'mwe-edit-video-tools' => 'Videóeszközök szerkesztése:',
+       'mwe-duration' => 'Hossz:',
+       'mwe-upload-subs-file' => 'Felirat feltöltése',
+       'mwe-add-subs-file-title' => 'Válaszd ki a feltöltendő feliratot',
+       'mwe-error-only-srt' => 'Csak srt fájlokat tölthetsz fel.',
+       'mwe-watch-video' => 'Videó megtekintése',
+       'mwe-select-other-language' => 'Másik nyelv választása',
+       'mwe-saving' => 'mentés…',
+       'mwe-select_transcript_set' => 'Feliratok kiválasztása',
+       'mwe-auto_scroll' => 'automatikus görgetés',
+       'mwe-close' => 'bezárás',
+       'mwe-improve_transcript' => 'Javítás',
+       'mwe-no_text_tracks_found' => 'Nincsenek szöveges feliratok',
+       'mwe-add-edit-subs' => 'Feliratok hozzáadása/szerkesztése',
+       'mwe-transition_in' => 'Áttűnés kezdete',
+       'mwe-transition_out' => 'Áttűnés vége',
+       'mwe-effects' => 'Effektverem',
+       'mwe-remove_transition' => 'Áttűnés eltávolítása',
+       'mwe-edit_transin' => 'Kezdő átmenet szerkesztése',
+       'mwe-edit_transout' => 'Klip végi átmenet szerkesztése',
+       'mwe-add-transition' => 'Átmenet hozzáadása',
+       'mwe-menu_clipedit' => 'Média szerkesztése',
+       'mwe-menu_transition' => 'Áttűnések és effektek',
+       'mwe-menu_cliplib' => 'Média hozzáadása',
+       'mwe-menu_resource_overview' => 'Erőforrás áttekintés',
+       'mwe-menu_options' => 'Beállítások',
+       'mwe-loading_timeline' => 'Idővonal betöltése…',
+       'mwe-loading_user_rights' => 'Felhasználói jogosultságok betöltése…',
+       'mwe-no_edit_permissions' => 'Nincs jogosultságod a változtatások elmentéséhez a jelenetbe',
+       'mwe-edit_clip' => 'Klip szerkesztése',
+       'mwe-edit_save' => 'Jelenet változásainak mentése',
+       'mwe-saving_wait' => 'Mentés folyamatban (kérlek várj)',
+       'mwe-save_done' => 'Mentés kész',
+       'mwe-edit_cancel' => 'Jelenet szerkesztésének eldobása',
+       'mwe-edit_cancel_confirm' => 'Biztos vagy benne, hogy megszakítod a szerkesztést? A változtatások elvesznek.',
+       'mwe-zoom_in' => 'Nagyítás',
+       'mwe-zoom_out' => 'Kicsinyítés',
+       'mwe-cut_clip' => 'Klipek vágása',
+       'mwe-expand_track' => 'Sáv kibontása',
+       'mwe-collapse_track' => 'Sáv összecsukása',
+       'mwe-play_from_position' => 'Lejátszás a lejátszó pozíciójától',
+       'mwe-pixle2sec' => 'képpontokat másodpercekké',
+       'mwe-rmclip' => 'Klip eltávolítása',
+       'mwe-clip_in' => 'klip eleji',
+       'mwe-clip_out' => 'klip végi',
+       'mwe-no_selected_resource' => '<h3>Nincs kiválasztott erőforrás</h3> Válassz egy klipet a szerkesztéshez.',
+       'mwe-error_edit_multiple' => '<h3>Több erőforrás kiválasztva</h3> Egy klipet válassz a szerkesztéséhez.',
+       'mwe-editor_options' => 'Szerkesztő beállításai',
+       'mwe-editor_mode' => 'Szerkesztői mód',
+       'mwe-simple_editor_desc' => 'egyszerű szerkesztő (iMovie stílusban)',
+       'mwe-advanced_editor_desc' => 'haladó szerkesztő (Final Cut stílusban)',
+       'mwe-other_options' => 'Egyéb beállítások',
+       'mwe-contextmenu_opt' => 'Helyi menük engedélyezése',
+       'mwe-sequencer_credit_line' => 'Fejlesztette a <a href="http://kaltura.com">Kaltura, Inc.</a> együttműködésben a <a href="http://wikimediafoundation.org/wiki/Home">Wikimédia Alapítvánnyal</a> (<a href="#">további információk</a>)',
+       'mwe-loading_txt' => 'betöltés…',
+       'mwe-error_load_lib' => 'Hiba: a(z) $1 JavaScript-fájl nem elérhető, vagy nem definiálja a(z) $2 osztályt.',
+       'mwe-loading-add-media-wiz' => 'Média hozzáadása varázsló betöltése',
+       'mwe-apiproxy-setup' => 'API proxy beállítása',
+       'mwe-load-drag-item' => 'Vonszolt elem betöltése',
+       'mwe-ok' => 'OK',
+       'mwe-cancel' => 'Mégse',
+       'mwe-setting-up-proxy' => 'Proxy beállítása…',
+       'mwe-re-try' => 'API kérés újrapróbálása',
+       'mwe-re-trying' => 'API kérés újraküldése…',
+       'mwe-proxy-not-ready' => 'A proxy nincs beállítva',
+       'mwe-please-login' => 'Nem vagy <a target="_new" href="$1">bejelentkezve</a> a(z) $2 wikire, vagy az mwEmbed nincs engedélyezve. Orvosold a problémát, majd próbáld újra a kérést.',
+       'mwe-remember-loging' => 'Általános biztonsági emlékeztető: csak akkor jelentkezz be egy weboldalra, ha a böngésződ címsorában annak az oldalnak a címét látod.',
+       'fogg-select_file' => 'Fájl kiválasztása',
+       'fogg-select_new_file' => 'Új fájl kiválasztása',
+       'fogg-select_url' => 'URL kiválasztása',
+       'fogg-save_local_file' => 'Ogg mentése',
+       'fogg-check_for_firefogg' => 'Firefogg keresése…',
+       'fogg-installed' => 'Firefogg telepítve',
+       'fogg-for_improved_uploads' => 'Fejlettebb feltöltésekhez:',
+       'fogg-please_install' => '<a href="$1">Firefogg telepítése</a>. További információkat <a href="http://commons.wikimedia.org/wiki/Commons:Firefogg">itt</a> találsz róla.',
+       'fogg-use_latest_firefox' => 'Először telepítsd a <a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=firefogg">Firefox 3.5</a>-ös, vagy újabb verzióját, <i>majd látogass el ide újra a <b>Firefogg</b>-kiterjesztés telepítéséhez.</i>',
+       'fogg-passthrough_mode' => 'Az általad kiválasztott fájl már Ogg formátumban van, vagy nem videófájl',
+       'fogg-transcoding' => 'Videó kódolása Ogg formátumba',
+       'fogg-encoding-done' => 'A kódolás kész',
+       'fogg-badtoken' => 'A token nem érvényes',
+       'fogg-preview' => 'Videó előnézete',
+       'fogg-hidepreview' => 'Előnézet elrejtése',
+       'mwe-imported_from' => 'A(z) $1 innen lett importálva: [$2 $3]. Lásd az eredeti [$4 leíró lapot] további információkért.',
+       'mwe-stream_title' => '$1 ($2–$3)',
+       'fogg-help-sticky' => 'Segítség (kattints a rögzítéshez)',
+       'fogg-cg-preset' => 'Beállítás: <strong>$1</strong>',
+       'fogg-cg-quality' => 'Alapszintű minőségi és felbontási beállítások',
+       'fogg-cg-meta' => 'Klip metaadatai',
+       'fogg-cg-range' => 'Átkódolási tartomány',
+       'fogg-cg-advVideo' => 'Fejlett videókódolási vezérlők',
+       'fogg-cg-advAudio' => 'Fejlett hangkódolási vezérlők',
+       'fogg-preset-custom' => 'Egyéni beállítások',
+       'fogg-webvideo-desc' => 'Theorával és Vorbisszal kódolt, 400 kbit/s-os, webre optimizált videó, legfeljebb 400 pixel széles',
+       'fogg-savebandwidth-desc' => 'Theorával és Vorbisszal kódolt, 164 kbit/s-os, alacsony sávszélességre optimizált videó, legfeljebb 200 pixel széles',
+       'fogg-highquality-desc' => 'Theorával és Vorbisszal kódolt, nagyfelbontású videó, legfeljebb 1080 pixel széles',
+       'fogg-videoQuality-title' => 'Videó minősége',
+       'fogg-videoQuality-help' => 'Megadja a kódolt videó <i>képének minőségét</i> (nincs használva, ha a fejlett vezérlőknél megadod a bitrátát).',
+       'fogg-starttime-title' => 'Kezdőmásodperc',
+       'fogg-starttime-help' => 'Csak ettől a másodperctől fog kódolni',
+       'fogg-endtime-title' => 'Befejező másodperc',
+       'fogg-endtime-help' => 'Csak eddig a másodpercig fog kódolni',
+       'fogg-audioQuality-title' => 'Hangminőség',
+       'fogg-audioQuality-help' => 'Megadja a kódolt videó <i>hangjának minőségét</i> (nincs használva, ha a fejlett vezérlőknél megadod a bitrátát).',
+       'fogg-videoCodec-title' => 'Videokodek',
+       'fogg-videoCodec-help' => 'Itt adhatod meg a videó kodekjét. Jelenleg csak a Theora támogatott. További információkat  <a target="_new" href="http://en.wikipedia.org/wiki/Theora">itt</a> találsz róla.',
+       'fogg-audioCodec-title' => 'Hangkodek',
+       'fogg-audioCodec-help' => 'Itt adhatod meg a videó hangkodekjét. Jelenleg csak a Vorbis támogatott. További információkat <a target="_new" href="http://en.wikipedia.org/wiki/Vorbis">itt</a> találsz róla.',
+       'fogg-width-title' => 'A videó szélessége',
+       'fogg-width-help' => 'Átméretezés megadott szélességre.',
+       'fogg-height-title' => 'A videó magassága',
+       'fogg-height-help' => 'Átméretezés megadott magasságra.',
+       'fogg-videoBitrate-title' => 'Videó bitsűrűség',
+       'fogg-videoBitrate-help' => 'A videó bitráta adja meg a videó kódolási bitsebességét, kb/s-ben',
+       'fogg-twopass-title' => 'Kétutas kódolás',
+       'fogg-twopass-help' => 'A kétutas kódolás lehetővé teszi a sokkal egyenletesebb minőséget az által, hogy kétszer megy végig a videófájlon',
+       'fogg-framerate-title' => 'Képváltási frekvencia',
+       'fogg-framerate-help' => 'A képváltási frekvencia. További információkat <a target="_new" href="http://en.wikipedia.org/wiki/Frame_rate">itt</a> tudhatsz meg róla.',
+       'fogg-aspect-title' => 'Képarány',
+       'fogg-aspect-help' => 'A videó képaránya lehet 4:3-as vagy 16:9-es.  További információkat <a target="_new" href="http://en.wikipedia.org/wiki/Aspect_ratio_%28image%29">itt</a> tudhatsz meg róla.',
+       'fogg-keyframeInterval-title' => 'Kulcskocka időköz',
+       'fogg-keyframeInterval-help' => 'A kulcskockák közötti szünetek, képkockák számában. Megjegyzés: a legtöbb kódoló kötelezően készít kulcskockát, ha a képkockák közötti különbség nagyobb, mint a kulcskocka kódolási mérete.
+További információkat <a href="http://en.wikipedia.org/wiki/I-frame">itt</a> tudhatsz meg róla.',
+       'fogg-denoise-title' => 'Zajmentesítő szűrő',
+       'fogg-denoise-help' => 'A bemeneti videó zajszűrése. (További információk a <a href="http://en.wikipedia.org/wiki/Video_denoising">zajszűrésről</a>.)',
+       'fogg-novideo-title' => 'Nincs videó',
+       'fogg-novideo-help' => 'videó letiltása a kimeneten',
+       'fogg-audioBitrate-title' => 'A hangsáv bitsebessége',
+       'fogg-samplerate-title' => 'Hang mintavételi frekvenciája',
+       'fogg-samplerate-help' => 'kimeneti mintavételi frekvencia beállítása (Hz).',
+       'fogg-noaudio-title' => 'Nincs hang',
+       'fogg-noaudio-help' => 'hang letiltása a kimeneten',
+       'fogg-title-title' => 'Cím',
+       'fogg-title-help' => 'A klip címe',
+       'fogg-artist-title' => 'Készítő neve',
+       'fogg-artist-help' => 'A klip készítője',
+       'fogg-date-title' => 'Dátum',
+       'fogg-date-help' => 'Az anyag elkészítésének vagy kiadásának dátuma',
+       'fogg-location-title' => 'Helyszín',
+       'fogg-location-help' => 'A film helyszíne',
+       'fogg-organization-title' => 'Szervezet',
+       'fogg-organization-help' => 'Szervezet neve (Stúdió)',
+       'fogg-copyright-title' => 'Szerzői jogi státusz',
+       'fogg-copyright-help' => 'A videó szerzői jogi státusza',
+       'fogg-license-title' => 'Licenc',
+       'fogg-license-help' => 'Az anyag licence (lehetőleg egy Creative Commons-licenc URL-címe).',
+       'fogg-contact-title' => 'Kapcsolat',
+       'fogg-contact-help' => 'Hivatkozás kapcsolattartáshoz',
+       'mwe-add_media_wizard' => 'Média hozzáadása varázsló',
+       'mwe-media_search' => 'Médiakeresés',
+       'rsd_box_layout' => 'Doboz elrendezése',
+       'rsd_list_layout' => 'Lista elrendezése',
+       'rsd_results_desc' => 'Eredmények $1 – $2',
+       'rsd_results_desc_total' => 'Találatok: $1–$2 (összesen: $3)',
+       'rsd_results_next' => 'következő',
+       'rsd_results_prev' => 'előző',
+       'rsd_no_results' => 'Nincs egyezés a(z) <b>$1</b> szöveggel',
+       'mwe-upload_tab' => 'Feltöltés',
+       'rsd_layout' => 'Elrendezés:',
+       'rsd_resource_edit' => 'Erőforrás szerkesztése: $1',
+       'mwe-resource_description_page' => 'Az erőforrás leírólapja',
+       'mwe-link' => 'hivatkozás',
+       'rsd_local_resource_title' => 'Helyi erőforrás-név',
+       'rsd_do_insert' => 'Beillesztés végrehajtása',
+       'mwe-cc_by_title' => 'Nevezd meg!',
+       'mwe-cc_nc_title' => 'Nemkereskedelmi',
+       'mwe-cc_nd_title' => 'Ne változtasd!',
+       'mwe-cc_sa_title' => 'Így add tovább!',
+       'mwe-cc_pd_title' => 'Közkincs',
+       'mwe-unknown_license' => 'Ismeretlen licenc',
+       'mwe-no_import_by_url' => 'Ez a felhasználó vagy wiki <b>nem</b> importálhat távoli URL-címekről.<p>Be kell jelentkezned?</p><p>Az upload_by_url jogosultság meg van adva számodra?<br />A wikin engedélyezve van a <a href="http://www.mediawiki.org/wiki/Manual:$wgAllowCopyUploads">$wgAllowCopyUploads</a>?</p>',
+       'mwe-results_from' => 'Találatok a következő helyről: <a href="$1" target="_new" >$2</a>',
+       'mwe-missing_desc_see_source' => 'Ez a médiatartalom nem rendelkezik leírással. Nézd meg az [$1 eredeti forrást] és segíts a leírás elkészítésében.',
+       'rsd_config_error' => 'Média hozzáadása varázsló konfigurációs hiba: $1',
+       'mwe-your_recent_uploads' => 'A friss feltöltéseid itt: $1',
+       'mwe-upload_a_file' => 'Új fájl feltöltése ide: $1',
+       'mwe-resource_page_desc' => 'Erőforrás lap leírása:',
+       'mwe-edit_resource_desc' => 'Az erőforrás wikiszöveges leírásának szerkesztése:',
+       'mwe-local_resource_title' => 'Helyi erőforrás cím:',
+       'mwe-watch_this_page' => 'Lap figyelése',
+       'mwe-do_import_resource' => 'Erőforrás importálása',
+       'mwe-update_preview' => 'Előnézet frissítése',
+       'mwe-cancel_import' => 'Importálás megszakítása',
+       'mwe-importing_asset' => 'Médiatartalom importálása',
+       'mwe-preview_insert_resource' => 'A következő erőforrás beillesztett változatának előnézete: $1',
+       'mwe-checking-resource' => 'Erőforrás keresése',
+       'mwe-resource-needs-import' => 'A(z) $1 erőforrást importálni kell ide: $2',
+       'mwe-ftype-svg' => 'SVG vektoros rajz',
+       'mwe-ftype-jpg' => 'JPEG képfájl',
+       'mwe-ftype-png' => 'PNG képfájl',
+       'mwe-ftype-oga' => 'Ogg hangfájl',
+       'mwe-ftype-ogg' => 'Ogg videófájl',
+       'mwe-ftype-unk' => 'Ismeretlen fájlformátum',
+       'rsd-wiki_commons-title' => 'Wikimedia Commons',
+       'rsd-wiki_commons' => 'Wikimedia Commons – szabad licencű, oktató médiatartalmak (képek, hangok és videóklipek) archívuma',
+       'rsd-this_wiki-title' => 'Ez a wiki',
+       'rsd-this_wiki-desc' => 'A helyben telepített wiki',
+       'rsd-archive_org-desc' => 'Internet Archive – kulturális műemlékek digitális könyvtára',
+       'rsd-flickr-desc' => 'Flickr.com – internetes fotómegosztó oldal',
+       'rsd-metavid-desc' => 'Metavid.org – az Amerikai Egyesült Államok képviselőházában és szenátusában történtek közösségi archívuma',
+       'mwe-select_file' => 'Fájl kijelölése',
+       'mwe-more_licence_options' => 'További licencelési lehetőségekért lásd a <a href="$1">rendes feltöltő űrlapot</a>',
+       'mwe-select_ownwork' => 'Teljesen általam készített munkát töltök fel, és a következő alatt licencelem:',
+       'mwe-licence_cc-by-sa' => 'Creative Commons Így add tovább! (3.0)',
+       'mwe-upload' => 'Fájl feltöltése',
+       'mwe-destfilename' => 'Cél fájlnév:',
+       'mwe-summary' => 'Összefoglaló',
+       'mwe-error_not_loggedin' => 'Nem vagy bejelentkezve, vagy nem tölthetsz fel fájlokat.',
+       'mwe-watch-this-file' => 'Fájl figyelése',
+       'mwe-ignore-any-warnings' => 'Figyelmeztetések figyelmen kívül hagyása',
+       'mwe-upload-transcode-in-progress' => 'Átkódolás és feltöltés folyamatban (ne zárd be ezt az ablakot)',
+       'mwe-upload-in-progress' => 'Feltöltés folyamatban (ne zárd be ezt az ablakot)',
+       'mwe-upload-transcoded-status' => 'Átkódolva',
+       'mwe-uploaded-status' => 'Feltöltött',
+       'mwe-upload-stats-fileprogress' => '$1 (összesen: $2)',
+       'mwe-upload_completed' => 'A feltöltés kész',
+       'mwe-upload_done' => '<a href="$1"><i>Lehet</i>, hogy a feltöltésed már elérhető</a>.',
+       'mwe-upload-unknown-size' => 'Ismeretlen méret',
+       'mwe-cancel-confim' => 'Biztos vagy benne, hogy megszakítod?',
+       'mwe-successfulupload' => 'Feltöltés sikeres',
+       'mwe-uploaderror' => 'Feltöltési hiba',
+       'mwe-uploadwarning' => 'Feltöltési figyelmeztetés',
+       'mwe-unknown-error' => 'Ismeretlen hiba:',
+       'mwe-return-to-form' => 'Visszatérés az űrlaphoz',
+       'mwe-file-exists-duplicate' => 'Ez a következő fájl duplikátuma:',
+       'mwe-fileexists' => 'Már létezik ilyen nevű fájl. Ellenőrizd a(z) <b><tt>$1</tt></b> fájlt, ha nem vagy biztos benne, hogy le szeretnéd cserélni.',
+       'mwe-fileexists-thumb' => '<center><b>Létező fájl</b></center>',
+       'mwe-ignorewarning' => 'Figyelmeztetés figyelmen kívül hagyása és a fájl mentése',
+       'mwe-file-thumbnail-no' => 'A fájlnév ezzel kezdődik: <b><tt>$1</tt></b>',
+       'mwe-go-to-resource' => 'Vissza az erőforrás lapra',
+       'mwe-upload-misc-error' => 'Ismeretlen feltöltési hiba',
+       'mwe-wgfogg_warning_bad_extension' => 'Egy olyan fájt választottál ki, aminek a kiterjesztése nem támogatott (<a href="http://commons.wikimedia.org/wiki/Commons:Firefogg#Supported_File_Types">további információk</a>).',
+       'mwe-upload-multi' => '{{PLURAL:$1|Fájl|Fájlok}} feltöltése',
+       'mwe-review-upload' => '{{PLURAL:$1|Feltöltés|Feltöltések}} ellenőrzése',
+       'mwe-loading_plugin' => 'bővítmény betöltése…',
+       'mwe-select_playback' => 'Használt lejátszó kiválasztása',
+       'mwe-link_back' => 'Visszahivatkozás',
+       'mwe-error_swap_vid' => 'Hiba: az mv_embed nem tudta kicserélni a videó taget az mv_embed felületére',
+       'mwe-add_to_end_of_sequence' => 'Hozzáadás a szekvencia végéhez',
+       'mwe-missing_video_stream' => 'Az adatfolyamhoz tartozó videofájl nincs meg',
+       'mwe-play_clip' => 'Klip lejátszása',
+       'mwe-pause_clip' => 'Klip pillanatállj',
+       'mwe-volume_control' => 'Hangerőszabályzó',
+       'mwe-player_options' => 'Lejátszó beállításai',
+       'mwe-closed_captions' => 'Feliratok',
+       'mwe-player_fullscreen' => 'Teljes képernyő',
+       'mwe-next_clip_msg' => 'Következő klip lejátszása',
+       'mwe-prev_clip_msg' => 'Előző klip lejátszása',
+       'mwe-current_clip_msg' => 'Klip lejátszásának folytatása',
+       'mwe-seek_to' => '$1 keresése',
+       'mwe-paused' => 'szüneteltetve',
+       'mwe-download_segment' => 'Kijelölés letöltése:',
+       'mwe-download_full' => 'Teljes videofájl letöltése:',
+       'mwe-download_right_click' => 'A letöltéshez kattints jobb gombbal, és <i>Cél mentése másként…</i>',
+       'mwe-download_clip' => 'Videó letöltése',
+       'mwe-download_text' => 'Szöveg letöltése (<a style="color:white" title="cmml" href="http://wiki.xiph.org/index.php/CMML">CMML</a> xml):',
+       'mwe-download' => 'Letöltés',
+       'mwe-share' => 'Megosztás',
+       'mwe-credits' => 'Készítők',
+       'mwe-clip_linkback' => 'Klip forráslapja',
+       'mwe-chose_player' => 'Videolejátszó választása',
+       'mwe-share_this_video' => 'Videó megosztása',
+       'mwe-video_credits' => 'A videó készítői',
+       'mwe-menu_btn' => 'Menü',
+       'mwe-close_btn' => 'Bezárás',
+       'mwe-ogg-player-vlc-player' => 'VLC player',
+       'mwe-ogg-player-videoElement' => 'Natív Ogg-videó',
+       'mwe-ogg-player-oggPlugin' => 'Általános Ogg bővítmény',
+       'mwe-ogg-player-quicktime-mozilla' => 'QuickTime-bővítmény',
+       'mwe-ogg-player-quicktime-activex' => 'QuickTime ActiveX',
+       'mwe-ogg-player-cortado' => 'Java Cortado',
+       'mwe-ogg-player-flowplayer' => 'Flowplayer',
+       'mwe-ogg-player-kplayer' => 'Kaltura lejátszó',
+       'mwe-ogg-player-selected' => '(kiválasztva)',
+       'mwe-ogg-player-omtkplayer' => 'OMTK Flash Vorbis',
+       'mwe-generic_missing_plugin' => 'A böngésző nem támogatja a következő lejátszási típust: <b>$1</b><br />Látogasd meg a <a href="http://commons.wikimedia.org/wiki/Commons:Media_help">Lejátszási módszerek</a> lapot egy lejátszó letöltéséhez.<br />',
+       'mwe-for_best_experience' => 'Jobb videolejátszási élményhez ajánljuk:<br /><b><a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=mwEmbed">Firefox 3.5</a>.</b>',
+       'mwe-do_not_warn_again' => 'Eltüntetés egyelőre.',
+       'mwe-playerselect' => 'Lejátszók',
+       'mwe-read_before_embed' => '<a href="http://mediawiki.org/wiki/Security_Notes_on_Remote_Embedding" target="_new">Olvasd el ezt</a>, mielőtt beillesztenéd.',
+       'mwe-embed_site_or_blog' => 'Beágyazás egy lapra',
+       'mwe-related_videos' => 'Kapcsolódó videók',
+       'mwe-seeking' => 'keresés',
+       'mwe-copy-code' => 'Kód másolása',
+       'mwe-credit-title' => 'Cím: $1',
+);
+
+/** Interlingua (Interlingua)
+ * @author McDutchie
+ */
+$messages['ia'] = array(
+       'mwe-crop' => 'Taliar imagine',
+       'mwe-apply_crop' => 'Facer un retalio del imagine',
+       'mwe-reset_crop' => 'Reinitialisar retalio',
+       'mwe-insert_image_page' => 'Inserer in pagina',
+       'mwe-insert_into_sequence' => 'Inserer in sequentia',
+       'mwe-preview_insert' => 'Previsualisar insertion',
+       'mwe-cancel_image_insert' => 'Cancellar insertion',
+       'mwe-sc_fileopts' => 'Modificar detalios del clip',
+       'mwe-sc_inoutpoints' => 'Definir punctos entrata-sortita',
+       'mwe-sc_overlays' => 'Superpositiones',
+       'mwe-sc_audio' => 'Controlo audio',
+       'mwe-sc_duration' => 'Duration',
+       'mwe-template_properties' => 'Proprietates de patrono',
+       'mwe-custom_title' => 'Titulo personalisate',
+       'mwe-edit_properties' => 'Modificar proprietates',
+       'mwe-other_properties' => 'Altere proprietates',
+       'mwe-resource_page' => 'Pagina del ressource:',
+       'mwe-set_in_out_points' => 'Definir punctos entrata-sortita',
+       'mwe-start_time' => 'Hora de initio',
+       'mwe-end_time' => 'Hora de fin',
+       'mwe-preview_inout' => 'Previsualisar punctos entrata-sortita',
+       'mwe-edit-tools' => 'Instrumentos de modification',
+       'mwe-inline-description' => 'Legenda',
+       'mwe-edit-video-tools' => 'Instrumentos de modification de video:',
+       'mwe-duration' => 'Durata:',
+       'mwe-upload-subs-file' => 'Cargar subtitulo',
+       'mwe-add-subs-file-title' => 'Selige le subtitulo a cargar',
+       'mwe-error-only-srt' => 'Solmente le files srt pote esser cargate a iste momento.',
+       'mwe-watch-video' => 'Reguardar video',
+       'mwe-select-other-language' => 'Seliger altere lingua',
+       'mwe-saving' => 'salveguarda...',
+       'mwe-select_transcript_set' => 'Seliger subtitulos',
+       'mwe-auto_scroll' => 'rolar automaticamente',
+       'mwe-close' => 'clauder',
+       'mwe-improve_transcript' => 'Meliorar',
+       'mwe-no_text_tracks_found' => 'Nulle tracia de texto trovate',
+       'mwe-add-edit-subs' => 'Adder/modificar subtitulos',
+       'mwe-transition_in' => 'Transition entrante',
+       'mwe-transition_out' => 'Transition sortiente',
+       'mwe-effects' => 'Pila de effectos',
+       'mwe-remove_transition' => 'Remover transition',
+       'mwe-edit_transin' => 'Inserer transition in clip',
+       'mwe-edit_transout' => 'Remover transition del clip',
+       'mwe-add-transition' => 'Adder un transition',
+       'mwe-menu_clipedit' => 'Modificar multimedia',
+       'mwe-menu_transition' => 'Transitiones e effectos',
+       'mwe-menu_cliplib' => 'Adder multimedia',
+       'mwe-menu_resource_overview' => 'Summario de ressources',
+       'mwe-menu_options' => 'Optiones',
+       'mwe-loading_timeline' => 'Carga chronologia ...',
+       'mwe-loading_user_rights' => 'Carga derectos de usator ...',
+       'mwe-no_edit_permissions' => 'Tu non ha le permission de immagazinar modificationes a iste sequentia',
+       'mwe-edit_clip' => 'Modificar clip',
+       'mwe-edit_save' => 'Immagazinar modificationes del sequentia',
+       'mwe-saving_wait' => 'Immagazinage in curso (per favor attende)',
+       'mwe-save_done' => 'Immagazinage complete',
+       'mwe-edit_cancel' => 'Cancellar modification del sequentia',
+       'mwe-edit_cancel_confirm' => 'Es tu secur de voler cancellar tu modification? Le cambiamentos essera perdite.',
+       'mwe-zoom_in' => 'Zoom avante',
+       'mwe-zoom_out' => 'Zoom retro',
+       'mwe-cut_clip' => 'Trenchar clips',
+       'mwe-expand_track' => 'Expander tracia',
+       'mwe-collapse_track' => 'Contraher tracia',
+       'mwe-play_from_position' => 'Reproducer a partir del position de lectura',
+       'mwe-pixle2sec' => 'pixeles a secundas',
+       'mwe-rmclip' => 'Remover clip',
+       'mwe-clip_in' => 'attachar',
+       'mwe-clip_out' => 'distachar',
+       'mwe-no_selected_resource' => '<h3>Nulle ressource seligite</h3> Selige un clip pro activar le modification.',
+       'mwe-error_edit_multiple' => '<h3>Plure ressources seligite</h3> Selige un sol clip pro modificar lo.',
+       'mwe-editor_options' => 'Optiones de editor',
+       'mwe-editor_mode' => 'Modo de editor',
+       'mwe-simple_editor_desc' => 'editor simple (stilo iMovie)',
+       'mwe-advanced_editor_desc' => 'editor avantiate (stilo Final Cut)',
+       'mwe-other_options' => 'Altere optiones',
+       'mwe-contextmenu_opt' => 'Activar menus contextual',
+       'mwe-sequencer_credit_line' => 'Disveloppate per <a href="http://kaltura.com">Kaltura, Inc.</a> in association con le <a href="http://wikimediafoundation.org/wiki/Home">Fundation Wikimedia</a> (<a href="#">plus information</a>).',
+       'mwe-loading_txt' => 'cargamento ...',
+       'mwe-error_load_lib' => 'Error: JavaScript $1 non esseva recuperabile o non defini $2',
+       'mwe-loading-add-media-wiz' => 'Cargamento del assistente pro adder multimedia',
+       'mwe-apiproxy-setup' => 'Configuration del proxy pro le API',
+       'mwe-load-drag-item' => 'Cargamento del file trahite',
+       'mwe-ok' => 'OK',
+       'mwe-cancel' => 'Cancella',
+       'mwe-setting-up-proxy' => 'Configuration del proxy...',
+       'mwe-re-try' => 'Reprobar requesta API',
+       'mwe-re-trying' => 'Reproba requesta API...',
+       'mwe-proxy-not-ready' => 'Le proxy non es configurate',
+       'mwe-please-login' => 'Tu non es <a target="_new" href="$1">identificate</a> in $2 o mwEmbed non ha essite activate. Resolve le problema, alora reproba le requesta.',
+       'mwe-remember-loging' => 'Promemoria general de securitate: Solmente identifica te a sitos web si tu barra de adresse monstra le adresse del sito in question.',
+       'fogg-select_file' => 'Seliger file',
+       'fogg-select_new_file' => 'Seliger nove file',
+       'fogg-select_url' => 'Seliger URL',
+       'fogg-save_local_file' => 'Immagazinar in Ogg',
+       'fogg-check_for_firefogg' => 'Verifica presentia de Firefogg ...',
+       'fogg-installed' => 'Firefogg es installate',
+       'fogg-for_improved_uploads' => 'Pro cargamentos meliorate:',
+       'fogg-please_install' => '<a href="$1">Installar Firefogg</a>. Plus information <a href="http://commons.wikimedia.org/wiki/Commons:Firefogg">a proposito de Firefogg</a>',
+       'fogg-use_latest_firefox' => 'Per favor primo installa <a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=firefogg">Firefox 3.5</a> (o plus recente). <i>Alora revisita iste pagina pro installar le extension <b>Firefogg</b>.</i>',
+       'fogg-passthrough_mode' => 'Le file que tu seligeva ja es in Ogg, o non es un file video',
+       'fogg-transcoding' => 'Codification del video in Ogg',
+       'fogg-encoding-done' => 'Codification complete',
+       'fogg-badtoken' => 'Le indicio non es valide',
+       'fogg-preview' => 'Previsualisar video',
+       'fogg-hidepreview' => 'Celar previsualisation',
+       'mwe-imported_from' => '$1 importate ex [$2 $3]. Vide le [$4 pagina del ressource] original pro plus information.',
+       'mwe-stream_title' => '$1 $2 a $3',
+       'fogg-help-sticky' => 'Adjuta (clicca pro tener)',
+       'fogg-cg-preset' => 'Predefinite: <strong>$1</strong>',
+       'fogg-cg-quality' => 'Controlo basic de qualitate e resolution',
+       'fogg-cg-meta' => 'Metadatos pro le clip',
+       'fogg-cg-range' => 'Portata de codification',
+       'fogg-cg-advVideo' => 'Controlos avantiate de codification de video',
+       'fogg-cg-advAudio' => 'Controlos avantiate de codification de audio',
+       'fogg-preset-custom' => 'Configurationes personalisate',
+       'fogg-webvideo-desc' => 'Video web Theora, Vorbis 400 kbit/s e 400px latitude maximal',
+       'fogg-savebandwidth-desc' => 'Theora a basse largessa de banda, Vorbos 164 kbit/s e 200px latitude maximal',
+       'fogg-highquality-desc' => 'Theora de alte qualitate, Vorbis 1080px largessa maximal',
+       'fogg-videoQuality-title' => 'Qualitate de video',
+       'fogg-videoQuality-help' => 'Usate pro definir le <i>qualitate visual</i> del video codificate (non usate si tu defini le taxa de bits in le controlos avantiate ci infra).',
+       'fogg-starttime-title' => 'Secunda de initio',
+       'fogg-starttime-help' => 'Solmente codificar desde tempore in secundas',
+       'fogg-endtime-title' => 'Secunda de fin',
+       'fogg-endtime-help' => 'Solmente codificar usque a tempore in secundas',
+       'fogg-audioQuality-title' => 'Qualitate del audio',
+       'fogg-audioQuality-help' => 'Usate pro definir le <i>qualitate acoustic</i> del audio codificate (non usate si tu defini le taxa de bits in le controlos avantiate ci infra).',
+       'fogg-videoCodec-title' => 'Codec de video',
+       'fogg-videoCodec-help' => 'Usate pro seliger le codec video del clip. Al presente, solo Theora es supportate. Lege plus a proposito del <a target="_new" href="http://ia.wikipedia.org/wiki/Theora">codec Theora</a>.',
+       'fogg-audioCodec-title' => 'Codec de audio',
+       'fogg-audioCodec-help' => 'Usate pro seliger le codec audio del clip. Al presente, solo Vorbis es supportate. Lege plus a proposito del <a target="_new" href="http://ia.wikipedia.org/wiki/Vorbis">codec Vorbis</a>.',
+       'fogg-width-title' => 'Latitude del video',
+       'fogg-width-help' => 'Redimensionar al latitude date.',
+       'fogg-height-title' => 'Altitude del video',
+       'fogg-height-help' => 'Redimensionar al altitude date.',
+       'fogg-videoBitrate-title' => 'Taxa de bits del video',
+       'fogg-videoBitrate-help' => 'Le taxa de bits vole dicer le velocitate de codification del video (in kb/s).',
+       'fogg-twopass-title' => 'Codification in duo passos',
+       'fogg-twopass-help' => 'Le codification in duo passos permitte un qualitate plus constante per processar le file video duo vices.',
+       'fogg-framerate-title' => 'Photogrammas per secunda',
+       'fogg-framerate-help' => 'Le numero de imagines per secunda in le video. Lege plus a proposito de <a target="_new" href="http://ia.wikipedia.org/wiki/Photogrammas_per_secunda">photogrammas per secunda</a>.',
+       'fogg-aspect-title' => 'Ration de aspecto',
+       'fogg-aspect-help' => 'Le ration de aspecto del video pote esser 4:3 o 16:9. Lege plus a proposito de <a target="_new" href="http://ia.wikipedia.org/wiki/Ration_de_aspecto_%28imagine%29">rationes de aspecto</a>.',
+       'fogg-keyframeInterval-title' => 'Intervallo de photogrammas clave',
+       'fogg-keyframeInterval-help' => 'Le intervallo inter photogrammas clave, in numero de imagines. Nota ben: Le major parte del codecs fortia le photogrammas clave si le differentia inter le photogrammas es plus grande que le dimension de codification del photogramma clave. Lege plus a proposito de <a href="http://en.wikipedia.org/wiki/I-frame">photogrammas clave</a>.',
+       'fogg-denoise-title' => 'Filtro anti-ruito',
+       'fogg-denoise-help' => 'Elimina le ruito del video. Lege plus a proposito del <a href="http://en.wikipedia.org/wiki/Video_denoising">suppression de ruito</a>.',
+       'fogg-novideo-title' => 'Nulle video',
+       'fogg-novideo-help' => 'disactivar video in le producto',
+       'fogg-audioBitrate-title' => 'Taxa de bits del audio',
+       'fogg-samplerate-title' => 'Frequentia de monstras del audio',
+       'fogg-samplerate-help' => 'definir le frequentia de monstras del producto (in Hz).',
+       'fogg-noaudio-title' => 'Nulle audio',
+       'fogg-noaudio-help' => 'disactivar audio in le producto',
+       'fogg-title-title' => 'Titulo',
+       'fogg-title-help' => 'Un titulo pro tu clip',
+       'fogg-artist-title' => 'Nomine del creator',
+       'fogg-artist-help' => 'Le creator de iste clip',
+       'fogg-date-title' => 'Data',
+       'fogg-date-help' => 'Le data de creation o publication del material',
+       'fogg-location-title' => 'Loco',
+       'fogg-location-help' => 'Le loco de filmation del material',
+       'fogg-organization-title' => 'Organisation',
+       'fogg-organization-help' => 'Nomine del organisation (studio)',
+       'fogg-copyright-title' => 'Copyright',
+       'fogg-copyright-help' => 'Le derectos de autor del clip',
+       'fogg-license-title' => 'Licentia',
+       'fogg-license-help' => 'Le licentia del clip (preferibilemente un URL de Creative Commons).',
+       'fogg-contact-title' => 'Contacto',
+       'fogg-contact-help' => 'Ligamine de contacto',
+       'mwe-add_media_wizard' => 'Adder assistente pro multimedia',
+       'mwe-media_search' => 'Recerca de multimedia',
+       'rsd_box_layout' => 'Disposition in quadros',
+       'rsd_list_layout' => 'Disposition in listas',
+       'rsd_results_desc' => 'Resultatos $1 a $2',
+       'rsd_results_desc_total' => 'Resultatos $1 a $2 de $3',
+       'rsd_results_next' => 'sequente',
+       'rsd_results_prev' => 'precedente',
+       'rsd_no_results' => 'Nulle resultato de recerca pro <b>$1</b>',
+       'mwe-upload_tab' => 'Cargar',
+       'rsd_layout' => 'Disposition:',
+       'rsd_resource_edit' => 'Modificar le ressource: $1',
+       'mwe-resource_description_page' => 'Pagina de description del ressource',
+       'mwe-link' => 'ligamine',
+       'rsd_local_resource_title' => 'Titulo local del ressource',
+       'rsd_do_insert' => 'Facer insertion',
+       'mwe-cc_by_title' => 'Attribution',
+       'mwe-cc_nc_title' => 'Non commercial',
+       'mwe-cc_nd_title' => 'Nulle obras derivate',
+       'mwe-cc_sa_title' => 'Condivider equalmente',
+       'mwe-cc_pd_title' => 'Dominio public',
+       'mwe-unknown_license' => 'Licentia incognite',
+       'mwe-no_import_by_url' => 'Iste usator o wiki <b>non pote</b> facer importationes ab URLs remote.<p>Debe tu aperir un session?</p><p>Es le permission upload_by_url definite pro te?<br />Es <a href="http://www.mediawiki.org/wiki/Manual:$wgAllowCopyUploads">$wgAllowCopyUploads</a> activate in le wiki?</p>',
+       'mwe-results_from' => 'Resultatos ab <a href="$1" target="_new" >$2</a>',
+       'mwe-missing_desc_see_source' => 'Il manca un description a iste ressource. Per favor consulta le [$1 origine] e adjuta a describer lo.',
+       'rsd_config_error' => 'Error de configuration in le assistente pro adder multimedia: $1',
+       'mwe-your_recent_uploads' => 'Tu cargas recente a $1',
+       'mwe-upload_a_file' => 'Cargar un nove file a $1',
+       'mwe-resource_page_desc' => 'Description del pagina de ressource:',
+       'mwe-edit_resource_desc' => 'Modificar le wikitexto del description del ressource:',
+       'mwe-local_resource_title' => 'Titulo local del ressource:',
+       'mwe-watch_this_page' => 'Observar iste pagina',
+       'mwe-do_import_resource' => 'Importar ressource',
+       'mwe-update_preview' => 'Actualisar previsualisation',
+       'mwe-cancel_import' => 'Cancellar importation',
+       'mwe-importing_asset' => 'Importation in curso',
+       'mwe-preview_insert_resource' => 'Previsualiar le insertion del ressource: $1',
+       'mwe-checking-resource' => 'Verification de ressource',
+       'mwe-resource-needs-import' => 'Le ressource $1 debe esser importate in $2',
+       'mwe-ftype-svg' => 'File de vectores SVG',
+       'mwe-ftype-jpg' => 'File de imagine JPEG',
+       'mwe-ftype-png' => 'File de imagine PNG',
+       'mwe-ftype-oga' => 'File de audio Ogg',
+       'mwe-ftype-ogg' => 'File de video Ogg',
+       'mwe-ftype-unk' => 'Formato de file incognite',
+       'rsd-wiki_commons-title' => 'Wikimedia Commons',
+       'rsd-wiki_commons' => 'Wikimedia Commons, un archivo de contento multimedial educative sub licentia libere (imagines, audio e video)',
+       'rsd-this_wiki-title' => 'Iste wiki',
+       'rsd-this_wiki-desc' => 'Le installation wiki local',
+       'rsd-archive_org-desc' => "Le ''Internet Archive'', un bibliotheca digital de artefactos cultural",
+       'rsd-flickr-desc' => 'Flickr.com, un sito pro condivider photos in linea',
+       'rsd-metavid-desc' => 'Metavid.org, un archivo communitari de actiones del Camera de representantes e Senato del SUA',
+       'mwe-select_file' => 'Seliger file',
+       'mwe-more_licence_options' => 'Pro ulterior optiones de licentia, vide le <a href="$1">pagina de carga normal</a>',
+       'mwe-select_ownwork' => 'Io carga un obra integremente mie, publicante lo sub le licentia:',
+       'mwe-licence_cc-by-sa' => 'Share Alike de Creative Commons (3.0)',
+       'mwe-upload' => 'Cargar file',
+       'mwe-destfilename' => 'Nomine del file de destination:',
+       'mwe-summary' => 'Summario',
+       'mwe-error_not_loggedin' => 'Il pare que tu non ha aprite un session o que tu non ha le privilegio de cargar files.',
+       'mwe-watch-this-file' => 'Observar iste file',
+       'mwe-ignore-any-warnings' => 'Ignorar omne advertimentos',
+       'mwe-upload-transcode-in-progress' => 'Transcodification e cargamento in progresso (non claude iste fenestra)',
+       'mwe-upload-in-progress' => 'Cargamento in progresso (non claude iste fenestra)',
+       'mwe-upload-transcoded-status' => 'Transcodificate',
+       'mwe-uploaded-status' => 'Cargate',
+       'mwe-upload-stats-fileprogress' => '$1 de $2',
+       'mwe-upload_completed' => 'Tu cargamento es complete',
+       'mwe-upload_done' => '<a href="$1">Tu cargamento <i>deberea esser</i> accessibile</a>.',
+       'mwe-upload-unknown-size' => 'Dimension incognite',
+       'mwe-cancel-confim' => 'Es tu secur de voler cancellar?',
+       'mwe-successfulupload' => 'Cargamento succedite',
+       'mwe-uploaderror' => 'Error de cargamento',
+       'mwe-uploadwarning' => 'Advertimento de cargamento',
+       'mwe-unknown-error' => 'Error incognite:',
+       'mwe-return-to-form' => 'Retornar al formulario',
+       'mwe-file-exists-duplicate' => 'Iste file es un duplicato del file sequente:',
+       'mwe-fileexists' => 'Un file con iste nomine ja existe. Per favor verifica <b><tt>$1</tt></b> si tu non es secur de voler cambiar lo.',
+       'mwe-fileexists-thumb' => '<center><b>File existente</b></center>',
+       'mwe-ignorewarning' => 'Ignorar le advertimento e immagazinar le file totevia',
+       'mwe-file-thumbnail-no' => 'Le nomine de file comencia con <b><tt>$1</tt></b>',
+       'mwe-go-to-resource' => 'Ir al pagina del ressource',
+       'mwe-upload-misc-error' => 'Error incognite de cargamento',
+       'mwe-wgfogg_warning_bad_extension' => 'Tu ha seligite un file con un extension non supportate (<a href="http://commons.wikimedia.org/wiki/Commons:Firefogg#Supported_File_Types">plus informationes</a>).',
+       'mwe-upload-multi' => 'Cargar {{PLURAL:$1|file|files}}',
+       'mwe-review-upload' => 'Revider le {{PLURAL:$1|cargamento del file|cargamentos del files}}',
+       'mwe-credit-title' => 'Titulo: $1',
+       'mwe-loading_plugin' => 'cargamento del plug-in ...',
+       'mwe-select_playback' => 'Definir preferentia de reproduction',
+       'mwe-link_back' => 'Retroligamine',
+       'mwe-error_swap_vid' => 'Error: mv_embed non poteva excambiar le etiquetta de video pro le interfacie mv_embed',
+       'mwe-add_to_end_of_sequence' => 'Adder al fin del sequentia',
+       'mwe-missing_video_stream' => 'Le file de video pro iste fluxo es mancante',
+       'mwe-play_clip' => 'Reproducer clip',
+       'mwe-pause_clip' => 'Pausar clip',
+       'mwe-volume_control' => 'Controlo de volumine',
+       'mwe-player_options' => 'Optiones de reproductor',
+       'mwe-closed_captions' => 'Subtitulos',
+       'mwe-player_fullscreen' => 'Plen schermo',
+       'mwe-next_clip_msg' => 'Reproducer sequente clip',
+       'mwe-prev_clip_msg' => 'Reproducer precedente clip',
+       'mwe-current_clip_msg' => 'Continuar a reproducer iste clip',
+       'mwe-seek_to' => 'Ir a $1',
+       'mwe-paused' => 'in pausa',
+       'mwe-download_segment' => 'Discargar selection:',
+       'mwe-download_full' => 'Discargar file de video complete:',
+       'mwe-download_right_click' => 'Pro discargar, face clic a dextra e selige <i>Immagazinar ligamine como...</i> (Save link as...)',
+       'mwe-download_clip' => 'Discargar video',
+       'mwe-download_text' => 'Discargar texto (<a style="color:white" title="cmml" href="http://wiki.xiph.org/index.php/CMML">CMML</a> xml):',
+       'mwe-download' => 'Discargar',
+       'mwe-share' => 'Condivider',
+       'mwe-credits' => 'Creditos',
+       'mwe-clip_linkback' => 'Pagina de fonte del clip',
+       'mwe-chose_player' => 'Seliger reproductor de video',
+       'mwe-share_this_video' => 'Condivider iste video',
+       'mwe-video_credits' => 'Creditos de video',
+       'mwe-menu_btn' => 'Menu',
+       'mwe-close_btn' => 'Clauder',
+       'mwe-ogg-player-vlc-player' => 'Reproductor VLC',
+       'mwe-ogg-player-videoElement' => 'Video Ogg native',
+       'mwe-ogg-player-oggPlugin' => 'Plug-in generic pro Ogg',
+       'mwe-ogg-player-quicktime-mozilla' => 'Plug-in de QuickTime',
+       'mwe-ogg-player-quicktime-activex' => 'QuickTime ActiveX',
+       'mwe-ogg-player-cortado' => 'Java Cortado',
+       'mwe-ogg-player-flowplayer' => 'Flowplayer',
+       'mwe-ogg-player-kplayer' => 'Le reproductor Kaltura',
+       'mwe-ogg-player-selected' => '(seligite)',
+       'mwe-ogg-player-omtkplayer' => 'OMTK Flash Vorbis',
+       'mwe-generic_missing_plugin' => 'Tu navigator non pare supportar le sequente typo de reproduction: <b>$1</b><br />Visita le pagina super <a href="http://commons.wikimedia.org/wiki/Commons:Media_help">methodos de reproduction</a> pro discargar un reproductor.<br />',
+       'mwe-for_best_experience' => 'Pro un melior experientia de reproduction de video, nos recommenda:<br /><b><a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=mwEmbed">Firefox 3.5</a>.</b>',
+       'mwe-do_not_warn_again' => 'Dimitter pro le momento.',
+       'mwe-playerselect' => 'Reproductores',
+       'mwe-read_before_embed' => 'Per favor lege le <a href="http://mediawiki.org/wiki/Security_Notes_on_Remote_Embedding" target="_new">notas de securitate super incastramento remote</a> ante de incastrar un cosa!',
+       'mwe-embed_site_or_blog' => 'Incastrar in un pagina',
+       'mwe-related_videos' => 'Videos connexe',
+       'mwe-seeking' => 'cercante',
+       'mwe-copy-code' => 'Copiar codice',
+       'mwe-video-h264' => 'Video H.264',
+       'mwe-video-flv' => 'Video Flash',
+       'mwe-video-ogg' => 'Video Ogg',
+       'mwe-video-audio' => 'Audio Ogg',
+);
+
+/** Indonesian (Bahasa Indonesia)
+ * @author Bennylin
+ * @author Irwangatot
+ * @author IvanLanin
+ */
+$messages['id'] = array(
+       'mwe-crop' => 'Potong gambar',
+       'mwe-apply_crop' => 'Terapkan pemotongan gambar',
+       'mwe-reset_crop' => 'Kembalikan pemotongan',
+       'mwe-insert_image_page' => 'Sisipkan pada halaman',
+       'mwe-insert_into_sequence' => 'Sisipkan pada urutan',
+       'mwe-preview_insert' => 'Sisipkan pratayang',
+       'mwe-cancel_image_insert' => 'Batalkan penyisipan',
+       'mwe-sc_fileopts' => 'Suntingan detail klip',
+       'mwe-sc_inoutpoints' => 'Atur titik masuk-keluar',
+       'mwe-sc_overlays' => 'Hamparan',
+       'mwe-sc_audio' => 'Kontrol audio',
+       'mwe-sc_duration' => 'Durasi',
+       'mwe-template_properties' => 'Properti Templat',
+       'mwe-custom_title' => 'Judul buatan',
+       'mwe-edit_properties' => 'Sunting properti',
+       'mwe-other_properties' => 'Properti lain',
+       'mwe-resource_page' => 'Sumber halaman:',
+       'mwe-set_in_out_points' => 'Atur titik masuk-keluar',
+       'mwe-start_time' => 'Waktu mulai',
+       'mwe-end_time' => 'Waktu selesai',
+       'mwe-preview_inout' => 'Pratayang titik masuk-keluar',
+       'mwe-edit-tools' => 'Alat penyuntingan',
+       'mwe-inline-description' => 'Judul',
+       'mwe-edit-video-tools' => 'Alat Penyuntingan Video:',
+       'mwe-duration' => 'Durasi:',
+       'mwe-upload-subs-file' => 'Unggah teks video',
+       'mwe-add-subs-file-title' => 'Pilih teks video untuk diunggah',
+       'mwe-error-only-srt' => 'Anda hanya dapat mengunggah berkas srt.',
+       'mwe-watch-video' => 'Tonton video',
+       'mwe-select-other-language' => 'Piliha bahasa lain',
+       'mwe-saving' => 'menyimpan..',
+       'mwe-select_transcript_set' => 'Pilih teks video',
+       'mwe-auto_scroll' => 'Gulir otomatis',
+       'mwe-close' => 'Tutup',
+       'mwe-improve_transcript' => 'Membaiki',
+       'mwe-no_text_tracks_found' => 'Tidak ada trek teks yang ditemukan',
+       'mwe-add-edit-subs' => 'Tambah/sunting subjudul',
+       'mwe-transition_in' => 'Transisi masuk',
+       'mwe-transition_out' => 'Transisi keluar',
+       'mwe-effects' => 'Tumpuk efek',
+       'mwe-remove_transition' => 'Singkirkan transisi',
+       'mwe-edit_transin' => 'Sunting transisi masuk klip',
+       'mwe-edit_transout' => 'Sunting transisi keluar klip',
+       'mwe-add-transition' => 'Tambahkan transisi',
+       'mwe-menu_clipedit' => 'Sunting media',
+       'mwe-menu_transition' => 'Transisi dan efek',
+       'mwe-menu_cliplib' => 'Tambah media',
+       'mwe-menu_resource_overview' => 'Tinjauan sumber daya',
+       'mwe-menu_options' => 'Pilihan',
+       'mwe-loading_timeline' => 'Memuat garis waktu ...',
+       'mwe-loading_user_rights' => 'Memuat hak pengguna ...',
+       'mwe-no_edit_permissions' => 'Anda tidak memiliki hak untuk menyimpan perubahan pada bagian ini',
+       'mwe-edit_clip' => 'Sunting klip',
+       'mwe-edit_save' => 'Simpan perubahan urutan',
+       'mwe-saving_wait' => 'Penyimpanan dalam proses (mohoon tunggu)',
+       'mwe-save_done' => 'Menyimpanan lengkap',
+       'mwe-edit_cancel' => 'Batalkan suntingan urutan',
+       'mwe-edit_cancel_confirm' => 'Apakan anda yakin akan membatalkan suntingan anda? Perubahan akan hilang.',
+       'mwe-zoom_in' => 'Zum masuk',
+       'mwe-zoom_out' => 'Zum keluar',
+       'mwe-cut_clip' => 'Potong klip',
+       'mwe-expand_track' => 'Kembangkan trek',
+       'mwe-collapse_track' => 'Ciutkan trek',
+       'mwe-play_from_position' => 'Putar dari posisi playline',
+       'mwe-pixle2sec' => 'piksel ke detik',
+       'mwe-rmclip' => 'Hapus klip',
+       'mwe-clip_in' => 'klip masuk',
+       'mwe-clip_out' => 'klip keluar',
+       'mwe-no_selected_resource' => '<h3>Tidak ada sumber dipilih</h3> Pilih klip untuk mengaktifkan suntingan.',
+       'mwe-error_edit_multiple' => '<h3>Beberapa sumber telah dipilih</h3> Pilih satu klip untuk disunting.',
+       'mwe-editor_options' => 'Pilihan penyunting',
+       'mwe-editor_mode' => 'Modus sunting',
+       'mwe-simple_editor_desc' => 'suntingan sederhana (gaya iMovie)',
+       'mwe-advanced_editor_desc' => 'suntingan lanjutan (gaya potongan akhir)',
+       'mwe-other_options' => 'Pilihan lain',
+       'mwe-contextmenu_opt' => 'Aktifkan menu konteks',
+       'mwe-sequencer_credit_line' => 'Dikembangkan oleh <a href="http://kaltura.com">Kaltura, Inc</a> bekerja sama dengan <a href="http://wikimediafoundation.org/wiki/Home">Wikimedia Foundation</a> (<a href="#">informasi lebih lanjut</a>).',
+       'mwe-loading_txt' => 'memuat...',
+       'mwe-error_load_lib' => 'Kesalahan: JavaScript $1 tidak dapat diambil atau tidak mendefinisikan $2',
+       'mwe-loading-add-media-wiz' => 'Memuat pemandu penambah media',
+       'mwe-apiproxy-setup' => 'Menyiapkan proksi API',
+       'mwe-load-drag-item' => 'Memuat butir terseret',
+       'mwe-ok' => 'Oke',
+       'mwe-cancel' => 'Batalkan',
+       'mwe-setting-up-proxy' => 'Menyiapkan proksi...',
+       'mwe-re-try' => 'Ulangi permintaan API',
+       'mwe-re-trying' => 'Mengulangi permintaan API...',
+       'mwe-proxy-not-ready' => 'Proksi tak dapat dikonfigurasi',
+       'mwe-please-login' => 'Anda tidak <a target="_new" href="$1">masuk log</a> di $2 atau mwEmbed belum diaktifkan. Perbaiki masalah ini, dan ulangi permintaan.',
+       'mwe-remember-loging' => 'Pengingat keamanan umum: Hanya masuk log ke situs web sewaktu bilah alamat Anda menampilkan alamat situs tersebut.',
+       'fogg-select_file' => 'Pilih berkas',
+       'fogg-select_new_file' => 'Pilih berkas baru',
+       'fogg-select_url' => 'Pilih URL',
+       'fogg-save_local_file' => 'Simpan Ogg',
+       'fogg-check_for_firefogg' => 'Mengecek Firefogg...',
+       'fogg-installed' => 'Firefogg telah terinstal',
+       'fogg-for_improved_uploads' => 'Untuk pengunggahan canggih:',
+       'fogg-please_install' => '<a href="$1">Instal Firefogg.</a> Lebih lanjut <a href="http://commons.wikimedia.org/wiki/Commons:Firefogg">tentang Firefogg.</a>',
+       'fogg-use_latest_firefox' => 'Silakan instal dulu <a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=firefogg">Firefox 3.5</a> (atau lebih baru). <i>Kemudian kunjungi kembali halaman ini untuk menginstal ekstensi <b>Firefogg</b>.</i>',
+       'fogg-passthrough_mode' => 'Berkas yang dipilih sudah berformat Ogg atau bukan suatu berkas video',
+       'fogg-transcoding' => 'Mengkodekan video ke Ogg...',
+       'fogg-encoding-done' => 'Pengkodean selesai',
+       'fogg-badtoken' => 'Token tidak valid',
+       'fogg-preview' => 'Pratilik video',
+       'fogg-hidepreview' => 'Sembunyikan pratilik',
+       'mwe-imported_from' => '$1 diimpor dari [$2 $3]. Lihat [$4 halaman sumber asli] untuk informasi lebih lanjut.',
+       'mwe-stream_title' => '$1 $2 sampai  $3',
+       'fogg-help-sticky' => 'Bantuan (klik untuk tetap ditampilkan)',
+       'fogg-cg-preset' => 'Setelan awal: <strong>$1</strong>',
+       'fogg-cg-quality' => 'Kontrol kualitas dan resolusi dasar',
+       'fogg-cg-meta' => 'Metadata untuk klip',
+       'fogg-cg-range' => 'Rentang pengkodean',
+       'fogg-cg-advVideo' => 'Kontrol pengkodean video lanjut',
+       'fogg-cg-advAudio' => 'Kontrol pengkodean audio lanjut',
+       'fogg-preset-custom' => 'Pengaturan buatan',
+       'fogg-webvideo-desc' => 'Video web Theora, Vorbis 400 kbit/s dan lebar maksimum 400px',
+       'fogg-savebandwidth-desc' => 'Theora lebarpita rendah, Vorbis 164 kbit/s dan lebar maksimum 200px',
+       'fogg-highquality-desc' => 'Theora kualitas tinggi, Vorbis lebar maksimum 1080px',
+       'fogg-videoQuality-title' => 'Kualitas video',
+       'fogg-videoQuality-help' => 'Digunakan untuk mengatur <i>kualitas visual</i> video terkodekan (tidak digunakan jika Anda menetapkan kecepatan bit dalam kontrol lanjut di bawah ini).',
+       'fogg-starttime-title' => 'Detik awal',
+       'fogg-starttime-help' => 'Hanya mengkodekan dari waktu dalam detik',
+       'fogg-endtime-title' => 'Detik akhir',
+       'fogg-endtime-help' => 'Hanya mengkodekan sampai waktu dalam detik',
+       'fogg-audioQuality-title' => 'Kualitas audio',
+       'fogg-audioQuality-help' => 'Digunakan untuk mengatur <i>kualitas akustik</i> audio terkodekan (tidak digunakan jika Anda mengatur kecepatan bit di kontrol lanjut di bawah ini).',
+       'fogg-videoCodec-title' => 'Codec video',
+       'fogg-videoCodec-help' => 'Digunakan untuk memilih codec klip video. Saat ini hanya mendukung Theora. Lebih lanjut tentang <a target="_new" href="http://en.wikipedia.org/wiki/Theora">codec Theora</a>.',
+       'fogg-audioCodec-title' => 'Codec audio',
+       'fogg-audioCodec-help' => 'Digunakan untuk mengatur codec klip audio. Saat ini hanya mendukung Vorbis. Lebih lanjut tentang <a target="_new" href="http://en.wikipedia.org/wiki/Vorbis">codec Vorbis</a>.',
+       'fogg-width-title' => 'Lebar video',
+       'fogg-width-help' => 'Ubah ukuran ke lebar yang diberikan.',
+       'fogg-height-title' => 'Tinggi video',
+       'fogg-height-help' => 'Ubah ukuran ke tinggi yang diberikan.',
+       'fogg-videoBitrate-title' => 'Kecepatan bit video',
+       'fogg-videoBitrate-help' => 'Kecepatan bit video mengatur kecepatan bit pengkodean untuk video dalam (kb/s)',
+       'fogg-twopass-title' => 'Pengkodean dua laluan',
+       'fogg-twopass-help' => 'Pengkodean dua laluan memungkinkan kualitas yang lebih konstan dengan membuat dua laluan atas berkas video',
+       'fogg-framerate-title' => 'Kecepatan bingkai',
+       'fogg-framerate-help' => 'Kecepatan bingkai video. Lebih lanjut tentang <a target="_new" href="http://en.wikipedia.org/wiki/Frame_rate">kecepatan bingkai</a>.',
+       'fogg-aspect-title' => 'Rasio aspek',
+       'fogg-aspect-help' => 'Rasio aspek video dapat berupa perbandingan 4:3 atau 16:9. Lebih lanjut tentang <a target="_new" href="http://en.wikipedia.org/wiki/Aspect_ratio_%28image%29">rasio aspek</a>.',
+       'fogg-keyframeInterval-title' => 'Interval bingkai utama',
+       'fogg-keyframeInterval-help' => 'Interval bingkai utama dalam bingkai. Catatan: Sebagian besar codec memaksa bingkai utama jika perbedaan antar bingkai lebih besar daripada ukuran pengkodean bingkai utama. Lebih lanjut tentang <a href="http://en.wikipedia.org/wiki/I-frame">bingkai utama</a>.',
+       'fogg-denoise-title' => 'Filter awaderau',
+       'fogg-denoise-help' => 'Menghilangkan derau video masukan. Lebih lanjut tentang <a href="http://en.wikipedia.org/wiki/Video_denoising">awaderau</a>.',
+       'fogg-novideo-title' => 'Tidak ada video',
+       'fogg-novideo-help' => 'menonaktifkan video pada keluaran',
+       'fogg-audioBitrate-title' => 'Kecepatan bit audio',
+       'fogg-samplerate-title' => 'Kecepatan pencuplikan audio',
+       'fogg-samplerate-help' => 'mengatur kecepatan pencuplikan keluaran (dalam Hz).',
+       'fogg-noaudio-title' => 'Tidak ada audio',
+       'fogg-noaudio-help' => 'menonaktifkan audio dalam keluaran',
+       'fogg-title-title' => 'Judul',
+       'fogg-title-help' => 'Suatu judul untuk klip Anda',
+       'fogg-artist-title' => 'Nama pembuat',
+       'fogg-artist-help' => 'Pembuat klip ini',
+       'fogg-date-title' => 'Tanggal',
+       'fogg-date-help' => 'Tanggal pembuatan atau rilis potongan film ini',
+       'fogg-location-title' => 'Lokasi',
+       'fogg-location-help' => 'Lokasi potongan film',
+       'fogg-organization-title' => 'Organisasi',
+       'fogg-organization-help' => 'Nama organisasi (studio)',
+       'fogg-copyright-title' => 'Hak cipta',
+       'fogg-copyright-help' => 'Hak cipta klip',
+       'fogg-license-title' => 'Lisensi',
+       'fogg-license-help' => 'Lisensi klip (lebih diutamakan suatu URL Creative Commons).',
+       'fogg-contact-title' => 'Kontak',
+       'fogg-contact-help' => 'Pranala kontak',
+       'mwe-add_media_wizard' => 'Pemandu penambahan media',
+       'mwe-media_search' => 'Cari media',
+       'rsd_box_layout' => 'Atak kotak',
+       'rsd_list_layout' => 'Atak daftar',
+       'rsd_results_desc' => 'Hasil $1 sampai $2',
+       'rsd_results_desc_total' => 'Hasil $1 sampai $2 dari $3',
+       'rsd_results_next' => 'selanjutnya',
+       'rsd_results_prev' => 'sebelumnya',
+       'rsd_no_results' => 'Tidak ada hasil pencarian untuk <b>$1</b>',
+       'mwe-upload_tab' => 'Unggah',
+       'rsd_layout' => 'Tampilan:',
+       'rsd_resource_edit' => 'Sunting Sumber: $1',
+       'mwe-resource_description_page' => 'Halaman keterangan sumber',
+       'mwe-link' => 'Pranala',
+       'rsd_local_resource_title' => 'Judul sumber lokal',
+       'rsd_do_insert' => 'Sisipkan',
+       'mwe-cc_by_title' => 'Atribut',
+       'mwe-cc_nc_title' => 'Nonkomersial',
+       'mwe-cc_nd_title' => 'Tanpa Karya Turunan',
+       'mwe-cc_sa_title' => 'Berbagi Serupa',
+       'mwe-cc_pd_title' => 'Domain Umum',
+       'mwe-unknown_license' => 'Lisensi tidak diketahui',
+       'mwe-no_import_by_url' => 'Pengguna atau wiki ini <b>tidak dapat</b> mengimpor aset dari URL luar.<p>Apakah Anda perlu masuk log?</p><p>Apakah izin upload_by_url telah diberikan untuk Anda?<br />Apakah <a href="http://www.mediawiki.org/wiki/Manual:$wgAllowCopyUploads">$wgAllowCopyUploads</a> telah diaktifkan pada wiki ini?</p>',
+       'mwe-results_from' => 'Hasil dari <a href="$1" target="_new" >$2</a>',
+       'mwe-missing_desc_see_source' => 'Aset ini tidak memiliki deskripsi. Silakan lihat [$1 sumber aslinya] dan bantulah untuk mendeskripsikannya.',
+       'rsd_config_error' => 'Kesalahan konfigurasi pemandu penambahan media: $1',
+       'mwe-your_recent_uploads' => 'Unggahan terbaru Anda ke $1',
+       'mwe-upload_a_file' => 'Unggah berkas baru ke $1',
+       'mwe-resource_page_desc' => 'Keterangan sumber halaman',
+       'mwe-edit_resource_desc' => 'Sunting teks wiki keterangan sumber:',
+       'mwe-local_resource_title' => 'Judul Sumber lokal :',
+       'mwe-watch_this_page' => 'Pantau halaman ini',
+       'mwe-do_import_resource' => 'Impor sumber',
+       'mwe-update_preview' => 'Perbaharui pratayang',
+       'mwe-cancel_import' => 'Batalkan impor',
+       'mwe-importing_asset' => 'Mengimpor aset',
+       'mwe-preview_insert_resource' => 'Pratayang pemasukan sumber: $1',
+       'mwe-checking-resource' => 'Mengecek sumber',
+       'mwe-resource-needs-import' => 'Sumber $1 perlu diimpor ke $2',
+       'mwe-ftype-svg' => 'Berkas vektor SVG',
+       'mwe-ftype-jpg' => 'Berkas gambar JPEG',
+       'mwe-ftype-png' => 'Berkas gambar PNG',
+       'mwe-ftype-oga' => 'Berkas audio Ogg',
+       'mwe-ftype-ogg' => 'Berkas video Ogg',
+       'mwe-ftype-unk' => 'Format berkas tak dikenal',
+       'rsd-wiki_commons-title' => 'Wikimedia Commons',
+       'rsd-wiki_commons' => 'Wikimedia Commons, suatu arsip media pendidikan berlisensi bebas (gambar, suara, dan klip video)',
+       'rsd-this_wiki-title' => 'Wiki ini',
+       'rsd-this_wiki-desc' => 'Instalasi wiki lokal',
+       'rsd-archive_org-desc' => 'Internet Archive, perpustakaan digital artefak budaya',
+       'rsd-flickr-desc' => 'Flickr.com, situs berbagi gambar daring',
+       'rsd-metavid-desc' => 'Metavid.org, arsip komunitas dari prosiding DPR dan Senat AS',
+       'mwe-select_file' => 'Pilih berkas',
+       'mwe-more_licence_options' => 'Untuk informasi pilihan lisensi lebih lanjut, lihat <a href="$1">halaman pengunggahan normal</a>',
+       'mwe-select_ownwork' => 'Saya mengunggah sepenuhnya karya saya sendiri, dan melisensikannya di bawah:',
+       'mwe-licence_cc-by-sa' => 'Creative Commons Berbagi Bersama (3.0)',
+       'mwe-upload' => 'Mengunggah berkas',
+       'mwe-destfilename' => 'Nama berkas tujuan:',
+       'mwe-summary' => 'Ringkasan',
+       'mwe-error_not_loggedin' => 'Anda tampaknya tidak masuk log atau tidak memiliki hak mengunggah.',
+       'mwe-watch-this-file' => 'Tonton berkas ini',
+       'mwe-ignore-any-warnings' => 'Abaikan semua peringatan',
+       'mwe-upload-transcode-in-progress' => 'Transkode dan pengunggahan dalam proses (jangan menutup jendela ini)',
+       'mwe-upload-in-progress' => 'Pengunggahan sedang berlangsung (jangan menutup jendela ini)',
+       'mwe-upload-transcoded-status' => 'Ditraskodekan',
+       'mwe-uploaded-status' => 'Diunggah',
+       'mwe-upload-stats-fileprogress' => '$1 dari $2',
+       'mwe-upload_completed' => 'Pengunggahan selesai',
+       'mwe-upload_done' => '<a href="$1">Unggahan Anda <i>harus dapat</i> diakses.</a>',
+       'mwe-upload-unknown-size' => 'Ukuran tidak diketahui',
+       'mwe-cancel-confim' => 'Apakah Anda yakin ingin membatalkan?',
+       'mwe-successfulupload' => 'Unggah berhasil',
+       'mwe-uploaderror' => 'Unggah galat',
+       'mwe-uploadwarning' => 'Peringatan pengunggahan',
+       'mwe-unknown-error' => 'Kesalahan tak dikenal:',
+       'mwe-return-to-form' => 'Kembali ke formulir',
+       'mwe-file-exists-duplicate' => 'Berkas ini adalah duplikat dari berkas berikut:',
+       'mwe-fileexists' => 'Suatu berkas dengan nama tersebut telah ada. Tolong cek <b><tt>$1</tt></b> jika Anda tidak yakin untuk mengubahnya.',
+       'mwe-fileexists-thumb' => '<center><b>Berkas yang sudah ada</b></center>',
+       'mwe-ignorewarning' => 'Abaikan peringatan dan simpan saja berkas',
+       'mwe-file-thumbnail-no' => 'Nama berkas diawali dengan <tt><b>$1</b></tt>',
+       'mwe-go-to-resource' => 'Lihat halaman sumber',
+       'mwe-upload-misc-error' => 'Kesalahan pengunggahan tak dikenal',
+       'mwe-wgfogg_warning_bad_extension' => 'Anda telah memilih berkas dengan ekstensi yang tak didukung (<a href="http://commons.wikimedia.org/wiki/Commons:Firefogg#Supported_File_Types">informasi lebih lanjut</a>).',
+       'mwe-upload-multi' => 'Unggah {{PLURAL:$1|berkas|berkas}}',
+       'mwe-review-upload' => 'Tinjau {{PLURAL:$1|Unggahan|Unggahan}} Berkas',
+       'mwe-credit-title' => 'Judul: $1',
+       'mwe-loading_plugin' => 'memuat pengaya ...',
+       'mwe-select_playback' => 'Atur preferensi pemutar',
+       'mwe-link_back' => 'Pranala balik',
+       'mwe-error_swap_vid' => 'Kesalahan: mv_embed tak dapat menukar tag video untuk antarmuka mv_embed',
+       'mwe-add_to_end_of_sequence' => 'Tambahkan ke akhir rangkaian',
+       'mwe-missing_video_stream' => 'Berkas video untuk aliran tidak ditemukan',
+       'mwe-play_clip' => 'Mainkan klip',
+       'mwe-pause_clip' => 'Jeda klip',
+       'mwe-volume_control' => 'Kontrol volume',
+       'mwe-player_options' => 'Pilihan pemutar',
+       'mwe-closed_captions' => 'Teks video',
+       'mwe-player_fullscreen' => 'Layar penuh',
+       'mwe-next_clip_msg' => 'Putar klip berikut',
+       'mwe-prev_clip_msg' => 'Putar klip sebelumnya',
+       'mwe-current_clip_msg' => 'Lanjutkan pemutaran klip ini',
+       'mwe-seek_to' => 'Cari $1',
+       'mwe-paused' => 'jeda',
+       'mwe-download_segment' => 'Unduh pilihan:',
+       'mwe-download_full' => 'Unduh berkas video lengkap:',
+       'mwe-download_right_click' => 'Untuk mengunduh, klik kanan dan pilih <i>Simpan tautan sebagai...</i>',
+       'mwe-download_clip' => 'Unduh video',
+       'mwe-download_text' => 'Unduh teks (xml <a style="color:white" title="CMML" href="http://wiki.xiph.org/index.php/CMML">CMML</a>):',
+       'mwe-download' => 'Unduh',
+       'mwe-share' => 'Bagikan',
+       'mwe-credits' => 'Kredit',
+       'mwe-clip_linkback' => 'Halaman sumber klip',
+       'mwe-chose_player' => 'Pilih pemutar video',
+       'mwe-share_this_video' => 'Bagikan video ini',
+       'mwe-video_credits' => 'Kredit video',
+       'mwe-menu_btn' => 'Menu',
+       'mwe-close_btn' => 'Tutup',
+       'mwe-ogg-player-vlc-player' => 'Pemutar VLC',
+       'mwe-ogg-player-videoElement' => 'Video Ogg asli',
+       'mwe-ogg-player-oggPlugin' => 'Pengaya generik Ogg',
+       'mwe-ogg-player-quicktime-mozilla' => 'Pengaya QuickTime',
+       'mwe-ogg-player-quicktime-activex' => 'ActiveX QuickTime',
+       'mwe-ogg-player-cortado' => 'Java Cortado',
+       'mwe-ogg-player-flowplayer' => 'Flowplayer',
+       'mwe-ogg-player-kplayer' => 'Pemutar Kaltura',
+       'mwe-ogg-player-selected' => '(dipilih)',
+       'mwe-ogg-player-omtkplayer' => 'OMTK Flash Vorbis',
+       'mwe-generic_missing_plugin' => 'Peramban Anda tampaknya tidak mendukung tipe pemutar berikut: <b>$1</b><br />Kunjungi halaman <a href="http://commons.wikimedia.org/wiki/Commons:Media_help">Metode Pemutar</a> untuk mengunduh pemutar.<br />',
+       'mwe-for_best_experience' => 'Untuk pengalaman pemutaran video yang lebih baik kami menyarankan: <br /><b><a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=mwEmbed">Firefox 3.5</a>.</b>',
+       'mwe-do_not_warn_again' => 'Selesai untuk saat ini.',
+       'mwe-playerselect' => 'Pemutar',
+       'mwe-read_before_embed' => '<a href="http://mediawiki.org/wiki/Security_Notes_on_Remote_Embedding" target="_new">Baca ini</a> sebelum mengikutkan.',
+       'mwe-embed_site_or_blog' => 'Sertakan pada suatu halaman',
+       'mwe-related_videos' => 'Video yang berhubungan',
+       'mwe-seeking' => 'mencari',
+       'mwe-copy-code' => 'Salin kode',
+       'mwe-video-h264' => 'Video H.264',
+       'mwe-video-flv' => 'Video flash',
+       'mwe-video-ogg' => 'Video ogg',
+       'mwe-video-audio' => 'Audio ogg',
+);
+
+/** Ido (Ido)
+ * @author Malafaya
+ */
+$messages['io'] = array(
+       'fogg-title-title' => 'Titulo',
+       'fogg-date-title' => 'Dato',
+       'rsd-this_wiki-title' => 'Ca wiki',
+       'mwe-upload' => 'Adkargar arkivo',
+       'mwe-upload-stats-fileprogres' => '$1 ek $2',
+);
+
+/** Italian (Italiano)
+ * @author Darth Kule
+ * @author Gianfranco
+ */
+$messages['it'] = array(
+       'mwe-close' => 'chiudi',
+       'mwe-menu_options' => 'Opzioni',
+       'mwe-other_options' => 'Altre opzioni',
+       'mwe-contextmenu_opt' => 'Attiva i menu contestuali',
+       'mwe-cancel' => 'Annulla',
+       'mwe-setting-up-proxy' => 'Installazione del proxy in corso...',
+       'mwe-proxy-not-ready' => 'Il Proxy non è configurato',
+       'fogg-installed' => 'Firefogg è installato',
+       'fogg-preview' => 'Anteprima video',
+       'fogg-hidepreview' => 'Nascondi anteprima',
+       'fogg-preset-custom' => 'Impostazioni personalizzate',
+       'fogg-audioQuality-title' => 'Qualità audio',
+       'fogg-width-title' => 'Larghezza video',
+       'fogg-width-help' => 'Ridimensiona alla larghezza indicata.',
+       'fogg-height-title' => 'Altezza video',
+       'fogg-height-help' => "Ridimensiona all'altezza indicata.",
+       'fogg-title-title' => 'Titolo',
+       'fogg-license-title' => 'Licenza',
+       'mwe-cc_by_title' => 'Attribuzione',
+       'mwe-cc_sa_title' => 'Condividi allo stesso modo',
+       'mwe-cc_pd_title' => 'Pubblico Dominio',
+       'mwe-unknown_license' => 'Licenza sconosciuta',
+       'mwe-watch_this_page' => 'Segui questa pagina',
+       'mwe-ftype-unk' => 'Formato del file sconosciuto',
+       'mwe-upload-unknown-size' => 'Dimensione sconosciuta',
+       'mwe-file-exists-duplicate' => 'Questo file è un duplicato del seguente file:',
+       'mwe-player_fullscreen' => 'Schermo intero',
+       'mwe-close_btn' => 'Chiudi',
+);
+
+/** Japanese (日本語)
+ * @author Aotake
+ * @author Fryed-peach
+ * @author Hosiryuhosi
+ * @author McDutchie
+ * @author Whym
+ * @author 青子守歌
+ */
+$messages['ja'] = array(
+       'mwe-crop' => '画像をトリミング',
+       'mwe-apply_crop' => '画像にトリミングを適用',
+       'mwe-reset_crop' => 'トリミングを取り消す',
+       'mwe-insert_image_page' => 'ページ中に挿入',
+       'mwe-insert_into_sequence' => 'シーケンス中に挿入',
+       'mwe-preview_insert' => '挿入をプレビュー',
+       'mwe-cancel_image_insert' => '挿入を中止',
+       'mwe-sc_fileopts' => 'クリップの詳細を編集',
+       'mwe-sc_inoutpoints' => 'イン・アウトポイントを設定',
+       'mwe-sc_overlays' => 'オーバーレイ',
+       'mwe-sc_audio' => 'オーディオ・コントロール',
+       'mwe-sc_duration' => '時間',
+       'mwe-template_properties' => 'テンプレートの属性',
+       'mwe-custom_title' => '独自のタイトル',
+       'mwe-edit_properties' => 'プロパティを編集',
+       'mwe-other_properties' => 'その他のプロパティ',
+       'mwe-resource_page' => 'リソースページ:',
+       'mwe-set_in_out_points' => 'イン・アウトポイントを設定',
+       'mwe-start_time' => '開始時間',
+       'mwe-end_time' => '終了時間',
+       'mwe-preview_inout' => 'イン・アウトポイントをプレビュー',
+       'mwe-edit-tools' => '編集ツール',
+       'mwe-inline-description' => 'キャプション',
+       'mwe-edit-video-tools' => '動画編集ツール:',
+       'mwe-duration' => '時間:',
+       'mwe-upload-subs-file' => '字幕をアップロード',
+       'mwe-add-subs-file-title' => 'アップロードする字幕を選択',
+       'mwe-error-only-srt' => 'アップロードできるのは srt ファイルのみです。',
+       'mwe-watch-video' => '動画を視聴',
+       'mwe-select-other-language' => '他の言語を選択',
+       'mwe-saving' => '保存中…',
+       'mwe-select_transcript_set' => '字幕を選択',
+       'mwe-auto_scroll' => '自動スクロール',
+       'mwe-close' => '閉じる',
+       'mwe-improve_transcript' => '改善',
+       'mwe-no_text_tracks_found' => 'テキスト用のトラックがありません',
+       'mwe-add-edit-subs' => '字幕を追加・編集',
+       'mwe-transition_in' => 'トランジション・イン',
+       'mwe-transition_out' => 'トランジション・アウト',
+       'mwe-effects' => 'エフェクト棚',
+       'mwe-remove_transition' => 'トランジションを除去',
+       'mwe-edit_transin' => 'クリップのトランジション・インを編集',
+       'mwe-edit_transout' => 'クリップのトランジション・アウトを編集',
+       'mwe-add-transition' => 'トランジションを追加',
+       'mwe-menu_clipedit' => 'メディアを編集',
+       'mwe-menu_transition' => 'トランジションとエフェクト',
+       'mwe-menu_cliplib' => 'メディアを追加',
+       'mwe-menu_resource_overview' => 'リソース概観',
+       'mwe-menu_options' => 'オプション',
+       'mwe-loading_timeline' => 'タイムラインを読み込み中 …',
+       'mwe-loading_user_rights' => '利用者権限を読み込み中 …',
+       'mwe-no_edit_permissions' => 'あなたはこのシーケンスに変更を加える許可がありません',
+       'mwe-edit_clip' => 'クリップを編集',
+       'mwe-edit_save' => 'シーケンスの変更を保存',
+       'mwe-saving_wait' => '保存処理中 (お待ちください)',
+       'mwe-save_done' => '保存完了',
+       'mwe-edit_cancel' => 'シーケンスの編集を中止',
+       'mwe-edit_cancel_confirm' => '本当に編集を中止しますか?変更は失われます。',
+       'mwe-zoom_in' => '拡大',
+       'mwe-zoom_out' => '縮小',
+       'mwe-cut_clip' => 'クリップを切り抜く',
+       'mwe-expand_track' => 'トラックを展開',
+       'mwe-collapse_track' => 'トラックを折り畳む',
+       'mwe-play_from_position' => '再生開始位置から再生',
+       'mwe-pixle2sec' => 'ピクセルから秒へ',
+       'mwe-rmclip' => 'クリップを削除',
+       'mwe-clip_in' => '添付する',
+       'mwe-clip_out' => '除去する',
+       'mwe-no_selected_resource' => '<h3>素材が選択されていません</h3>編集を行うにはクリップを選択してください。',
+       'mwe-error_edit_multiple' => '<h3>複数の素材が選択されています</h3> 編集するにはクリップを1つだけ選択してください。',
+       'mwe-editor_options' => '編集オプション',
+       'mwe-editor_mode' => '編集モード',
+       'mwe-simple_editor_desc' => '単純なエディター (iMovie 風)',
+       'mwe-advanced_editor_desc' => '高度なエディター (Final Cut 風)',
+       'mwe-other_options' => '他のオプション',
+       'mwe-contextmenu_opt' => 'コンテキストメニューを有効化',
+       'mwe-sequencer_credit_line' => '本機能は<a href="http://kaltura.com">Kaltura, Inc.</a> が <a href="http://wikimediafoundation.org/wiki/Home">ウィキメディア財団</a>の協力のもと開発しました (<a href="#">詳細情報</a>)。',
+       'mwe-loading_txt' => '読み込み中 …',
+       'mwe-error_load_lib' => 'エラー:JavaScript $1 は参照不能か、$2 を定義していません。',
+       'mwe-loading-add-media-wiz' => '追加メディアウィザードを読み込み中',
+       'mwe-apiproxy-setup' => 'API プロキシーをセットアップ中',
+       'mwe-load-drag-item' => 'ドラッグされた項目を読み込み中',
+       'mwe-ok' => 'OK',
+       'mwe-cancel' => '中止',
+       'mwe-setting-up-proxy' => 'プロキシをセットアップ中…',
+       'mwe-re-try' => 'API 要求を再試行',
+       'mwe-re-trying' => 'API 要求を再試行中…',
+       'mwe-proxy-not-ready' => 'プロキシが設定されていません',
+       'mwe-please-login' => 'あなたが $2 へ<a target="_new" href="$1">ログイン</a>していないか、mwEmbed が有効化されていません。この問題を解決し、それから要求を再試行してください。',
+       'mwe-remember-loging' => '一般的に、セキュリティーのためにはアドレスバーにそのサイトのアドレスが表示されるウェブサイトにのみログインしてください。',
+       'fogg-select_file' => 'ファイルを選択',
+       'fogg-select_new_file' => '別のファイルを選択',
+       'fogg-select_url' => 'URLを選択',
+       'fogg-save_local_file' => 'Ogg を保存',
+       'fogg-check_for_firefogg' => 'Firefogg を確認しています ...',
+       'fogg-installed' => 'Firefogg はインストールされています',
+       'fogg-for_improved_uploads' => 'アップロードをより便利にするには:',
+       'fogg-please_install' => '<a href="$1">Firefogg をインストール</a>。<a href="http://commons.wikimedia.org/wiki/Commons:Firefogg">Firefogg について</a>。',
+       'fogg-use_latest_firefox' => 'はじめに <a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=firefogg">Firefox 3.5 (以降)</a>をインストールしてください。<i>次にこのページを再読み込みし、 <b>Firefogg</b> 拡張機能をインストールしてください。</i>',
+       'fogg-passthrough_mode' => '選択したファイルはすでに Ogg 形式であるか、動画ファイルではありません',
+       'fogg-transcoding' => '動画を Ogg に形式変換',
+       'fogg-encoding-done' => '形式変換終了',
+       'fogg-badtoken' => 'トークンが無効です',
+       'fogg-preview' => 'ビデオをプレビュー',
+       'fogg-hidepreview' => 'プレビューを隠す',
+       'mwe-imported_from' => '$1 は [$2 $3] からインポートされました。詳しくはもともとの[$4 出所ページ]を参照してください。',
+       'mwe-stream_title' => '$1 $2 から $3',
+       'fogg-help-sticky' => 'ヘルプ (開いたままにするにはクリック)',
+       'fogg-cg-preset' => 'プリセット: <strong>$1</strong>',
+       'fogg-cg-quality' => '基本品質と解像度コントロール',
+       'fogg-cg-meta' => 'クリップのメタデータ',
+       'fogg-cg-range' => 'エンコーディング範囲',
+       'fogg-cg-advVideo' => '高度な動画変換コントロール',
+       'fogg-cg-advAudio' => '高度な音声変換コントロール',
+       'fogg-preset-custom' => 'カスタム設定',
+       'fogg-webvideo-desc' => 'ウェブビデオ Theora、Vorbis 400 kbps および 最大幅 400px',
+       'fogg-savebandwidth-desc' => '低帯域幅 Theora、Vorbis 164 kbps および 最大幅 200px',
+       'fogg-highquality-desc' => '高品質 Theora、Vorbis 最大幅 1080px',
+       'fogg-videoQuality-title' => '動画品質',
+       'fogg-videoQuality-help' => 'エンコードされた動画の<i>視覚品質</i>を設定するために使われます (以下の高度設定でビットレートを設定した場合は使われません)。',
+       'fogg-starttime-title' => '開始秒',
+       'fogg-starttime-help' => 'この時点(単位:秒)からのみエンコードする',
+       'fogg-endtime-title' => '終了秒',
+       'fogg-endtime-help' => 'この時点(単位:秒)までのみエンコードする',
+       'fogg-audioQuality-title' => 'オーディオ品質',
+       'fogg-audioQuality-help' => 'エンコードされた音声・音楽の<i>音響品質</i>を設定するために使用されます (以下の高度設定でビットレートを設定した場合は使われません)。',
+       'fogg-videoCodec-title' => '動画コーデック',
+       'fogg-videoCodec-help' => 'クリップの動画コーデックを選ぶために使われます。現時点では Theora にのみ対応しています。詳しくは <a target="_new" href="http://ja.wikipedia.org/wiki/Theora">Theora コーデック</a>を参照。',
+       'fogg-audioCodec-title' => 'オーディオコーデック',
+       'fogg-audioCodec-help' => 'クリップのオーディオコーデックを設定するために使われます。現時点では Vorbis にのみ対応しています。詳しくは <a target="_new" href="http://ja.wikipedia.org/wiki/Vorbis">Vorbis コーデック</a>を参照。',
+       'fogg-width-title' => '動画の横幅',
+       'fogg-width-help' => '指定した横幅に変更する。',
+       'fogg-height-title' => '動画の縦幅',
+       'fogg-height-help' => '指定した縦幅に変更する。',
+       'fogg-videoBitrate-title' => '動画のビットレート',
+       'fogg-videoBitrate-help' => '動画のビットレートは動画の符号化ビットレートをキロビット毎秒の単位で設定します',
+       'fogg-twopass-title' => '2パスエンコード',
+       'fogg-twopass-help' => '2パスエンコードでは、動画ファイルに対してパスを2つ経ることでより高い品質を得ることができます',
+       'fogg-framerate-title' => 'フレームレート',
+       'fogg-framerate-help' => '動画のフレームレート。詳しくは<a target="_new" href="http://ja.wikipedia.org/wiki/%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AC%E3%83%BC%E3%83%88">フレームレート</a>を参照。',
+       'fogg-aspect-title' => 'アスペクト比',
+       'fogg-aspect-help' => '動画のアスペクト比は 4:3 あるいは 16:9 に設定できます。詳しくは<a target="_new" href="http://ja.wikipedia.org/wiki/%E7%94%BB%E9%9D%A2%E3%82%A2%E3%82%B9%E3%83%9A%E3%82%AF%E3%83%88%E6%AF%94">アスペクト比</a>を参照。',
+       'fogg-keyframeInterval-title' => 'キーフレーム間隔',
+       'fogg-keyframeInterval-help' => 'フレーム間のキーフレーム間隔。注意:ほとんどのコーデックではフレーム間の差異がキーフレームエンコードサイズより大きい場合にキーフレームが強要されます。詳しくは<a href="http://en.wikipedia.org/wiki/I-frame">キーフレーム (英語)</a> を参照。',
+       'fogg-denoise-title' => 'ノイズ除去フィルター',
+       'fogg-denoise-help' => '入力の動画からノイズを除去する。詳しくは<a href="http://en.wikipedia.org/wiki/Video_denoising">動画ノイズ除去</a> (英語) を参照。',
+       'fogg-novideo-title' => '動画なし',
+       'fogg-novideo-help' => '出力中の動画を無効化する',
+       'fogg-audioBitrate-title' => 'オーディオビットレート',
+       'fogg-samplerate-title' => 'オーディオのサンプリングレート',
+       'fogg-samplerate-help' => '出力のサンプリングレートを設定します (単位:ヘルツ)。',
+       'fogg-noaudio-title' => 'オーディオなし',
+       'fogg-noaudio-help' => '出力中の音声を無効化する',
+       'fogg-title-title' => 'タイトル',
+       'fogg-title-help' => 'クリップのタイトル',
+       'fogg-artist-title' => '作者名',
+       'fogg-artist-help' => 'このクリップの作者',
+       'fogg-date-title' => '日付',
+       'fogg-date-help' => 'その映像が作成もしくは公表された日付',
+       'fogg-location-title' => '撮影地',
+       'fogg-location-help' => '映像の撮影地',
+       'fogg-organization-title' => '組織',
+       'fogg-organization-help' => '組織(製作所)の名前',
+       'fogg-copyright-title' => '著作権',
+       'fogg-copyright-help' => 'クリップの著作権',
+       'fogg-license-title' => 'ライセンス',
+       'fogg-license-help' => 'クリップのライセンス (できればクリエイティブ・コモンズの URL)。',
+       'fogg-contact-title' => '連絡先',
+       'fogg-contact-help' => '連絡先のリンク',
+       'mwe-add_media_wizard' => 'メディア追加ウィザード',
+       'mwe-media_search' => 'メディア検索',
+       'rsd_box_layout' => 'ボックス・レイアウト',
+       'rsd_list_layout' => 'リスト・レイアウト',
+       'rsd_results_desc' => '結果 $1から$2',
+       'rsd_results_desc_total' => '結果$3件中$1件目から$2件目',
+       'rsd_results_next' => '次',
+       'rsd_results_prev' => '前',
+       'rsd_no_results' => '<b>$1</b> に対する結果はありませんでした',
+       'mwe-upload_tab' => 'アップロード',
+       'rsd_layout' => 'レイアウト:',
+       'rsd_resource_edit' => 'リソースを編集: $1',
+       'mwe-resource_description_page' => 'リソース解説ページ',
+       'mwe-link' => 'リンク',
+       'rsd_local_resource_title' => 'ローカルのリソース名',
+       'rsd_do_insert' => '挿入実行',
+       'mwe-cc_title' => 'クリエイティブ・コモンズ',
+       'mwe-cc_by_title' => '帰属',
+       'mwe-cc_nc_title' => '非営利',
+       'mwe-cc_nd_title' => '派生作品禁止',
+       'mwe-cc_sa_title' => '継承',
+       'mwe-cc_pd_title' => 'パブリック・ドメイン',
+       'mwe-unknown_license' => 'ライセンス不明',
+       'mwe-no_import_by_url' => 'この利用者またはウィキは遠隔 URL からデータをインポートすることが<b>できません</b>。</p><p>ログインする必要がありますか?</p><p>あなたに upload_by_url 権限が設定済みですか?<br />ウィキで <a href="http://www.mediawiki.org/wiki/Manual:$wgAllowCopyUploads">$wgAllowCopyUploads</a> が有効となっていますか?</p>',
+       'mwe-results_from' => '<a href="$1" target="_new" >$2</a>の結果',
+       'mwe-missing_desc_see_source' => 'この素材には説明がありません。[$1 もともとの出所]を確認して解説を追加してください。',
+       'rsd_config_error' => 'メディア追加ウィザードの設定エラー: $1',
+       'mwe-your_recent_uploads' => 'あなたの最近の $1 へのアップロード',
+       'mwe-upload_a_file' => '新しいファイルを $1 へアップロード',
+       'mwe-resource_page_desc' => '出典情報ページの解説:',
+       'mwe-edit_resource_desc' => 'アップロード元情報のウィキテキストを編集',
+       'mwe-local_resource_title' => 'ローカルのアップロード元ファイル名:',
+       'mwe-watch_this_page' => 'このページをウォッチする',
+       'mwe-do_import_resource' => 'リソースをインポート',
+       'mwe-update_preview' => 'プレビューを更新',
+       'mwe-cancel_import' => 'インポートを中止',
+       'mwe-importing_asset' => 'データをインポート中',
+       'mwe-preview_insert_resource' => 'アップロード元ファイルのプレビュー: $1',
+       'mwe-checking-resource' => 'リソースの点検中',
+       'mwe-resource-needs-import' => 'リソース $1 を $2 にインポートする必要があります',
+       'mwe-ftype-svg' => 'SVG ベクターファイル',
+       'mwe-ftype-jpg' => 'JPEG 画像ファイル',
+       'mwe-ftype-png' => 'PNG 画像ファイル',
+       'mwe-ftype-oga' => 'Ogg オーディオファイル',
+       'mwe-ftype-ogg' => 'Ogg 動画ファイル',
+       'mwe-ftype-unk' => '不明なファイル形式',
+       'rsd-wiki_commons-title' => 'ウィキメディア・コモンズ',
+       'rsd-wiki_commons' => 'ウィキメディア・コモンズはフリーなライセンスの下にある教育用のメディアコンテンツ(画像、音声、および動画クリップ)のアーカイブです',
+       'rsd-this_wiki-title' => 'このウィキ',
+       'rsd-this_wiki-desc' => 'ローカルウィキへのインストール',
+       'rsd-archive_org-desc' => 'インターネット・アーカイブは文化遺産のデジタルライブラリーです',
+       'rsd-flickr-desc' => 'Flickr.com はオンライン写真共有サイトです',
+       'rsd-metavid-desc' => 'Metavid.org はアメリカ合衆国議会の議事録の共同アーカイブです',
+       'mwe-select_file' => 'ファイルを選択',
+       'mwe-more_licence_options' => 'その他のライセンスを選択したい場合は<a href="$1">通常のアップロード画面</a>をご利用ください。',
+       'mwe-select_ownwork' => '今からアップロードする作品は全部分が自作です。私は以下のライセンスのもと提供します:',
+       'mwe-licence_cc-by-sa' => 'クリエイティブ・コモンズ 継承 (3.0)',
+       'mwe-upload' => 'ファイルをアップロード',
+       'mwe-destfilename' => '掲載するファイル名:',
+       'mwe-summary' => '要約',
+       'mwe-error_not_loggedin' => 'あなたはログインしていないか、アップロード権限を保有していません。',
+       'mwe-watch-this-file' => 'このファイルをウォッチ',
+       'mwe-ignore-any-warnings' => '警告をすべて無視する',
+       'mwe-upload-transcode-in-progress' => 'トランスコードおよびアップロードの処理中 (このウィンドウを閉じないでください)',
+       'mwe-upload-in-progress' => 'アップロード処理中 (このウィンドウを閉じないでください)',
+       'mwe-upload-transcoded-status' => 'トランスコード済み',
+       'mwe-uploaded-status' => 'アップロード済み',
+       'mwe-upload-stats-fileprogress' => '$2中 $1',
+       'mwe-upload_completed' => 'アップロードは完了しました',
+       'mwe-upload_done' => '<a href="$1">あなたがアップロードしたファイルはアクセス可能になっている<i>はず</i>です</a>。',
+       'mwe-upload-unknown-size' => '不明なサイズ',
+       'mwe-cancel-confim' => '本当に中止しますか?',
+       'mwe-successfulupload' => 'アップロード成功',
+       'mwe-uploaderror' => 'アップロードエラー',
+       'mwe-uploadwarning' => 'アップロードの警告',
+       'mwe-unknown-error' => '不明なエラー:',
+       'mwe-return-to-form' => 'フォームに戻る',
+       'mwe-file-exists-duplicate' => 'このファイルは以下のファイルと重複しています:',
+       'mwe-fileexists' => '同名のファイルが既に存在しています。上書きしてよいかわからない場合は <b><tt>$1</tt></b> を確認してください。',
+       'mwe-fileexists-thumb' => '<center><b>既存のファイル</b></center>',
+       'mwe-ignorewarning' => '警告を無視してファイルを保存する',
+       'mwe-file-thumbnail-no' => 'ファイル名が<b><tt>$1</tt></b>から始まるもの',
+       'mwe-go-to-resource' => '出典情報ページへ行く',
+       'mwe-upload-misc-error' => '不明なアップロードエラー',
+       'mwe-wgfogg_warning_bad_extension' => '選択したファイルはサポートされていない拡張子を持っています(<a href="http://commons.wikimedia.org/wiki/Commons:Firefogg#Supported_File_Types">詳細情報</a>)。',
+       'mwe-upload-multi' => '{{PLURAL:$1|ファイル}}をアップロード',
+       'mwe-review-upload' => 'ファイルの{{PLURAL:$1|アップロード}}を精査',
+       'mwe-credit-title' => 'タイトル: $1',
+       'mwe-loading_plugin' => 'プラグインを読み込み中 ...',
+       'mwe-select_playback' => '再生環境を設定',
+       'mwe-link_back' => 'トラックバック',
+       'mwe-error_swap_vid' => 'エラー: mv_embed 形式にあった動画タグに置換できませんでした。',
+       'mwe-add_to_end_of_sequence' => 'シーケンスの終わりに追加',
+       'mwe-missing_video_stream' => 'このストリームに必要な動画ファイルが見つかりません',
+       'mwe-play_clip' => 'クリップを再生',
+       'mwe-pause_clip' => 'クリップを一時停止',
+       'mwe-volume_control' => '音量調節',
+       'mwe-player_options' => 'プレイヤーの設定',
+       'mwe-closed_captions' => '字幕',
+       'mwe-player_fullscreen' => '全画面表示',
+       'mwe-next_clip_msg' => '次のクリップを再生',
+       'mwe-prev_clip_msg' => '前のクリップを再生',
+       'mwe-current_clip_msg' => 'このクリップの再生を続ける',
+       'mwe-seek_to' => '$1 へシーク',
+       'mwe-paused' => '一時停止中',
+       'mwe-download_segment' => 'ダウンロード方法を選択:',
+       'mwe-download_full' => '動画ファイル全体をダウンロード:',
+       'mwe-download_right_click' => 'ダウンロードするには、右クリックして<i>名前を付けてリンク先を保存</i>を選んでください',
+       'mwe-download_clip' => '動画をダウンロード',
+       'mwe-download_text' => 'テキストをダウンロード(<a style="color:white" title="cmml" href="http://wiki.xiph.org/index.php/CMML">CMML</a> xml):',
+       'mwe-download' => 'ダウンロード',
+       'mwe-share' => '共有',
+       'mwe-credits' => 'クレジット',
+       'mwe-clip_linkback' => 'クリップの情報ページ',
+       'mwe-chose_player' => 'ビデオの再生プレイヤーを選択',
+       'mwe-share_this_video' => 'この動画を共有する',
+       'mwe-video_credits' => '動画のクレジット',
+       'mwe-menu_btn' => 'メニュー',
+       'mwe-close_btn' => '閉じる',
+       'mwe-ogg-player-vlc-player' => 'VLC プレイヤー',
+       'mwe-ogg-player-videoElement' => 'ネイティブの Ogg ビデオ',
+       'mwe-ogg-player-oggPlugin' => '汎用の Ogg プラグイン',
+       'mwe-ogg-player-quicktime-mozilla' => 'QuickTimeプラグイン',
+       'mwe-ogg-player-quicktime-activex' => 'QuickTime ActiveX',
+       'mwe-ogg-player-cortado' => 'Java Cortado',
+       'mwe-ogg-player-flowplayer' => 'Flowplayer',
+       'mwe-ogg-player-kplayer' => 'Kaltura プレイヤー',
+       'mwe-ogg-player-selected' => '(選択済み)',
+       'mwe-ogg-player-omtkplayer' => 'OMTK Flash Vorbis',
+       'mwe-generic_missing_plugin' => 'ご使用中のブラウザは以下の再生形式をサポートしていないようです。<b>$1</b><br />プレイヤーをダウンロードするには <a href="http://commons.wikimedia.org/wiki/Commons:Media_help">再生方法の解説</a>ページをご覧ください。<br />',
+       'mwe-for_best_experience' => '動画再生品質をあげるためには <br /><b><a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=mwEmbed">Firefox 3.5</a></b>の使用をお勧めします。',
+       'mwe-do_not_warn_again' => '今のところは無視する',
+       'mwe-playerselect' => 'プレイヤー',
+       'mwe-read_before_embed' => '埋め込む前に<a href="http://mediawiki.org/wiki/Security_Notes_on_Remote_Embedding" target="_new">注意事項</a>をお読みください。',
+       'mwe-embed_site_or_blog' => 'ページに埋め込む',
+       'mwe-related_videos' => '関連する動画',
+       'mwe-seeking' => 'シーク中',
+       'mwe-copy-code' => 'コピーコード',
+       'mwe-video-h264' => 'H.264 ビデオ',
+       'mwe-video-flv' => 'Flash ビデオ',
+       'mwe-video-ogg' => 'Ogg ビデオ',
+       'mwe-video-audio' => 'Ogg オーディオ',
+);
+
+/** Georgian (ქართული)
+ * @author BRUTE
+ */
+$messages['ka'] = array(
+       'mwe-sc_audio' => 'აუდიო კონტროლი',
+       'mwe-sc_duration' => 'ხანგძლივობა',
+       'mwe-improve_transcript' => 'გაუმჯობესება',
+       'fogg-select_file' => 'ფაილის არჩევა',
+       'fogg-date-title' => 'თარიღი',
+       'rsd_results_desc' => 'შედეგები',
+       'rsd_results_next' => 'შემდეგი',
+       'rsd_results_prev' => 'წინა',
+       'mwe-upload_a_file' => 'ახალი ფაილის ატვირთვა',
+       'mwe-select_file' => 'ფაილის არჩევა',
+       'mwe-upload' => 'ფაილის დამატება',
+       'mwe-file-exists-duplicate' => 'ეს ფაილი არის დუბლიკატი შემდეგი ფაილისა:',
+);
+
+/** Korean (한국어)
+ * @author Kwj2772
+ */
+$messages['ko'] = array(
+       'mwe-crop' => '그림을 잘라내기',
+       'mwe-start_time' => '시작 시간',
+       'mwe-end_time' => '종료 시간',
+       'mwe-duration' => '시간:',
+       'mwe-watch-video' => '비디오 보기',
+       'mwe-select-other-language' => '다른 언어 선택하기',
+       'mwe-close' => '닫기',
+       'mwe-menu_options' => '설정',
+       'mwe-zoom_in' => '확대',
+       'mwe-zoom_out' => '축소',
+       'mwe-editor_options' => '에디터 설정',
+       'mwe-other_options' => '다른 설정',
+       'mwe-loading_txt' => '불러오는 중...',
+       'mwe-cancel' => '취소',
+       'fogg-installed' => 'Firefogg가 설치되었습니다',
+       'fogg-transcoding' => '비디오를 Ogg로 인코딩하는 중...',
+       'fogg-encoding-done' => '인코딩 완료',
+       'fogg-badtoken' => '토큰이 유효하지 않습니다.',
+       'mwe-cc_by_title' => '저작자표시',
+       'mwe-cc_nc_title' => '비영리',
+       'mwe-cc_nd_title' => '변경금지',
+       'mwe-cc_sa_title' => '동일조건변경허락',
+       'mwe-cc_pd_title' => '퍼블릭 도메인',
+       'mwe-watch_this_page' => '이 문서를 주시하기',
+       'mwe-ftype-svg' => 'SVG 벡터 그래픽 파일',
+       'mwe-ftype-jpg' => 'JPEG 이미지 파일',
+       'mwe-ftype-png' => 'PNG 이미지 파일',
+       'mwe-ftype-oga' => 'Ogg 소리 파일',
+       'mwe-ftype-ogg' => 'Ogg 비디오 파일',
+       'rsd-wiki_commons-title' => '위키미디어 공용',
+       'mwe-licence_cc-by-sa' => '크리에이티브 커먼즈 저작자표시-동일조건변경허락 (3.0)',
+       'mwe-upload' => '파일 올리기',
+       'mwe-destfilename' => '파일의 새 이름:',
+       'mwe-ignore-any-warnings' => '모든 경고를 무시하기',
+       'mwe-successfulupload' => '파일 올리기 성공',
+       'mwe-loading_plugin' => '플러그인을 불러오는 중...',
+       'mwe-player_options' => '플레이어 설정',
+       'mwe-player_fullscreen' => '전체 화면',
+       'mwe-download' => '다운로드',
+       'mwe-share' => '공유하기',
+       'mwe-menu_btn' => '메뉴',
+       'mwe-close_btn' => '닫기',
+       'mwe-ogg-player-selected' => '(선택됨)',
+       'mwe-for_best_experience' => '더 나은 비디오 재생을 위해서는<br /><b><a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=mwEmbed">파이어폭스 3.5</a></b>를 권장합니다.',
+       'mwe-copy-code' => '코드 복사하기',
+);
+
+/** Ripoarisch (Ripoarisch)
+ * @author McDutchie
+ * @author Purodha
+ */
+$messages['ksh'] = array(
+       'mwe-crop' => 'Beld beschnigge',
+       'mwe-apply_crop' => 'Lohß Jonn!',
+       'mwe-reset_crop' => 'Et Zerääschnigge ophävve',
+       'mwe-insert_image_page' => 'En en Sigg ennfööje',
+       'mwe-insert_into_sequence' => 'En de Afshpellleß ennfööje',
+       'mwe-preview_insert' => 'Vör_Aansich för et Ennfööje',
+       'mwe-cancel_image_insert' => 'Et Enfööje avbreche!',
+       'mwe-sc_fileopts' => 'Einzelheit vum Ußschnet ändere',
+       'mwe-sc_inoutpoints' => 'Der En- un Ußschteeschßpunk för et Afschpelle faßlääje',
+       'mwe-sc_overlays' => 'Övverbländunge',
+       'mwe-sc_audio' => 'Enshtällunge för der Tohn',
+       'mwe-sc_duration' => 'Duuer',
+       'mwe-template_properties' => 'Eijeschaffte vun en Schabloon',
+       'mwe-custom_title' => 'Ene aanjepaßte Tittel',
+       'mwe-edit_properties' => 'Eijeschaffte ändere',
+       'mwe-other_properties' => 'Ander Eijeschaffte',
+       'mwe-resource_page' => 'De Sigg dovun:',
+       'mwe-set_in_out_points' => 'En- un Ußschteeschßpunk faßlääje',
+       'mwe-start_time' => 'Aanfangszick',
+       'mwe-end_time' => 'Schloßzick',
+       'mwe-preview_inout' => 'Vör-Aanseesch vum En- un Ußschteeschßpunk',
+       'mwe-edit-tools' => 'Wärkzüsch för Belder de ändere',
+       'mwe-inline-description' => 'Legände',
+       'mwe-edit-video-tools' => 'Wärkzüsch för Viddejos ze beärbeide:',
+       'mwe-duration' => 'Duur:',
+       'mwe-upload-subs-file' => 'Ongertittele huhlaade',
+       'mwe-add-subs-file-title' => 'Ongertitel ußwähle för zom Huhlaade',
+       'mwe-error-only-srt' => 'Do kanns bloß <code lang="en">srt</code> Datteije huh laade.',
+       'mwe-watch-video' => 'Der Viddejo aalooere',
+       'mwe-select-other-language' => 'Donn en annder Shprooch ußwähle',
+       'mwe-saving' => 'Aam Speijschere{{int:ellipsis}}',
+       'mwe-select_transcript_set' => 'Ongertittelle ußsöhke',
+       'mwe-auto_scroll' => 'automattesch wigger_rolle',
+       'mwe-close' => 'zohmaache',
+       'mwe-improve_transcript' => 'Verbessere',
+       'mwe-no_text_tracks_found' => 'Kein Täx-Shpur jefonge',
+       'mwe-add-edit-subs' => 'Ongertittele dobei donn udder ändere',
+       'mwe-transition_in' => 'Övverjang en',
+       'mwe-transition_out' => 'Övverjang uß',
+       'mwe-effects' => 'Dä Pöngel met dä Effäkte',
+       'mwe-remove_transition' => 'Dä Övverjang fott nämme',
+       'mwe-edit_transin' => 'Donn dä Övverjang en dä Ußschnett eren bränge',
+       'mwe-edit_transout' => 'Donn dä Övverjang uß däm Ußschned eruß bränge',
+       'mwe-add-transition' => 'Donn ene Övverjang dobei',
+       'mwe-menu_clipedit' => 'Meedije Ändere',
+       'mwe-menu_transition' => 'Övverjäng un besönder Effäkte',
+       'mwe-menu_cliplib' => 'Alle Meedije',
+       'mwe-menu_resource_overview' => 'Övverseesch',
+       'mwe-menu_options' => 'Ußwahle',
+       'mwe-loading_timeline' => 'En Zick-Reih aam Laade&nbsp;…',
+       'mwe-loading_user_rights' => 'Metmaacher-Rääschte aam Laade&nbsp;…',
+       'mwe-no_edit_permissions' => 'Do häs nit dat Rääsch, Änderunge aan heh dä Afshpellleß afzeshpeishere',
+       'mwe-edit_clip' => 'Ußschnett ändere',
+       'mwe-edit_save' => 'Änderunge aan dä Afshpellleß afshpeishere',
+       'mwe-saving_wait' => 'Et Afsheijshere es noch em Jang, donn noch jät waade.',
+       'mwe-save_done' => 'Fäädesch afjeshpeishert',
+       'mwe-edit_cancel' => 'Et Ändere vun dä Afshpellleß afbreshe',
+       'mwe-edit_cancel_confirm' => 'Bes De sescher, dat De et Ändere afbräsche wells? All Ding Werrek beß jäz jeiht verschött!',
+       'mwe-zoom_in' => 'Eraan zoome',
+       'mwe-zoom_out' => 'Fott zoome',
+       'mwe-cut_clip' => 'Ußschnedde ußschnigge',
+       'mwe-expand_track' => 'Shpoor opklappe',
+       'mwe-collapse_track' => 'Shpoor ennklappe',
+       'mwe-play_from_position' => 'Vun dä Linnesch aan afschpelle',
+       'mwe-pixle2sec' => 'Pixele pro Sekund',
+       'mwe-rmclip' => 'Ußschnett fott schmiiße',
+       'mwe-clip_in' => 'Ußschnett en',
+       'mwe-clip_out' => 'Ußschnett uß',
+       'mwe-no_selected_resource' => '<h3>Nix ußjesöhk</h3>Söhk ene Ußschnett uß, öm et Ändere müjjelesch ze maache.',
+       'mwe-error_edit_multiple' => '<h3>Mieh wie ein Denge ußjesöhk</h3>Söhk ene einzel Ußschnett uß, öm et Ändere müjjelesch ze maache.',
+       'mwe-editor_options' => 'Enshtällunge för et Ändere',
+       'mwe-editor_mode' => 'Aat vum Beärbeide',
+       'mwe-simple_editor_desc' => 'Eijfach Beärbeide (em Shtil vun <i lang="en">iMovie</i>)',
+       'mwe-advanced_editor_desc' => 'Beärbeide met alle Schikaane (em Shtil vun <i lang="en">Final Cut</i>)',
+       'mwe-other_options' => 'Ander Müjjeleshkeite',
+       'mwe-contextmenu_opt' => 'Donn de Kontex-Menühß zohlohße',
+       'mwe-sequencer_credit_line' => 'Äntweckelt vun dä Ferma <i lang="en"><a href="http://kaltura.com">Kaltura, Inc.</a></i> em Zosammewerke met dä <a href="http://wikimediafoundation.org/wiki/Home">Wikimedia Shtefftung</a> (<a href="#">mieh Enfommazjohne</a>).',
+       'mwe-loading_txt' => 'aam Laade …',
+       'mwe-size-gigabytes' => '$1&nbsp;GB',
+       'mwe-size-megabytes' => '$1&nbsp;MB',
+       'mwe-size-kilobytes' => '$1&nbsp;KB',
+       'mwe-size-bytes' => '$1&nbsp;Bytes',
+       'mwe-error_load_lib' => 'Fähler: Dat JavaSkrep „<code lang="en">$1</code>“ wohr nit ze laade udder et leiht „<code lang="en">$2</code>“ nit faß.',
+       'mwe-cancel' => 'Affbräsche',
+       'mwe-remember-loging' => 'Opjepaß: För sescher ze sinn, donn bloß dann ööhnßwoh enlogge,wann Dinge Brauser dä ßait ier Addräß en singem Feld för de Addräß aanzeijsch!',
+       'fogg-select_file' => 'Dattei ußwähle',
+       'fogg-select_new_file' => 'Neu Dattei ußwähle',
+       'fogg-select_url' => '<i lang="en">URL</i> ußwähle',
+       'fogg-save_local_file' => 'Ogg afshpeijshere',
+       'fogg-check_for_firefogg' => 'Op <i lang="en">Firefogg</i> aam Prööve&nbsp;…',
+       'fogg-installed' => '<i lang="en">Firefogg</i> es ennjeresht',
+       'fogg-for_improved_uploads' => 'För e verbäßert Huhlaade:&nbsp;',
+       'fogg-please_install' => 'Donn <a href="$1"><i lang="en">Firefogg</i> ennreshte</a>. Kanns mieh <a href="http://commons.wikimedia.org/wiki/Commons:Firefogg">övver <i lang="en">Firefogg</i> lässe</a>.',
+       'fogg-use_latest_firefox' => 'Donn eets dä <i lang="en"><a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=firefogg">Firefox 3.5</a></i> (odder neuer) enshtalleere. Donoh jangk widder op hee di Sigg, öm et Zohsazprojramm <i lang="en"><b>Firefogg</b></i> ze enshtalleere.',
+       'fogg-passthrough_mode' => 'Ding ußjesöhk Dattei eß ald em <i lang="en">Ogg</i>-Fommaat, udder et eß jaa keine Viddejo drän.',
+       'fogg-transcoding' => 'Dä Viddejo weedt jraadt noh em <i lang="en">Ogg</i>-Fommaat ömjewandelt',
+       'fogg-encoding-done' => 'Ömwandlung es fäädesch',
+       'fogg-badtoken' => 'Dat <i lang="en">token</i> es nit jöltesch',
+       'fogg-preview' => 'Viddejo-Vör-Aansesch',
+       'fogg-hidepreview' => 'Vör-Aansesch verschteische',
+       'mwe-imported_from' => '$1 es vun [$2 $3] empotteet woode. Op dä [$4 Ojinaal-Sigg] künnt mieh doh drövver ze lässe sin.',
+       'mwe-stream_title' => '$1 $2 beß $3',
+       'fogg-help-sticky' => 'Hölp (aanklecke zom Faßhallde)',
+       'fogg-cg-preset' => 'Vörenshtellung: <strong>$1</strong>',
+       'fogg-cg-quality' => 'Jrundenshtellunge för de Kwalliteit un Oplöösung',
+       'fogg-cg-meta' => 'Metta_Daate för dä Ußschnett',
+       'fogg-cg-range' => 'Dä Berett för et Kodeere',
+       'fogg-cg-advVideo' => 'Ußföhrlesche Enshtellunge för de Viddejo-Kodeerung',
+       'fogg-cg-advAudio' => 'Ußföhrlesche Enshtellunge för de Tohn-Kodeerung',
+       'fogg-preset-custom' => 'Eije Enshtellunge',
+       'fogg-videoQuality-title' => 'De Qualliteit vum Viddejo',
+       'fogg-starttime-title' => 'Sekund vum Aanfang',
+       'fogg-starttime-help' => 'Dunn de Zick vum Aanfang bloß en Sekunde kodeere',
+       'fogg-endtime-title' => 'Sekund vum Ängk',
+       'fogg-endtime-help' => 'Dunn de Zick vum Ängk bloß en Sekunde kodeere',
+       'fogg-audioQuality-title' => 'De Tonqualliteit',
+       'fogg-videoCodec-title' => 'Et Ümwandlungsprojramm för Viddejos',
+       'fogg-audioCodec-title' => 'Et Ümwandlungsprojramm för Tondateeije',
+       'fogg-width-title' => 'Dämm Viddejo sing Breed',
+       'fogg-width-help' => 'Der Viddejo op de aanjejovve Breed bränge.',
+       'fogg-height-title' => 'Dämm Viddejo sing Hühde',
+       'fogg-height-help' => 'Der Viddejo op de aanjejovve Hühde bränge.',
+       'fogg-videoBitrate-title' => 'Dämm Viddejo sing Bitraat',
+       'fogg-videoBitrate-help' => 'Dämm Viddejo sing Bitraat säz de Bitraat för et Koddeere för dä Viddejo en Killobits pro Sekund.',
+       'fogg-twopass-title' => 'Kodeere en zweij Dorschjäng',
+       'fogg-twopass-help' => 'Kodeere en zweij Dorschjäng sorresch för en besser Qualliteit, endämm dat et zweijmohl övver dä Viddejo jeiht',
+       'fogg-novideo-title' => 'Kei Viddejo',
+       'fogg-novideo-help' => 'donn dä Viddejo en de Ußjabe ußschallde',
+       'fogg-noaudio-title' => 'Keine Tohn',
+       'fogg-noaudio-help' => 'donn dä Tohn en de Ußjab ußschallde',
+       'fogg-title-title' => 'Övverschreff',
+       'fogg-title-help' => 'Enne Tittel för Dinge Ußschnett',
+       'fogg-date-title' => 'Dattum',
+       'fogg-location-title' => 'Plaz',
+       'fogg-copyright-title' => 'Urhävverrääsch',
+       'fogg-license-title' => 'Lizänz',
+       'fogg-license-help' => 'De Lizänz, onger dä dä Ußschnett schteiht — am leevste ham_mer en <i lang="en">URL</i> vun <i lang="en">Creative Commons</i>.',
+       'fogg-contact-title' => 'Kumtak',
+       'fogg-contact-help' => 'Kumtak Lengk',
+       'mwe-add_media_wizard' => 'Der Hexemeister för Meedije dobeidonn',
+       'mwe-media_search' => 'Meedijje Söhke',
+       'rsd_box_layout' => 'Als ene Kaßte',
+       'rsd_list_layout' => 'Als en Leß',
+       'rsd_results_desc' => 'Eruß kohme $1 beß $2',
+       'rsd_results_desc_total' => 'Eruß kohme $1 beß $2 vun Schtöcker $3',
+       'rsd_results_next' => 'näx',
+       'rsd_results_prev' => 'vörijje',
+       'rsd_no_results' => 'Beim Söhke noh <b>$1</b> kohm nix erus',
+       'mwe-upload_tab' => 'Huhlaade',
+       'rsd_layout' => 'Forrem:',
+       'rsd_resource_edit' => 'Beärbeide: $1',
+       'mwe-resource_description_page' => 'Sigg, woh dat beschrevve es',
+       'mwe-link' => 'Lengk',
+       'rsd_local_resource_title' => 'Dä Tittel dofun heh em Wiki',
+       'rsd_do_insert' => 'Ennfööje',
+       'mwe-cc_title' => '<i lang="en">Creative Commons</i>',
+       'mwe-cc_by_title' => 'De Schriiver möße jenannt wääde',
+       'mwe-cc_nc_title' => 'Kein Jeldverdeene met zohjelohße',
+       'mwe-cc_nd_title' => 'Kein afjeleidt Werke zohjelohße',
+       'mwe-cc_sa_title' => 'Afjeleidt Werke onger desellve Bedenunge wigger jävve',
+       'mwe-cc_pd_title' => 'Allmende (jemeinfrei, <i lang="en">public domain</i>)',
+       'mwe-unknown_license' => 'En onbikannte Lizänz',
+       'mwe-no_import_by_url' => 'Heh dä Metmaacher odder heh dat Wiki <b>kann nix</b> vun <i lang="en">URLs</i> vun ußerhallef empotteere.
+
+Moß De enlogge?
+
+Wann de Rääschte reschtesch jesaz sin, moß mer velleijsh noch <a href="http://www.mediawiki.org/wiki/Manual:$wgAllowCopyUploads"><code lang="en">$wgAllowCopyUploads</code></a> aanschallde.',
+       'mwe-results_from' => 'Wat eruß kohm bei <a href="$1" target="_new" >$2</a>',
+       'mwe-missing_desc_see_source' => 'Dat Denge hee es unbeschrevve. Loor op dä [$1 Ojinaal-Sigg] noh, un hellf met, dat mer dat noh heh krijje.',
+       'rsd_config_error' => 'Dä Hexemeister för Meedije hädd_enne Fähler en singe Enshtällunge: $1',
+       'mwe-your_recent_uploads' => 'Ding neuer huhjelaade Datteije noh $1',
+       'mwe-upload_a_file' => 'Neu Dattei not $1 huhlaade',
+       'mwe-resource_page_desc' => 'Beschrevve:',
+       'mwe-edit_resource_desc' => 'Donn dä Wiki_Kood ändere, woh dat Denge met beschrevve es:',
+       'mwe-local_resource_title' => 'Dä Tittel heh em Wiki:',
+       'mwe-watch_this_page' => 'Op di Sigg hee oppasse',
+       'mwe-do_import_resource' => 'Empotteere',
+       'mwe-update_preview' => 'Vör_Aansesch op der neuste Shtand bränge',
+       'mwe-cancel_import' => 'Empotteere Afbreshe!',
+       'mwe-importing_asset' => 'Ben aam Empotteere',
+       'mwe-preview_insert_resource' => 'Vör_Aansesch övver et Ennfööje vun: $1',
+       'mwe-resource-needs-import' => 'De Quäll $1 moß noh $2 empotteet wääde',
+       'mwe-ftype-svg' => 'Ene <code lang="en"i>SVG</code> Dattei met Väktoore',
+       'mwe-ftype-jpg' => 'Ene <code lang="en"i>JPEG</code> Dattei met enem Beld',
+       'mwe-ftype-png' => 'Ene <code lang="en"i>PNG</code> Dattei met enem Beld',
+       'mwe-ftype-oga' => 'Ene <code lang="en"i>OGG</code> Dattei met Tön',
+       'mwe-ftype-ogg' => 'Ene <code lang="en"i>Ogg</code> Dattei met enem Viddejo',
+       'mwe-ftype-unk' => 'E nit bekannt Datteifommaat',
+       'rsd-wiki_commons-title' => '<i lang="en">Wikimedia Commons</i>',
+       'rsd-wiki_commons' => '<i lang="en">Wikimedia Commons</i>, en A\'schiif met Medije för jät vun ze liehre unger freije Lizänze, met Beld-, Ton-, un Viddejo-Datteije',
+       'rsd-this_wiki-title' => 'Heh dat Wiki',
+       'rsd-flickr-desc' => '<i lang="en">Flickr.com</i>, en Websigg för Fottos öffentlesch ze maache',
+       'mwe-select_file' => 'Dattei ußsöhke',
+       'mwe-more_licence_options' => 'Mieh Müjjeleschkeite för en Lizänz fengkd_Er op dä <a href="$1">jewööhnlijje Sigg zem Huhlaade</a>.',
+       'mwe-select_ownwork' => 'Esch ben bloß ming eije Werk aam huhlaade, un et darf jebruch wääde onger dä Lizänz:',
+       'mwe-licence_cc-by-sa' => 'Wiggerjävve onger desellve Bedengunge (noh <i lang="en">Creative Commons</i>) (3.0)',
+       'mwe-upload' => 'Dattei huhlaade',
+       'mwe-destfilename' => 'Dä Name för di neu Dattei:',
+       'mwe-summary' => '{{int:Summary}}',
+       'mwe-error_not_loggedin' => 'Do bes nit enjelogg udder häs nit dat Rääsch för jät huhzelaade.',
+       'mwe-watch-this-file' => 'Op heh di Dattei oppaße',
+       'mwe-ignore-any-warnings' => 'All de Warnunge övverjonn',
+       'mwe-upload-transcode-in-progress' => 'Et Huhlaade un Ömsaze es ungerwähß (Donn heh dat Finster nit zohmaache)',
+       'mwe-upload-in-progress' => 'Et Huhlaade es em Jang (Donn heh dat Finster nit zohmaache)',
+       'mwe-upload-transcoded-status' => 'Ömjesaz',
+       'mwe-uploaded-status' => 'Huhjelaade',
+       'mwe-upload-stats-fileprogress' => '$1 vun $2',
+       'mwe-upload_completed' => 'Et Huhlaade es fäädesch',
+       'mwe-upload_done' => '<a href="$1">Ding huhjelaade Dattei <i>sullt</i> zo han sinn</a>.',
+       'mwe-upload-unknown-size' => 'Dä Datteiömfang es unbikannt',
+       'mwe-cancel-confim' => 'Wells De werklesch ophüüre?',
+       'mwe-successfulupload' => 'Huhjelaade',
+       'mwe-uploaderror' => 'Fähler beim Huhlaade',
+       'mwe-uploadwarning' => 'Warnung beim Huhlade',
+       'mwe-unknown-error' => 'Fähler, dä mer nit kenne:',
+       'mwe-return-to-form' => 'Jangk retuur op dat Fommulaa',
+       'mwe-file-exists-duplicate' => 'Di Dattei es dubbel met dä hee:',
+       'mwe-fileexists' => 'En Dattei met dämm Name jidd_et ald. Beß esu joot un donn <b><tt>$1</tt></b> prööfe, wann De Der nit sescher beß, of De jät ändere wells.',
+       'mwe-fileexists-thumb' => '<center>Datei ald doh</center>',
+       'mwe-ignorewarning' => '{{int:ignorewarning}}',
+       'mwe-file-thumbnail-no' => 'Dä Dattei iere Name fängk met <b><tt>$1</tt></b> aan.',
+       'mwe-go-to-resource' => 'Jank op di Sigg doh drövver',
+       'mwe-upload-misc-error' => 'Dat Huhlaade jing donevve, woröm es nit kloh',
+       'mwe-wgfogg_warning_bad_extension' => 'Do häss_en Dattei met enem onbikannte Datteinamesengk ußjsöhk (<a href="http://commons.wikimedia.org/wiki/Commons:Firefogg#Supported_File_Types">mieh doh drövver</a>).',
+       'mwe-upload-multi' => '{{PLURAL:$1|Ein Datei|$1 Dateie|Kein Datteije}} huhlaade',
+       'mwe-review-upload' => 'Donn de huhjelaade {{PLURAL:$1|Dattei|Datteije|nix}} nohloore',
+       'mwe-loading_plugin' => 'Ben dat Ongerprojramm aam laade&nbsp;…',
+       'mwe-select_playback' => 'Enstellunge för et Affshpelle maache',
+       'mwe-link_back' => 'Lengk retuur',
+       'mwe-error_swap_vid' => 'Fähler: <code lang="en">mv_embed</code> kunnt de Etikätte för dä Viddejo för <code lang="en">mv_embed</code> sing Schnetshtäl nit ußtuusche.',
+       'mwe-add_to_end_of_sequence' => 'Aam Engk vun dä Afschpellleß aanfööje',
+       'mwe-missing_video_stream' => 'De Viddejodattei för heh dä Daateshrom fählt',
+       'mwe-play_clip' => 'Donn dä Ußschnedd afshpelle',
+       'mwe-pause_clip' => 'Donn dä Ußschnedd aanhallde',
+       'mwe-volume_control' => 'Enshtellung för de Loutshtärk',
+       'mwe-player_options' => 'Enschtellunge för Affshpellprojramme',
+       'mwe-closed_captions' => 'Beischreffte',
+       'mwe-player_fullscreen' => 'Op der janze Beldscherm jonn',
+       'mwe-next_clip_msg' => 'Donn dä Ußschnedd donoh shpelle',
+       'mwe-prev_clip_msg' => 'Donn dä Ußschnedd dovöör shpelle',
+       'mwe-current_clip_msg' => 'Donn dä Ußschnedd wigger shpelle',
+       'mwe-seek_to' => 'Söhk bes: $1',
+       'mwe-paused' => 'aanjehallde',
+       'mwe-download_segment' => 'Ußwahl för erunger ze laade:',
+       'mwe-download_full' => 'Donn dä janze Viddejo erunge laade:',
+       'mwe-download_right_click' => 'Zom Eronger laade, kleck met dä rääschte Taßd_aan Dinge Muuß, un söhk „Afshpeishere onger&nbsp;…“ uß',
+       'mwe-download_clip' => 'Viddejo erunger lade',
+       'mwe-download_text' => 'Tex erungerlaade (<i lang="en"><a style="color:white" title="cmml" href="http://wiki.xiph.org/index.php/CMML">CMML</a> XML</i>):',
+       'mwe-download' => 'Eronger laade',
+       'mwe-share' => 'Wigger jävve',
+       'mwe-credits' => 'Aanerkennunge för Beidrääsch',
+       'mwe-clip_linkback' => 'Däm Ußschnett singe Quällsigg',
+       'mwe-chose_player' => 'Donn en Affshpellprojramm för Viddejos ußsöhke',
+       'mwe-share_this_video' => 'Donn dä Viddejo wigger jävve',
+       'mwe-video_credits' => 'Aanerkennunge för Beidrääsch aan dämm Viddejo',
+       'mwe-menu_btn' => 'Ußwahl',
+       'mwe-close_btn' => 'Zohmaache',
+       'mwe-ogg-player-vlc-player' => 'Dä <i lang="en">VLC</i>-Affschpeller',
+       'mwe-ogg-player-videoElement' => 'Däm <i lang="en">Ogg</i>-Shpeller singe enjeboute Viddejo-Affshpeller',
+       'mwe-ogg-player-oggPlugin' => 'Däm <i lang="en">Ogg</i>-Shpeller sing Stanndatt-<i lang="en">plugin</i>',
+       'mwe-ogg-player-quicktime-mozilla' => 'Dä <i lang="en">QuickTime</i>-Shpeller als <i lang="en">plugin</i>',
+       'mwe-ogg-player-quicktime-activex' => 'Dä <i lang="en">QuickTime</i>-Shpeller övver <i lang="en">ActiveX</i>',
+       'mwe-ogg-player-cortado' => 'Dä <i lang="en">Java Cortado</i> Shpeller',
+       'mwe-ogg-player-flowplayer' => 'Dä <i lang="en">Flow</i>shpeller',
+       'mwe-ogg-player-kplayer' => 'Dä <i lang="en">Kaltura</i> Afshpeller',
+       'mwe-ogg-player-selected' => '(ußjesöhk)',
+       'mwe-ogg-player-omtkplayer' => '<i lang="en">OMTK Flash Vorbis</i> Shpeller',
+       'mwe-generic_missing_plugin' => 'Dinge Brauser schingk de Zoot <b>$1</b> för et Afshpelle nit ze künne.<br />Loor Der de <a href="http://commons.wikimedia.org/wiki/Commons:Media_help">Sigg över de Mettoode för et Afshpelle</a> aan, öm e Afshpellprojramm eraf ze laade.<br />',
+       'mwe-for_best_experience' => 'öm en bäßere Qualliteit för dä Viddejo ze krijje, nämmp_der:<br /><b><i lang="en"><a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=mwEmbed">Firefox 3.5</a></i>.</b>',
+       'mwe-do_not_warn_again' => 'Eets ens nit norr_ens aanzeije.',
+       'mwe-playerselect' => 'Affshpellprojramme',
+       'mwe-read_before_embed' => 'Beß esu joot un liß <a href="http://mediawiki.org/wiki/Security_Notes_on_Remote_Embedding" target="_new">övver de Sesherheit bemm Ennfööje övver et Netz</a> iih dat De jet ennfööschß!',
+       'mwe-embed_site_or_blog' => 'En en Websigg udder <i lang="en">Blog</i>_erinndonn',
+       'mwe-related_videos' => 'Verwandte Viddejos',
+       'mwe-seeking' => 'aam Söhke',
+       'mwe-copy-code' => 'Kood kopeere',
+);
+
+/** Luxembourgish (Lëtzebuergesch)
+ * @author McDutchie
+ * @author Robby
+ */
+$messages['lb'] = array(
+       'mwe-crop' => 'Bild ofschneiden',
+       'mwe-apply_crop' => "Ofschneiden op d'Bild uwenden",
+       'mwe-reset_crop' => 'Ofschneiden zrécksetzen',
+       'mwe-insert_image_page' => "An d'Säit drasetzen",
+       'mwe-insert_into_sequence' => "An d'Sequenz drasetzen",
+       'mwe-preview_insert' => 'Drasetze kucken ouni ze späicheren',
+       'mwe-cancel_image_insert' => 'Drasetzen ofbriechen',
+       'mwe-sc_fileopts' => 'Detail vum Clip änneren',
+       'mwe-sc_audio' => 'Audiosteierung',
+       'mwe-sc_duration' => 'Dauer',
+       'mwe-template_properties' => 'Eegeschafte vun der Schabloun',
+       'mwe-custom_title' => 'Personaliséierten Titel',
+       'mwe-edit_properties' => 'Eegeschaften änneren',
+       'mwe-other_properties' => 'Aner Eegeschaften',
+       'mwe-start_time' => 'Ufankszäit',
+       'mwe-end_time' => 'Schlusszäit',
+       'mwe-edit-tools' => "Handwierksgeschir fir z'änneren",
+       'mwe-inline-description' => 'Beschreiwung',
+       'mwe-duration' => 'Dauer:',
+       'mwe-upload-subs-file' => 'Ënnertitel eroplueden',
+       'mwe-add-subs-file-title' => 'Sicht en Ënnertitel eraus fir eropzelueden',
+       'mwe-error-only-srt' => 'Dir kënnt nëmmen srt-Fichieren eroplueden.',
+       'mwe-watch-video' => 'Video kucken',
+       'mwe-select-other-language' => 'Aner Sprooch eraussichen',
+       'mwe-saving' => 'späicheren...',
+       'mwe-select_transcript_set' => 'Ënnertitelen eraussichen',
+       'mwe-auto_scroll' => 'automatesch scrollen',
+       'mwe-close' => 'zoumaachen',
+       'mwe-improve_transcript' => 'Verbesseren',
+       'mwe-no_text_tracks_found' => 'Keng Text-Ënnertitele fonnt',
+       'mwe-add-edit-subs' => 'Ënnertitelen derbäisetzen/änneren',
+       'mwe-transition_in' => 'Iwwergang fir eran',
+       'mwe-transition_out' => 'Iwwergang fir eraus',
+       'mwe-remove_transition' => 'Iwwergang ewechhuelen',
+       'mwe-add-transition' => 'En Iwwergang derbäisetzen',
+       'mwe-menu_transition' => 'Iwwergäng an Effekter',
+       'mwe-menu_cliplib' => 'E Medium derbäi setzen',
+       'mwe-menu_resource_overview' => "Iwwersiicht iwwer d'Ressourcen",
+       'mwe-menu_options' => 'Optiounen',
+       'mwe-loading_timeline' => 'Zäitläischt lueden ...',
+       'mwe-loading_user_rights' => 'Benotzerrechter lueden ...',
+       'mwe-no_edit_permissions' => "Dir hutt net d'Rechter fir Ännerungen un dëser Sequenz",
+       'mwe-edit_clip' => 'Clip änneren',
+       'mwe-edit_save' => "D'Ännerunge vun der Sequenz späicheren",
+       'mwe-saving_wait' => 'Späicheren amgaang (waard w.e.g.)',
+       'mwe-save_done' => 'Späicheren ofgeschloss',
+       'mwe-edit_cancel' => 'Ännerung vun der Sequenz ofbriechen',
+       'mwe-edit_cancel_confirm' => "Sidd Dir sécher datt dir Är Ännerung ofbrieche wëllt? D'Ännerunge gi verluer.",
+       'mwe-zoom_in' => 'Era zoomen',
+       'mwe-cut_clip' => 'Clippe schneiden',
+       'mwe-pixle2sec' => 'Pixelen op Sekonnen',
+       'mwe-rmclip' => 'Clip ewechhuelen',
+       'mwe-clip_in' => 'Clip derbäisetzen',
+       'mwe-clip_out' => 'Clip ewechhuelen',
+       'mwe-other_options' => 'Aner Optiounen',
+       'mwe-contextmenu_opt' => 'Kontextmenüen aktivéieren',
+       'mwe-sequencer_credit_line' => 'Entwéckelt vu <a href="http://kaltura.com">Kaltura, Inc.</a> an zesummenaarbecht mat der <a href="http://wikimediafoundation.org/wiki/Home">Wikimedia Foundation</a> (<a href="#">méi Informatiounen</a>).',
+       'mwe-loading_txt' => 'lueden ...',
+       'mwe-apiproxy-setup' => 'API-Proxy astellen',
+       'mwe-ok' => 'OK',
+       'mwe-cancel' => 'Ofbriechen',
+       'mwe-setting-up-proxy' => 'Proxy astellen ...',
+       'mwe-re-try' => 'Api-Ufro widderhuelen',
+       'mwe-re-trying' => 'UPI-Ufro gëtt widderholl.',
+       'mwe-proxy-not-ready' => 'De Proxy ass net agestallt',
+       'fogg-select_file' => 'Fichier eraussichen',
+       'fogg-select_new_file' => 'Neie Fichier eraussichen',
+       'fogg-select_url' => 'URL eraussichen',
+       'fogg-save_local_file' => 'Ogg späicheren',
+       'fogg-check_for_firefogg' => 'Sichen no Firefogg ...',
+       'fogg-installed' => 'Firefogg ass installéiert',
+       'fogg-for_improved_uploads' => 'Fir verbessert Eroplueden:',
+       'fogg-please_install' => '<a href="$1">Installéiert Firefogg</a>. Méi <a href="http://commons.wikimedia.org/wiki/Commons:Firefogg">iwwer Firefogg</a>',
+       'fogg-use_latest_firefox' => "Installéiert w.e.g. fir d'éischt <a href=\"http://www.mozilla.com/en-US/firefox/upgrade.html?from=firefogg\">Firefox 3.5</a> (oder méi eng nei Versioun). <i>Kommt duerno zréck op dës Säit fir d'<b>Firefogg</b>-Erweiderung z'installéieren.</i>",
+       'fogg-preview' => 'Video kucken ouni ze späicheren',
+       'mwe-imported_from' => "$1 huet vun [$2 $3] importéiert. Kuckt d'[$4 Originalquellsäit] fir méi Informatiounen.",
+       'mwe-stream_title' => '$1 $2 bis $3',
+       'fogg-help-sticky' => 'Hëllef (klickt fir festzestellen)',
+       'fogg-cg-meta' => 'Meta-Date fir de Clip',
+       'fogg-preset-custom' => 'Personaliséiert Astellungen',
+       'fogg-videoQuality-title' => 'Videoqualitéit',
+       'fogg-audioQuality-title' => 'Audioqualitéit',
+       'fogg-videoCodec-title' => 'Videocodec',
+       'fogg-width-title' => 'Breet vum Video',
+       'fogg-width-help' => 'Redimensionéieren op déi Breet déi uginn ass.',
+       'fogg-height-title' => 'Héicht vum Video',
+       'fogg-height-help' => 'Redimensionéieren op déi Héicht déi uginn ass.',
+       'fogg-denoise-title' => 'Rauschfilter',
+       'fogg-novideo-title' => 'Kee Video',
+       'fogg-noaudio-title' => 'Keen Toun',
+       'fogg-title-title' => 'Titel',
+       'fogg-title-help' => 'En Titel fir Äre Clip',
+       'fogg-artist-title' => 'Numm vum Artist',
+       'fogg-date-title' => 'Datum',
+       'fogg-date-help' => "Den Datum wou d'Filmmaterial zesummegestallt oder verëffentlecht gouf",
+       'fogg-location-title' => 'Plaz',
+       'fogg-organization-title' => 'Organisatioun',
+       'fogg-organization-help' => 'Numm vun der Organisatioun (Studio)',
+       'fogg-copyright-title' => 'Copyright',
+       'fogg-copyright-help' => 'De Copyright vum Clip',
+       'fogg-license-title' => 'Lizens',
+       'fogg-contact-title' => 'Kontakt',
+       'fogg-contact-help' => 'Link vum Kontakt',
+       'rsd_box_layout' => 'Layout vun der Këscht',
+       'rsd_list_layout' => 'Layout vun der Lëscht',
+       'rsd_results_desc' => 'Resultater $1 bis $2',
+       'rsd_results_desc_total' => 'Resultatet $1 bis $2 vu(n) $3',
+       'rsd_results_next' => 'nächsten',
+       'rsd_results_prev' => 'vireg',
+       'rsd_no_results' => 'Kee Resultat bäi der Sich no <b>$1</b>',
+       'mwe-upload_tab' => 'Eroplueden',
+       'rsd_layout' => 'Layout:',
+       'mwe-link' => 'Link',
+       'rsd_do_insert' => 'Drasetzen',
+       'mwe-cc_by_title' => 'Attributioun',
+       'mwe-cc_nc_title' => 'Net-kommerziell',
+       'mwe-unknown_license' => 'Onbekannte Lizenz',
+       'mwe-no_import_by_url' => 'Dëse Benotzer oder dës Wiki <b>kënne eng</b> Poste vun externen URLen importéieren.
+<p>Musst Dir Iech aloggen?</p>
+<p>Sinn upload_by_url-Rechter fir Iech agestallt?<br />Huet dës Wiki <a href="http://www.mediawiki.org/wiki/Manual:$wgAllowCopyUploads">$wgAllowCopyUploads</a> ageschalt?</p>',
+       'mwe-results_from' => 'Resultater vu(n) <a href="$1" target="_new" >$2</a>',
+       'mwe-your_recent_uploads' => 'Är rezent op $1 eropgeluede Fichieren',
+       'mwe-upload_a_file' => 'En neie Fichier op $1 eroplueden',
+       'mwe-watch_this_page' => 'Dës Säit iwwerwaachen',
+       'mwe-cancel_import' => 'Import ofbriechen',
+       'mwe-ftype-svg' => 'SVG Vektor-Fichier',
+       'mwe-ftype-jpg' => 'JPEG Bild-Fichier',
+       'mwe-ftype-png' => 'PNG Bild-Fichier',
+       'mwe-ftype-oga' => 'Ogg Audio-Fichier',
+       'mwe-ftype-ogg' => 'Ogg Video-Fichier',
+       'mwe-ftype-unk' => 'Onbekannte Format vum Fichier',
+       'rsd-wiki_commons-title' => 'Wikimedia Commons',
+       'rsd-this_wiki-title' => 'Dës Wiki',
+       'rsd-this_wiki-desc' => 'Déi lokal installéiert Wiki',
+       'mwe-select_file' => 'Fichier eraussichen',
+       'mwe-licence_cc-by-sa' => 'Creative Commons Share Alike (3.0)',
+       'mwe-upload' => 'Fichier eroplueden',
+       'mwe-destfilename' => 'Numm vum Zilfichier',
+       'mwe-summary' => 'Resumé',
+       'mwe-error_not_loggedin' => 'Et gesäit aus wéi wann dir net ageloggt wiert oder Dir hutt keng Rechter fir eppes eropzelueden.',
+       'mwe-watch-this-file' => 'Dëse Fichier iwwerwwaachen',
+       'mwe-ignore-any-warnings' => 'All Warnungen ignoréieren',
+       'mwe-upload-in-progress' => "Eroplueden amgaang (maacht d'Fënster net zou)",
+       'mwe-uploaded-status' => 'Eropgelueden',
+       'mwe-upload-stats-fileprogress' => '$1 vu(n) $2',
+       'mwe-upload_completed' => "D'Eroplueden ass ofgeschloss",
+       'mwe-upload_done' => '<a href="$1">De Fichier deen Dir eropgelueden hutt <i>misst</i> elo disponibel sinn</a>.',
+       'mwe-upload-unknown-size' => 'Onbekannte Gréisst',
+       'mwe-cancel-confim' => 'Sidd Dir sécher datt Dir ofbrieche wëllt?',
+       'mwe-successfulupload' => 'Mat Erfolleg eropgelueden',
+       'mwe-uploaderror' => 'Feeler beim eroplueden',
+       'mwe-uploadwarning' => 'Warnung beim Eroplueden',
+       'mwe-unknown-error' => 'Onbekannte Feeler',
+       'mwe-return-to-form' => 'Zréck op de Formulaire',
+       'mwe-file-exists-duplicate' => 'Dëse Fichier ass en Doublon vun dësem Fichier:',
+       'mwe-fileexists' => 'E Fichier mat dësem Numm gëtt et schonn. Kuckt w.e.g. op <b><tt>$1</tt></b> no wann Dir net sécher sidd ob Dir en ännere wëllt.',
+       'mwe-fileexists-thumb' => '<center><b>Fichier deen et gëtt</b></center>',
+       'mwe-ignorewarning' => 'Warnung ignoréieren an de Fichier trotzdeem späicheren',
+       'mwe-file-thumbnail-no' => 'Den Numm vum fichier fänkt mat <b><tt>$1</tt></b> un',
+       'mwe-upload-misc-error' => 'Onbekannte Feeler beim Eroplueden',
+       'mwe-wgfogg_warning_bad_extension' => 'Dir hutt e Fichier mat enger Erweiderung déi net ënnerstetzt gëtt (<a href="http://commons.wikimedia.org/wiki/Commons:Firefogg#Supported_File_Types">méi Informatiounen</a>) erausgesicht.',
+       'mwe-upload-multi' => '{{PLURAL:$1|Fichier|Fichieren}} eroplueden',
+       'mwe-review-upload' => '{{PLURAL:$1|Eropgeluedene Fichier|Eropgeluede Fichieren}} nokucken',
+       'mwe-credit-title' => 'Titel: $1',
+       'mwe-loading_plugin' => 'Plugin lueden ...',
+       'mwe-select_playback' => 'Astellunge vum Ofspillen festleeën',
+       'mwe-link_back' => 'Link zréck',
+       'mwe-add_to_end_of_sequence' => 'Um Schluss vun der Sequenz derbäisetzen',
+       'mwe-missing_video_stream' => 'De Video-Fichier fir dëse Stream feelt',
+       'mwe-play_clip' => 'Clip spillen',
+       'mwe-pause_clip' => 'Clip ënnerbriechen',
+       'mwe-closed_captions' => 'Erklärungen déi zougemaachen',
+       'mwe-player_fullscreen' => 'Ganzen Ecran',
+       'mwe-next_clip_msg' => 'Nächste Clip spillen',
+       'mwe-prev_clip_msg' => 'Virege Clip spillen',
+       'mwe-current_clip_msg' => 'Dëse Clip weiderspillen',
+       'mwe-seek_to' => 'Sich $1',
+       'mwe-paused' => 'ënnerbrach',
+       'mwe-download_segment' => 'Dat wat erausgesicht ass eroflueden:',
+       'mwe-download_full' => 'Ganze Videofichier eroflueden:',
+       'mwe-download_right_click' => 'Fir erofzelueden, klickt op déi riets Maustast a wielt <i>Link späicheren als...</i>',
+       'mwe-download_clip' => 'Video eroflueden',
+       'mwe-download_text' => 'Text eroflueden (<a style="color:white" title="cmml" href="http://wiki.xiph.org/index.php/CMML">CMML</a> xml):',
+       'mwe-download' => 'Eroflueden',
+       'mwe-share' => 'Deelen',
+       'mwe-share_this_video' => 'Dëse Video deelen',
+       'mwe-menu_btn' => 'Menü',
+       'mwe-close_btn' => 'Zoumaachen',
+       'mwe-ogg-player-quicktime-mozilla' => 'QuickTime-Plugin',
+       'mwe-ogg-player-quicktime-activex' => 'QuickTime ActiveX',
+       'mwe-ogg-player-cortado' => 'Java Cortado',
+       'mwe-ogg-player-selected' => '(erausgesicht)',
+       'mwe-ogg-player-omtkplayer' => 'OMTK Flash Vorbis',
+       'mwe-do_not_warn_again' => 'Fir den Ament ophalen.',
+       'mwe-playerselect' => 'Spiller',
+       'mwe-read_before_embed' => 'Liest w.e.g. virum Abannen d\'<a href="http://mediawiki.org/wiki/Security_Notes_on_Remote_Embedding" target="_new">Sécherheetsinformatiounen iwwert d\'Abannen iwwer Remote</a> ier Dir mam Abanne weidermaacht!',
+       'mwe-embed_site_or_blog' => 'An Är Säit abauen',
+       'mwe-related_videos' => 'Ähnlech Videoen',
+       'mwe-seeking' => 'sichen',
+       'mwe-copy-code' => 'Code kopéieren',
+);
+
+/** Malayalam (മലയാളം)
+ * @author McDutchie
+ * @author Praveenp
+ */
+$messages['ml'] = array(
+       'mwe-crop' => 'ചിത്രം മുറിയ്ക്കുക',
+       'mwe-apply_crop' => 'മുറിയ്ക്കൽ ചിത്രത്തിൽ പ്രാവർത്തികമാക്കുക',
+       'mwe-reset_crop' => 'മുറിയ്ക്കൽ പുനഃക്രമീകരിക്കുക',
+       'mwe-insert_image_page' => 'താളിൽ ഉൾപ്പെടുത്തുക',
+       'mwe-insert_into_sequence' => 'അനുവർത്തനത്തിലേയ്ക്ക് ഉൾപ്പെടുത്തുക',
+       'mwe-preview_insert' => 'ഉൾപ്പെടുത്തലിന്റെ പ്രിവ്യൂ',
+       'mwe-cancel_image_insert' => 'ഉൾപ്പെടുത്തൽ റദ്ദാക്കുക',
+       'mwe-sc_fileopts' => 'ചലച്ചിത്രശകലത്തിന്റെ വിവരങ്ങൾ തിരുത്തുക',
+       'mwe-sc_audio' => 'ശബ്ദ നിയന്ത്രണം',
+       'mwe-sc_duration' => 'കാലയളവ്',
+       'mwe-template_properties' => 'ഫലക വിശേഷതകൾ',
+       'mwe-custom_title' => 'മാറ്റിയെഴുതാവുന്ന തലക്കെട്ട്',
+       'mwe-edit_properties' => 'വിശേഷതകൾ തിരുത്തുക',
+       'mwe-other_properties' => 'മറ്റ് വിശേഷതകൾ',
+       'mwe-resource_page' => 'സ്രോതസ്സ് താൾ:',
+       'mwe-start_time' => 'തുടങ്ങുന്ന സമയം',
+       'mwe-end_time' => 'അവസാനിക്കുന്ന സമയം',
+       'mwe-edit-tools' => 'തിരുത്തൽ ഉപകരണങ്ങൾ',
+       'mwe-inline-description' => 'അടിക്കുറിപ്പ്',
+       'mwe-edit-video-tools' => 'ചലച്ചിത്രത്തിൽ മാറ്റം വരുത്താനുള്ള ഉപകരണങ്ങൾ:',
+       'mwe-duration' => 'ദൈർഘ്യം:',
+       'mwe-upload-subs-file' => 'അടിയെഴുത്തുകൾ അപ്‌‌ലോഡ് ചെയ്യുക',
+       'mwe-add-subs-file-title' => 'അപ്‌‌ലോഡ് ചെയ്യാനായി അടിയെഴുത്ത് തിരഞ്ഞെടുക്കുക',
+       'mwe-error-only-srt' => 'താങ്കൾക്ക് എസ്.ആർ.റ്റി. പ്രമാണങ്ങൾ മാത്രമേ അപ്‌‌ലോഡ് ചെയ്യാനാവൂ.',
+       'mwe-watch-video' => 'ചലച്ചിത്രം കാണുക',
+       'mwe-select-other-language' => 'മറ്റു ഭാഷകൾ തിരഞ്ഞെടുക്കുക',
+       'mwe-saving' => 'സേവ് ചെയ്യുന്നു...',
+       'mwe-select_transcript_set' => 'അടിയെഴുത്തുകൾ തിരഞ്ഞെടുക്കുക',
+       'mwe-close' => 'അടയ്ക്കുക',
+       'mwe-improve_transcript' => 'മെച്ചപ്പെടുത്തുക',
+       'mwe-no_text_tracks_found' => 'അടിയെഴുത്തുകൾക്കായുള്ള എഴുത്തുകളൊന്നും കണ്ടെത്താനായില്ല',
+       'mwe-add-edit-subs' => 'അടിയെഴുത്തുകൾ ചേർക്കുക/തിരുത്തുക',
+       'mwe-menu_clipedit' => 'മീഡിയ തിരുത്തുക',
+       'mwe-menu_cliplib' => 'മീഡിയ കൂട്ടിച്ചേർക്കുക',
+       'mwe-menu_resource_overview' => 'സ്രോതസ്സ് അവലോകനം',
+       'mwe-menu_options' => 'ഐച്ഛികങ്ങൾ',
+       'mwe-loading_timeline' => 'സമയരേഖ ശേഖരിക്കുന്നു ...',
+       'mwe-loading_user_rights' => 'ഉപയോക്തൃ അവകാശങ്ങൾ ശേഖരിക്കുന്നു ...',
+       'mwe-no_edit_permissions' => 'ഈ അനുവർത്തനത്തിൽ മാറ്റങ്ങൾ സേവ് ചെയ്യാനുള്ള അനുമതി താങ്കൾക്കില്ല',
+       'mwe-edit_clip' => 'ചലച്ചിത്രശകലം തിരുത്തുക',
+       'mwe-edit_save' => 'അനുവർത്തനത്തിലെ മാറ്റങ്ങൾ സേവ് ചെയ്യുക',
+       'mwe-saving_wait' => 'സേവ് ചെയ്യൽ പുരോഗമിക്കുന്നു (ദയവായി കാത്തിരിക്കുക)',
+       'mwe-save_done' => 'പൂർണ്ണമായത് സേവ് ചെയ്യുക',
+       'mwe-edit_cancel' => 'അനുവർത്തനത്തിലെ തിരുത്തൽ റദ്ദാക്കുക',
+       'mwe-edit_cancel_confirm' => 'താങ്കളുടെ തിരുത്തൽ റദ്ദാക്കണം എന്നതിൽ താങ്കൾ ഉറച്ചു നിൽക്കുന്നുവോ? മാറ്റങ്ങൾ നഷ്ടമാവുന്നതാണ്.',
+       'mwe-zoom_in' => 'വലുതാക്കുക',
+       'mwe-zoom_out' => 'ചെറുതാക്കുക',
+       'mwe-cut_clip' => 'ചലച്ചിത്രശകലം മുറിയ്ക്കുക',
+       'mwe-rmclip' => 'ചലച്ചിത്രശകലം നീക്കംചെയ്യുക',
+       'mwe-clip_in' => 'ചലച്ചിത്രശകലം ഉൾപ്പെടുത്തുക',
+       'mwe-clip_out' => 'ചലച്ചിത്രശകലം പുറംതള്ളുക',
+       'mwe-no_selected_resource' => '<h3>ഒരു സ്രോതസ്സും തിരഞ്ഞെടുത്തിട്ടില്ല</h3> മാറ്റംവരുത്തുവാൻ ഒരു ചലച്ചിത്രശകലം തിരഞ്ഞെടുക്കുക.',
+       'mwe-error_edit_multiple' => '<h3>നിരവധി സ്രോതസ്സുകൾ തിരഞ്ഞെടുത്തിരിക്കുന്നു</h3> മാറ്റംവരുത്തുവാനായി ഒരു ചലച്ചിത്രശകലം തിരഞ്ഞെടുക്കുക.',
+       'mwe-editor_options' => 'തിരുത്തലുപകരണ ഐച്ഛികങ്ങൾ',
+       'mwe-editor_mode' => 'തിരുത്തലുപകരണ സമ്പ്രദായം',
+       'mwe-simple_editor_desc' => 'ലളിതമായ തിരുത്തലുപകരണം (iMovie രീതി)',
+       'mwe-advanced_editor_desc' => 'വിപുലമായ തിരുത്തലുപകരണം (ഫൈനൽ കട്ട് രീതി)',
+       'mwe-other_options' => 'മറ്റ് ഐച്ഛികങ്ങൾ',
+       'mwe-sequencer_credit_line' => '<a href="http://kaltura.com">Kaltura, Inc.</a>, <a href="http://wikimediafoundation.org/wiki/Home">വിക്കിമീഡിയ ഫൗണ്ടേഷന്റെ</a> പങ്കാളിത്തത്തോടു കൂടി വികസിപ്പിച്ചെടുത്തത് (<a href="#">കൂടുതൽ വിവരങ്ങൾ</a>).',
+       'mwe-loading_txt' => 'ശേഖരിക്കുന്നു ...',
+       'mwe-error_load_lib' => 'പിശക്: ജാവാസ്ക്രിപ്റ്റ് $1 ശേഖരിക്കാൻ കഴിഞ്ഞില്ല അല്ലെങ്കിൽ $2 നിർവ്വചിച്ചിട്ടില്ല',
+       'mwe-apiproxy-setup' => 'എ.പി.ഐ. പ്രോക്സി സജ്ജീകരിക്കുക',
+       'mwe-load-drag-item' => 'വലിച്ചിട്ടത് ശേഖരിക്കുന്നു',
+       'mwe-ok' => 'ശരി',
+       'mwe-cancel' => 'റദ്ദാക്കുക',
+       'mwe-setting-up-proxy' => 'പ്രോക്സി സജ്ജീകരിക്കുന്നു...',
+       'mwe-proxy-not-ready' => 'പ്രോക്സി ക്രമീകരിക്കപ്പെട്ടിട്ടില്ല.',
+       'mwe-please-login' => 'താങ്കൾ $2 സംരംഭത്തിൽ <a target="_new" href="$1">പ്രവേശിച്ചിട്ടില്ല</a> അല്ലങ്കിൽ mwEmbed സജ്ജമാക്കിയിട്ടില്ല. ഈ പ്രശ്നം പരിഹരിച്ച ശേഷം വീണ്ടും ശ്രമിക്കൂ.',
+       'mwe-remember-loging' => 'പൊതു സുരക്ഷാ ഓർമ്മക്കുറിപ്പ്: സൈറ്റിന്റെ വിലാസം അഡ്രസ് ബാറിൽ കാണുകയാണെങ്കിൽ മാത്രം ലോഗിൻ ചെയ്യുക.',
+       'fogg-select_file' => 'പ്രമാണം തിരഞ്ഞെടുക്കുക',
+       'fogg-select_new_file' => 'പുതിയ പ്രമാണം തിരഞ്ഞെടുക്കുക',
+       'fogg-select_url' => 'യു.ആർ.എൽ. തിരഞ്ഞെടുക്കുക',
+       'fogg-save_local_file' => 'ഓഗ് ആയി സേവ് ചെയ്യുക',
+       'fogg-check_for_firefogg' => 'ഫയർഫോഗ് തിരയുന്നു...',
+       'fogg-installed' => 'ഫയർഫോഗ് ഇൻസ്റ്റോൾ ചെയ്തിട്ടുണ്ട്',
+       'fogg-for_improved_uploads' => 'മെച്ചപ്പെടുത്തിയ അപ്‌‌ലോഡുകൾക്കു വേണ്ടി:',
+       'fogg-please_install' => '<a href="$1">ഫയർഫോഗ് ഇൻസ്റ്റോൾ ചെയ്യുക</a>. <a href="http://commons.wikimedia.org/wiki/Commons:Firefogg">ഫയർഫോഗിനെ കുറിച്ചു കൂടുതൽ</a>',
+       'fogg-use_latest_firefox' => 'ദയവായി <a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=firefogg">ഫയർഫോക്സ് 3.5</a> (അല്ലങ്കിൽ ശേഷമുള്ളത്) ആദ്യം ഇൻസ്റ്റോൾ ചെയ്യുക. <i>പിന്നീട് <b>Firefogg</b> അനുബന്ധത്തിനായി ഈ താൾ ഒന്നുകൂടി സന്ദർശിക്കുക.</i>',
+       'fogg-passthrough_mode' => 'താങ്കൾ തിരഞ്ഞെടുത്ത പ്രമാണം ഓഗ് (Ogg) തന്നെയാണ് അല്ലങ്കിൽ വീഡിയോ പ്രമാണം അല്ല',
+       'fogg-transcoding' => 'ചലച്ചിത്രം ഓഗ് ആയി എൻകോഡ് ചെയ്യുന്നു...',
+       'fogg-encoding-done' => 'എൻകോഡിങ് പൂർണ്ണം',
+       'fogg-badtoken' => 'ചീട്ട് അസാധുവാണ്',
+       'fogg-preview' => 'വീഡിയോയുടെ പ്രിവ്യൂ',
+       'fogg-hidepreview' => 'പ്രിവ്യൂ മറയ്ക്കുക',
+       'mwe-imported_from' => '[$2 $3]-യിൽ നിന്ന് $1 ഇറക്കുമതി ചെയ്തിരിക്കുന്നു. കൂടുതൽ വിവരങ്ങൾക്ക് ശരിക്കുമുള്ള [$4 സ്രോതസ്സ് താൾ] കാണുക.',
+       'mwe-stream_title' => '$1 $2 മുതൽ $3 വരെ',
+       'fogg-help-sticky' => 'സഹായം (നിൽക്കാൻ ഞെക്കുക)',
+       'fogg-cg-preset' => 'മുൻനിശ്ചിതം: <strong>$1</strong>',
+       'fogg-cg-meta' => 'ചലച്ചിത്രശകലത്തിനുള്ള മെറ്റഡേറ്റ',
+       'fogg-cg-range' => 'എൻകോഡിങ് പരിധി',
+       'fogg-cg-advVideo' => 'വിപുലമായ ചലച്ചിത്ര എൻകോഡിങ് നിയന്ത്രണങ്ങൾ',
+       'fogg-cg-advAudio' => 'വിപുലമായ ശബ്ദ എൻകോഡിങ് നിയന്ത്രണങ്ങൾ',
+       'fogg-preset-custom' => 'സ്വന്തം സജ്ജീകരണങ്ങൾ',
+       'fogg-webvideo-desc' => 'വെബ് ചലച്ചിത്രം തിയോറ, വോർബിസ് 400 കിലോബിറ്റ്/സെക്കന്റ് 400 ബിന്ദു പരമാവധി വീതി',
+       'fogg-savebandwidth-desc' => 'കുറഞ്ഞ ബാൻഡ്‌‌വിഡ്ത് തിയോറ, വോർബിസ് 164 കിലോബിറ്റ്/സെക്കന്റ് 200ബിന്ദു പരമാവധി വീതി',
+       'fogg-highquality-desc' => 'ഉന്നത നിലവാരത്തിലുള്ള തിയോറ, വോർബിസ്; പരമാവധി വീതി 1080 ബിന്ദു',
+       'fogg-videoQuality-title' => 'ചലച്ചിത്ര ഗുണനിലവാരം',
+       'fogg-starttime-title' => 'തുടങ്ങുന്ന സെക്കന്റ്',
+       'fogg-endtime-title' => 'അവസാനിക്കുന്ന സെക്കന്റ്',
+       'fogg-audioQuality-title' => 'ശബ്ദ ഗുണനിലവാരം',
+       'fogg-videoCodec-title' => 'ചലച്ചിത്ര കോഡെക്',
+       'fogg-videoCodec-help' => 'ചലച്ചിത്രശകലത്തിന്റെ വീഡിയോ കോഡെക് തിരഞ്ഞെടുക്കാൻ ഉപയോഗിക്കുന്നു. ഇപ്പോൾ തിയോറ മാത്രമാണ് പിന്തുണയുള്ളത് <a target="_new" href="http://en.wikipedia.org/wiki/Theora">തിയോറ കോഡെകിനെ കുറിച്ച്</a> കൂടുതൽ വായിക്കുക.',
+       'fogg-audioCodec-title' => 'ശബ്ദ കോഡെക്',
+       'fogg-audioCodec-help' => 'ചലച്ചിത്രശകലത്തിന്റെ ശബ്ദ കോഡെക് തിരഞ്ഞെടുക്കാൻ ഉപയോഗിക്കുന്നു. ഇപ്പോൾ വോർബിസിനു മാത്രമാണ് പിന്തുണയുള്ളത് <a target="_new" href="http://en.wikipedia.org/wiki/Vorbis">വോർബിസ് കോഡെകിനെ കുറിച്ചു</a> കൂടുതൽ വായിക്കുക.',
+       'fogg-width-title' => 'ചലച്ചിത്രത്തിന്റെ വീതി',
+       'fogg-width-help' => 'തന്നിരിക്കുന്ന വീതിയിലേയ്ക്ക് പുനഃക്രമീകരിക്കുക',
+       'fogg-height-title' => 'ചലച്ചിത്രത്തിന്റെ ഉയരം',
+       'fogg-height-help' => 'നൽകുന്ന പൊക്കത്തിനനുസരിച്ച് വലിപ്പം ക്രമീകരിക്കുക.',
+       'fogg-novideo-title' => 'ചലച്ചിത്രം ലഭ്യമല്ല',
+       'fogg-novideo-help' => 'ഔട്ട്പുട്ടിൽ ചലച്ചിത്രം നിഷേധിക്കുക',
+       'fogg-noaudio-title' => 'ശബ്ദം ലഭ്യമല്ല',
+       'fogg-noaudio-help' => 'ഔട്ട്പുട്ടിലെ ശബ്ദം നിഷേധിക്കുക',
+       'fogg-title-title' => 'തലക്കെട്ട്',
+       'fogg-title-help' => 'താങ്കളുടെ ചലച്ചിത്രശകലത്തിന്റെ തലക്കെട്ട്',
+       'fogg-artist-title' => 'സ്രഷ്ടാവിന്റെ പേര്',
+       'fogg-artist-help' => 'ഈ ചലച്ചിത്രശകലത്തിന്റെ സ്രഷ്ടാവ്',
+       'fogg-date-title' => 'തീയതി',
+       'fogg-date-help' => 'ചിത്രീകരണം പുറത്തിറക്കുകയോ സൃഷ്ടിക്കുകയോ ചെയ്ത തീയതി',
+       'fogg-location-title' => 'സ്ഥലം',
+       'fogg-location-help' => 'ചിത്രീകരണം നടന്ന സ്ഥലം',
+       'fogg-organization-title' => 'സംഘടന',
+       'fogg-organization-help' => 'സംഘടനയുടെ പേര് (സ്റ്റുഡിയോ)',
+       'fogg-copyright-title' => 'പകർപ്പവകാശം',
+       'fogg-copyright-help' => 'ഈ ചലച്ചിത്രശകലത്തിന്റെ പകർപ്പവകാശം',
+       'fogg-license-title' => 'അനുമതി',
+       'fogg-license-help' => 'ഈ ചലച്ചിത്രശകലത്തിന്റെ ഉപയോഗാനുമതി (ഒരു ക്രിയേറ്റീവ് കോമൺസ് യൂ.ആർ.എൽ ആയിരിക്കാൻ താത്പര്യപ്പെടുന്നു).',
+       'fogg-contact-title' => 'സമ്പർക്കം',
+       'fogg-contact-help' => 'സമ്പർക്ക കണ്ണി',
+       'mwe-media_search' => 'മീഡിയ തിരച്ചിൽ',
+       'rsd_box_layout' => 'ചതുരപ്പെട്ടി രൂപകല്പന',
+       'rsd_list_layout' => 'പട്ടിക രൂപകല്പന',
+       'rsd_results_desc' => '$1 മുതൽ $2 വരെയുള്ള ഫലങ്ങൾ',
+       'rsd_results_desc_total' => '$3 ഫലങ്ങളിൽ $1 മുതൽ $2 വരെ',
+       'rsd_results_next' => 'അടുത്തത്',
+       'rsd_results_prev' => 'മുൻപത്തേത്',
+       'rsd_no_results' => '<b>$1</b> എന്ന തിരച്ചിലിനു ഫലങ്ങളൊന്നും ലഭ്യമായില്ല',
+       'mwe-upload_tab' => 'അപ്‌‌ലോഡ്',
+       'rsd_layout' => 'രൂപകല്പന:',
+       'rsd_resource_edit' => 'സ്രോതസ്സ് തിരുത്തുക: $1',
+       'mwe-resource_description_page' => 'സ്രോതസ്സിന്റെ വിവരണ താൾ',
+       'mwe-link' => 'കണ്ണി',
+       'rsd_local_resource_title' => 'പ്രാദേശിക സ്രോതസ്സ് തലക്കെട്ട്',
+       'rsd_do_insert' => 'ഉൾപ്പെടുത്തുക',
+       'mwe-cc_title' => 'ക്രിയേറ്റീവ് കോമൺസ്',
+       'mwe-cc_nc_title' => 'വാണിജ്യേതരം',
+       'mwe-cc_nd_title' => 'വ്യുൽപ്പന്ന കൃതികളൊന്നുമില്ല',
+       'mwe-cc_pd_title' => 'പൊതു സഞ്ചയം',
+       'mwe-unknown_license' => 'അപരിചിതമായ അനുമതി',
+       'mwe-results_from' => '<a href="$1" target="_new" >$2</a> മുതലുള്ള ഫലങ്ങൾ',
+       'mwe-your_recent_uploads' => '$1 പദ്ധതിയിൽ താങ്കൾ സമീപകാലത്ത് അപ്‌‌ലോഡ് ചെയ്തവ',
+       'mwe-upload_a_file' => '$1 പദ്ധതിയിലേയ്ക്ക് പുതിയ പ്രമാണം അപ്‌‌ലോഡ് ചെയ്യുക',
+       'mwe-resource_page_desc' => 'സ്രോതസ്സ് താളിന്റെ വിവരണം:',
+       'mwe-edit_resource_desc' => 'വിക്കി എഴുത്തിലുള്ള സ്രോതസ്സ് വിവരണം തിരുത്തുക:',
+       'mwe-local_resource_title' => 'പ്രാദേശിക സ്രോതസ്സ് തലക്കെട്ട്:',
+       'mwe-watch_this_page' => 'ഈ താൾ ശ്രദ്ധിക്കുക',
+       'mwe-do_import_resource' => 'സ്രോതസ്സ് ഇറക്കുമതി ചെയ്യുക',
+       'mwe-update_preview' => 'പ്രിവ്യൂ പുതുക്കുക',
+       'mwe-cancel_import' => 'ഇറക്കുമതി റദ്ദാക്കുക',
+       'mwe-importing_asset' => 'മുതൽ ഇറക്കുമതി ചെയ്യുന്നു',
+       'mwe-preview_insert_resource' => 'സ്രോതസ് ഉൾപ്പെടുത്തുമ്പോൾ പ്രിവ്യൂ കാട്ടുക: $1',
+       'mwe-checking-resource' => 'സ്രോതസ്സുകൾക്കായി പരിശോധിക്കുക',
+       'mwe-resource-needs-import' => '$1 എന്ന സ്രോതസ്സ് $2 പദ്ധതിയിലേയ്ക്ക് ഇറക്കുമതി ചെയ്യേണ്ടതാണ്',
+       'mwe-ftype-svg' => 'SVG വെക്റ്റർ പ്രമാണം',
+       'mwe-ftype-jpg' => 'JPEG ചിത്ര പ്രമാണം',
+       'mwe-ftype-png' => 'PNG ചിത്ര പ്രമാണം',
+       'mwe-ftype-oga' => 'ഓഗ് ശബ്ദ പ്രമാണം',
+       'mwe-ftype-ogg' => 'ഓഗ് വീഡിയോ പ്രമാണം',
+       'mwe-ftype-unk' => 'അജ്ഞാതമായ തരം പ്രമാണം',
+       'rsd-wiki_commons-title' => 'വിക്കിമീഡിയ കോമൺസ്',
+       'rsd-wiki_commons' => 'വിക്കിമീഡിയ കോമൺസ്, സ്വതന്ത്രാനുമതിയുള്ള വിദ്യാഭ്യാസ മീഡിയ ഉള്ളടക്കങ്ങളുടെ (ചിത്രങ്ങൾ, ശബ്ദ, ചലച്ചിത്ര ശകലങ്ങൾ) സഞ്ചയിക',
+       'rsd-this_wiki-title' => 'ഈ വിക്കി',
+       'rsd-this_wiki-desc' => 'പ്രാദേശിക വിക്കി ഇൻസ്റ്റോൾ',
+       'rsd-archive_org-desc' => 'ഇന്റർനെറ്റ് സഞ്ചയിക, സാംസ്കാരിക കലകളുടെ ശാല',
+       'rsd-flickr-desc' => 'Flickr.com, ഓൺലൈനായി ചിത്രങ്ങൾ പങ്ക് വെയ്ക്കാനുള്ള സൈറ്റ്',
+       'mwe-select_file' => 'പ്രമാണം തിരഞ്ഞെടുക്കുക',
+       'mwe-more_licence_options' => 'കൂടുതൽ അനുമതികൾ തിരഞ്ഞെടുക്കാൻ, സാധാരണ <a href="$1">അപ്‌‌ലോഡ് താൾ</a> കാണുക',
+       'mwe-select_ownwork' => 'ഞാൻ പൂർണ്ണമായും എന്റേതായ കൃതിയാണ് അപ്‌‌ലോഡ് ചെയ്യുന്നത്, അതിന്റെ ഉപയോഗാനുമതി ഇപ്രകാരമാണ്:',
+       'mwe-licence_cc-by-sa' => 'ക്രിയേറ്റീവ് കോമൺസ് ഷെയർ എലൈക്ക്(3.0)',
+       'mwe-upload' => 'പ്രമാണം അപ്‌‌ലോഡ് ചെയ്യുക',
+       'mwe-destfilename' => 'ലക്ഷ്യ പ്രമാണനാമം:',
+       'mwe-summary' => 'ചുരുക്കം',
+       'mwe-error_not_loggedin' => 'താങ്കൾ ലോഗിൻ ചെയ്തിട്ടില്ല, അല്ലെങ്കിൽ അപ്‌ലോഡ് അനുമതി ഇല്ല.',
+       'mwe-watch-this-file' => 'ഈ പ്രമാണം ശ്രദ്ധിക്കുക',
+       'mwe-ignore-any-warnings' => 'അറിയിപ്പുകൾ അവഗണിക്കുക',
+       'mwe-upload-in-progress' => 'അപ്‌‌ലോഡിങ് ചെയ്തുകൊണ്ടിരിക്കുന്നു (ഈ ജാലകം അടയ്ക്കരുത്)',
+       'mwe-uploaded-status' => 'അപ്‌‌ലോഡ് ചെയ്തിരിക്കുന്നു',
+       'mwe-upload-stats-fileprogress' => '$2 എന്നതിൽ $1',
+       'mwe-upload_completed' => 'താങ്കളുടെ അപ്‌‌ലോഡ് പൂർണ്ണമായിരിക്കുന്നു',
+       'mwe-upload_done' => '<a href="$1">താങ്കളുടെ അപ്‌‌ലോഡ് <i>ലഭ്യമായിരിക്കണം</i></a>.',
+       'mwe-upload-unknown-size' => 'വലിപ്പം അറിയില്ല',
+       'mwe-cancel-confim' => 'റദ്ദാക്കണമെന്നു താങ്കൾക്കു തീർച്ചയാണോ?',
+       'mwe-successfulupload' => 'അപ്‌‌ലോഡ് വിജയകരം',
+       'mwe-uploaderror' => 'അപ്‌‌ലോഡിൽ പിശക്',
+       'mwe-uploadwarning' => 'അപ്‌‌ലോഡ് മുന്നറിയിപ്പ്',
+       'mwe-unknown-error' => 'അപരിചിതമായ പിശക്:',
+       'mwe-return-to-form' => 'ഫോമിലേക്ക് തിരിച്ചു പോവുക',
+       'mwe-file-exists-duplicate' => 'താഴെ കൊടുത്തിരിക്കുന്ന പ്രമാണത്തിന്റെ അപരനാണ് ഈ പ്രമാണം:',
+       'mwe-fileexists' => 'ഇതേ പേരിൽ ഒരു പ്രമാണം നിലവിലുണ്ട്. അതിൽ മാറ്റം വരുത്തണോ എന്നു താങ്കൾക്ക് ഉറപ്പില്ലങ്കിൽ ദയവായി <b><tt>$1</tt></b> കാണുക.',
+       'mwe-fileexists-thumb' => '<center><b>നിലവിലുള്ള പ്രമാണം</b></center>',
+       'mwe-ignorewarning' => 'മുന്നറിയിപ്പ് അവഗണിക്കുക, എന്തായാലും പ്രമാണം സേവ് ചെയ്യുക',
+       'mwe-file-thumbnail-no' => '<b><tt>$1</tt></b> എന്നാണു പ്രമാണത്തിന്റെ പേര് ആരംഭിക്കുന്നത്',
+       'mwe-go-to-resource' => 'സ്രോതസ്സ് താളിലേയ്ക്ക് പോവുക',
+       'mwe-upload-misc-error' => 'അപ്‌‌ലോഡിൽ അപരിചിതമായ പിശക്',
+       'mwe-wgfogg_warning_bad_extension' => 'താങ്കൾ പിന്തുണയില്ലാത്ത തരത്തിലുള്ള പ്രമാണമാണ് തിരഞ്ഞെടുത്തിരിക്കുന്നത് (<a href="http://commons.wikimedia.org/wiki/Commons:Firefogg#Supported_File_Types">കൂടുതൽ വിവരങ്ങൾ</a>).',
+       'mwe-upload-multi' => '{{PLURAL:$1|പ്രമാണം|പ്രമാണങ്ങൾ}} അപ്‌‌ലോഡ് ചെയ്യുക',
+       'mwe-review-upload' => 'പ്രമാണ {{PLURAL:$1|അപ്‌‌ലോഡ്|അപ്‌‌ലോഡുകൾ}} സംശോധനം ചെയ്യുക',
+       'mwe-credit-title' => 'തലക്കെട്ട്: $1',
+       'mwe-loading_plugin' => 'പ്ലഗ്ഗിൻ ശേഖരിക്കുന്നു...',
+       'mwe-link_back' => 'പിന്നിലേയ്ക്ക് കണ്ണി സൃഷ്ടിക്കുക',
+       'mwe-add_to_end_of_sequence' => 'അനുവർത്തനത്തിന്  ഒടുവിൽ ചേർക്കുക',
+       'mwe-play_clip' => 'ചലച്ചിത്രശകലം പ്രവർത്തിപ്പിക്കുക',
+       'mwe-pause_clip' => 'ചലച്ചിത്രശകലം തത്കാലം നിർത്തുക',
+       'mwe-volume_control' => 'ശബ്ദ നിയന്ത്രണം',
+       'mwe-player_options' => 'പ്ലേയർ ഐച്ഛികങ്ങൾ',
+       'mwe-closed_captions' => 'അടയ്ക്കപ്പെട്ട തലക്കുറികൾ',
+       'mwe-player_fullscreen' => 'പൂർണ്ണസ്ക്രീൻ',
+       'mwe-next_clip_msg' => 'അടുത്ത ചലച്ചിത്രശകലം പ്രവർത്തിപ്പിക്കുക',
+       'mwe-prev_clip_msg' => 'മുൻ ചലച്ചിത്രശകലം പ്രവർത്തിപ്പിക്കുക',
+       'mwe-current_clip_msg' => 'ഈ ചലച്ചിത്രശകലം പ്രവർത്തിപ്പിക്കുന്നതു തുടരുക',
+       'mwe-seek_to' => '$1 നോക്കുക',
+       'mwe-paused' => 'തത്കാലം നിർത്തിവെച്ചിരിക്കുന്നു',
+       'mwe-download_segment' => 'തിരഞ്ഞെടുത്തത് ഡൗൺലോഡ് ചെയ്യുക:',
+       'mwe-download_full' => 'പൂർണ്ണ ചലച്ചിത്ര പ്രമാണം ഡൗൺലോഡ് ചെയ്യുക:',
+       'mwe-download_right_click' => 'ഡൗൺലോഡ് ചെയ്യുവാനായി, റൈറ്റ് ക്ലിക്ക് ചെയ്തശേഷം <i>Save link as...</i> എന്നതുപയോഗിക്കുക',
+       'mwe-download_clip' => 'ചലച്ചിത്രം ഡൗൺലോഡ് ചെയ്യുക',
+       'mwe-download_text' => 'എഴുത്ത് ഡൗൺലോഡ് ചെയ്യുക (<a style="color:white" title="cmml" href="http://wiki.xiph.org/index.php/CMML">CMML</a> എക്സ്.എം.എൽ.):',
+       'mwe-download' => 'ഡൗൺലോഡ് ചെയ്യുക',
+       'mwe-share' => 'പങ്ക് വെയ്ക്കുക',
+       'mwe-credits' => 'കടപ്പാടുകൾ',
+       'mwe-clip_linkback' => 'ചലച്ചിത്രശകലത്തിന്റെ സ്രോതസ് താൾ',
+       'mwe-chose_player' => 'ചലച്ചിത്ര പ്ലേയർ തിരഞ്ഞെടുക്കുക',
+       'mwe-share_this_video' => 'ഈ ചലച്ചിത്രം പങ്ക് വെയ്ക്കുക',
+       'mwe-video_credits' => 'ചലച്ചിത്രത്തിനുള്ള കടപ്പാടുകൾ',
+       'mwe-close_btn' => 'അടയ്ക്കുക',
+       'mwe-ogg-player-vlc-player' => 'വി.എൽ.സി. പ്ലേയർ',
+       'mwe-ogg-player-videoElement' => 'സ്വതവേയുള്ള ഓഗ് ചലച്ചിത്രം',
+       'mwe-ogg-player-oggPlugin' => 'ജെനറിക് ഓഗ് പ്ലഗിൻ',
+       'mwe-ogg-player-quicktime-mozilla' => 'ക്വിക്ക്റ്റൈം പ്ലഗിൻ',
+       'mwe-ogg-player-quicktime-activex' => 'ക്വിക്ക്റ്റൈം ആക്റ്റീവ്‌‌എക്സ്',
+       'mwe-ogg-player-cortado' => 'ജാവ കോർറ്റാഡോ',
+       'mwe-ogg-player-flowplayer' => 'ഫ്ലോപ്ലേയർ',
+       'mwe-ogg-player-kplayer' => 'കൽറ്റ്യൂറ പ്ലേയർ',
+       'mwe-ogg-player-selected' => '(തിരഞ്ഞെടുത്തവ)',
+       'mwe-ogg-player-omtkplayer' => 'ഓ‌‌എംറ്റികെ ഫ്ലാഷ് വോർബിസ്',
+       'mwe-generic_missing_plugin' => 'താങ്കളുടെ ബ്രൗസറിനു താഴെ പറയുന്നവ പ്രവർത്തിപ്പിക്കാനുള്ള പിന്തുണയുണ്ടെന്നു തോന്നുന്നില്ല: <b>$1</b><br /><a href="http://commons.wikimedia.org/wiki/Commons:Media_help">പ്ലേബാക്ക് സൗകര്യങ്ങൾ</a> എന്ന താൾ സന്ദർശിച്ച് ഒരു പ്ലേയർ ഡൗൺലോഡ് ചെയ്യുക.<br />',
+       'mwe-for_best_experience' => 'മെച്ചപ്പെട്ട ചലച്ചിത്രാസ്വാദനത്തിനു ഞങ്ങൾ നിർദ്ദേശിക്കുന്നത്:<br /><b><a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=mwEmbed">ഫയർഫോക്സ് 3.5</a>.</b>',
+       'mwe-do_not_warn_again' => 'ഇപ്പോൾ ഒഴിവാക്കുക.',
+       'mwe-playerselect' => 'പ്ലേയേഴ്സ്',
+       'mwe-read_before_embed' => 'ഉൾപ്പെടുത്തുന്നതിനു മുമ്പ് <a href="http://mediawiki.org/wiki/Security_Notes_on_Remote_Embedding" target="_new">ഇത് വായിക്കുക</a>.',
+       'mwe-embed_site_or_blog' => 'ഒരു താളിൽ ഉൾപ്പെടുത്തുക',
+       'mwe-related_videos' => 'ബന്ധപ്പെട്ട ചലച്ചിത്രങ്ങൾ',
+       'mwe-seeking' => 'നോക്കുന്നു',
+       'mwe-copy-code' => 'കോഡ് പകർത്തുക',
+       'mwe-video-h264' => 'എച്ച്.264 ചലച്ചിത്രം',
+       'mwe-video-flv' => 'ഫ്ലാഷ് ചലച്ചിത്രം',
+       'mwe-video-ogg' => 'ഓഗ് ചലച്ചിത്രം',
+       'mwe-video-audio' => 'ഓഗ് ശബ്ദപ്രമാണം',
+);
+
+/** Dutch (Nederlands)
+ * @author McDutchie
+ * @author Naudefj
+ * @author SPQRobin
+ * @author Siebrand
+ */
+$messages['nl'] = array(
+       'mwe-crop' => 'Afbeelding uitsnijden',
+       'mwe-apply_crop' => 'Uitsnede op afbeelding toepassen',
+       'mwe-reset_crop' => 'Uitsnede verwijderen',
+       'mwe-insert_image_page' => 'Aan pagina toevoegen',
+       'mwe-insert_into_sequence' => 'Aan reeks toevoegen',
+       'mwe-preview_insert' => 'Voorvertoning',
+       'mwe-cancel_image_insert' => 'Toevoegen annuleren',
+       'mwe-sc_fileopts' => 'Clipdetails bewerken',
+       'mwe-sc_inoutpoints' => 'In-uit-punten instellen',
+       'mwe-sc_overlays' => 'Overlays',
+       'mwe-sc_audio' => 'Audioinstellingen',
+       'mwe-sc_duration' => 'Duur',
+       'mwe-template_properties' => 'Eigenschappen van sjabloon',
+       'mwe-custom_title' => 'Aangepaste beschijving',
+       'mwe-edit_properties' => 'Eigenschappen bewerken',
+       'mwe-other_properties' => 'Overige eigenschappen',
+       'mwe-resource_page' => 'Bronpagina:',
+       'mwe-set_in_out_points' => 'In- en uitpunten instellen',
+       'mwe-start_time' => 'Starttijd',
+       'mwe-end_time' => 'Eindtijd',
+       'mwe-preview_inout' => 'In- en uitpunten weergeven',
+       'mwe-edit-tools' => 'Bewerkingshulpmiddelen',
+       'mwe-inline-description' => 'Beschrijving',
+       'mwe-edit-video-tools' => 'Videobewerkingshulpmiddelen:',
+       'mwe-duration' => 'Duur:',
+       'mwe-upload-subs-file' => 'Ondertitel uploaden',
+       'mwe-add-subs-file-title' => 'Te uploaden ondertitel selecteren',
+       'mwe-error-only-srt' => 'U mag alleen SRT-bestanden uploaden.',
+       'mwe-watch-video' => 'Video bekijken',
+       'mwe-select-other-language' => 'Andere taal selecteren',
+       'mwe-saving' => 'bezig met opslaan...',
+       'mwe-select_transcript_set' => 'Ondertitels selecteren',
+       'mwe-auto_scroll' => 'automatisch scrollen',
+       'mwe-close' => 'sluiten',
+       'mwe-improve_transcript' => 'Verbeteren',
+       'mwe-no_text_tracks_found' => 'Er zijn geen tekstsporen aangetroffen',
+       'mwe-add-edit-subs' => 'Ondertitels toevoegen/bewerken',
+       'mwe-transition_in' => 'Overgangen',
+       'mwe-transition_out' => 'Overgang einde',
+       'mwe-effects' => 'Effecten',
+       'mwe-remove_transition' => 'Overgang verwijderen',
+       'mwe-edit_transin' => 'Overgang in clip bewerken',
+       'mwe-edit_transout' => 'Overgang uit clip verwijderen',
+       'mwe-add-transition' => 'Overgang toevoegen',
+       'mwe-menu_clipedit' => 'Media bewerken',
+       'mwe-menu_transition' => 'Overgangseffecten',
+       'mwe-menu_cliplib' => 'Media toevoegen',
+       'mwe-menu_resource_overview' => 'Bronnenoverzicht',
+       'mwe-menu_options' => 'Instellingen',
+       'mwe-loading_timeline' => 'Bezig met het laden van de tijdlijn ...',
+       'mwe-loading_user_rights' => 'Bezig met laden van gebruikersrechten ...',
+       'mwe-no_edit_permissions' => 'U hebt geen rechten om wijzigingen aan deze reeks op te slaan',
+       'mwe-edit_clip' => 'Clip bewerken',
+       'mwe-edit_save' => 'Wijzigingen aan de reeks opslaan',
+       'mwe-saving_wait' => 'Bezig met opslaan. Even geduld, alstublieft.',
+       'mwe-save_done' => 'Opslaan voltooid.',
+       'mwe-edit_cancel' => 'Bewerken van de reeks annuleren',
+       'mwe-edit_cancel_confirm' => 'Weet u zeker dat u uw bewerking wilt afbreken? Alle wijzigingen worden ongedaan gemaakt.',
+       'mwe-zoom_in' => 'Vergroten',
+       'mwe-zoom_out' => 'Verkleinen',
+       'mwe-cut_clip' => 'Clips uitsnijden',
+       'mwe-expand_track' => 'Spoor uitklappen',
+       'mwe-collapse_track' => 'Spoor inklappen',
+       'mwe-play_from_position' => 'Afspelen vanaf positie',
+       'mwe-pixle2sec' => 'pixels naar seconden',
+       'mwe-rmclip' => 'Clip verwijderen',
+       'mwe-clip_in' => 'clip toevoegen',
+       'mwe-clip_out' => 'clip verwijderen',
+       'mwe-no_selected_resource' => '<h3>Er is geen bestand geselecteerd</h3>
+Selecteer een te bewerken clip.',
+       'mwe-error_edit_multiple' => '<h3>Er zijn meerdere bestanden geselecteerd</h3>
+Selecteer één te bewerken clip.',
+       'mwe-editor_options' => 'Editorinstellingen',
+       'mwe-editor_mode' => 'Bewerkingsmodus',
+       'mwe-simple_editor_desc' => 'eenvoudige editor (iMovie-stijl)',
+       'mwe-advanced_editor_desc' => 'uitgebreide editor (Final Cut-stijl)',
+       'mwe-other_options' => 'Ander opsies',
+       'mwe-contextmenu_opt' => "Contextafhankelijke menu's inschakelen",
+       'mwe-sequencer_credit_line' => 'Ontwikkeld door <a href="http://kaltura.com">Kaltura, Inc.</a> in samenwerking met de <a href="http://wikimediafoundation.org/wiki/Home">Wikimedia Foundation</a> (<a href="#">meer informatie</a>).',
+       'mwe-loading_txt' => 'bezig met laden ...',
+       'mwe-error_load_lib' => 'Fout: JavaScript $1 kon niet opgehaald worden of definieert $2 niet',
+       'mwe-loading-add-media-wiz' => 'Bezig met het laden van de Wizard media toevoegen',
+       'mwe-apiproxy-setup' => 'Bezig met het opzetten van een API-proxy',
+       'mwe-load-drag-item' => 'Bezig met het laden van het gesleepte bestand',
+       'mwe-ok' => 'OK',
+       'mwe-cancel' => 'Annuleren',
+       'mwe-setting-up-proxy' => 'Bezig met het opzetten van een proxy...',
+       'mwe-re-try' => 'API-verzoek opnieuw uitvoeren',
+       'mwe-re-trying' => 'Bezig met het opnieuw uitvoeren van het API-verzoek...',
+       'mwe-proxy-not-ready' => 'De proxy is niet ingesteld',
+       'mwe-please-login' => 'U bent niet <a target="_new" href="$1">aangemeld</a> by $2 of mwEmbed is niet ingeschakeld. Los het probleem op, en voer het verzoek daarna opnieuw uit.',
+       'mwe-remember-loging' => 'Algemene beveiligingswaarschuwing: meld u zich alleen aan bij websites waarvan het adres in de adresbalk overeenkomt met het webadres van de site.',
+       'fogg-select_file' => 'Bestand selecteren',
+       'fogg-select_new_file' => 'Kies nuwe lêer',
+       'fogg-select_url' => 'URL selecteren',
+       'fogg-save_local_file' => 'Ogg opslaan',
+       'fogg-check_for_firefogg' => 'Firefogg aan het controleren ...',
+       'fogg-installed' => 'Firefogg is geïnstalleerd',
+       'fogg-for_improved_uploads' => 'Voor verbeterde uploads:',
+       'fogg-please_install' => '<a href="$1">Installeer Firefogg</a>. Meer <a href="http://commons.wikimedia.org/wiki/Commons:Firefogg">over Firefogg</a>',
+       'fogg-use_latest_firefox' => 'Installeer alstublieft eerst <a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=firefogg">Firefox 3.5</a> (of een latere versie).
+<i>Kom daarna terug naar deze pagina om de uitbreiding <b>Firefogg</b> te installeren.</i>',
+       'fogg-passthrough_mode' => 'Het geselecteerde bestand is al een Ogg-bestand of geen videobestand',
+       'fogg-transcoding' => 'Bezig met het converteren van video naar Ogg',
+       'fogg-encoding-done' => 'Converteren is afgerond',
+       'fogg-badtoken' => 'Het token is niet geldig',
+       'fogg-preview' => 'Voorvertoning bekijken',
+       'fogg-hidepreview' => 'Voorvertoning verbergen',
+       'mwe-imported_from' => '$1 is geïmporteerd van [$2 $3]. Meer informatie is te vinden op de [$4 originele beschrijvingspagina].',
+       'mwe-stream_title' => '$1 $2 tot $3',
+       'fogg-help-sticky' => 'Help (klik om te laten staan)',
+       'fogg-cg-preset' => 'Instellingen: <strong>$1</strong>',
+       'fogg-cg-quality' => 'Basisinstellingen voor kwaliteit en resolutie',
+       'fogg-cg-meta' => 'Metadata voor de clip',
+       'fogg-cg-range' => 'Te coderen selectie',
+       'fogg-cg-advVideo' => 'Gevorderde instellingen voor videocodering',
+       'fogg-cg-advAudio' => 'Gevorderde instellingen voor audiocodering',
+       'fogg-preset-custom' => 'Aangepaste instellingen',
+       'fogg-webvideo-desc' => 'Webvideo Theora, Vorbis 400 kbit/s en 400px maximale breedte',
+       'fogg-savebandwidth-desc' => 'Lage bandbreedte Theora, Vorbis 164 kbit/s en 200px maximale breedte',
+       'fogg-highquality-desc' => 'Hoge kwaliteit Theora, Vorbis 1080px maximale breedte',
+       'fogg-videoQuality-title' => 'Videokwaliteit',
+       'fogg-videoQuality-help' => 'Gebruikt om de <i>visuele kwaliteit</i> van de te coderen video in te stellen. Deze instelling wordt niet gebruikt als u hieronder bij de geavanceerde instellingen de bitsnelheid instelt.',
+       'fogg-starttime-title' => 'Startseconde',
+       'fogg-starttime-help' => 'Alleen coderen vanaf tijd in seconden',
+       'fogg-endtime-title' => 'Stopseconde',
+       'fogg-endtime-help' => 'Alleen coderen tot tijd in seconden',
+       'fogg-audioQuality-title' => 'Audiokwaliteit',
+       'fogg-audioQuality-help' => 'Gebruikt om de <i>geluidskwaliteit</i> van de te coderen audio in te stellen. Deze instelling wordt niet gebruikt als u hieronder bij de geavanceerde instellingen de bitsnelheid instelt.',
+       'fogg-videoCodec-title' => 'Videocodec',
+       'fogg-videoCodec-help' => 'Gebruikt om de videocodec voor de clip in te stellen. Op het moment wordt alleen Theora ondersteund. Meer over de <a target="_new" href="http://nl.wikipedia.org/wiki/Theora_%28compressieformaat%29">Theora-codec</a>.',
+       'fogg-audioCodec-title' => 'Audiocodec',
+       'fogg-audioCodec-help' => 'Gebruikt om de audiocodec voor de clip in te stellen. Op het moment wordt alleen Vorbis ondersteund. Meer over de <a target="_new" href="http://nl.wikipedia.org/wiki/Ogg_Vorbis">Vorbis-codec</a>.',
+       'fogg-width-title' => 'Breedte video',
+       'fogg-width-help' => 'Naar de opgegeven breedte aanpassen.',
+       'fogg-height-title' => 'Hoogte video',
+       'fogg-height-help' => 'Naar de opgegeven hoogte aanpassen.',
+       'fogg-videoBitrate-title' => 'Bitsnelheid video',
+       'fogg-videoBitrate-help' => 'De bitsnelheid van de video stelt de bitsnelheid van de video in (in kbit/s)',
+       'fogg-twopass-title' => 'Variabele bitsnelheid',
+       'fogg-twopass-help' => 'Het coderen met variabele bitsnelheid maakt een meer constante kwaliteit mogelijk door het videobestand twee keer te verwerken.',
+       'fogg-framerate-title' => 'Beelden per seconde',
+       'fogg-framerate-help' => 'Het aantal beelden per seconde in de video. Meer over <a target="_new" href="http://nl.wikipedia.org/wiki/Beelden_per_seconde">beelden per seconde</a>.',
+       'fogg-aspect-title' => 'Beeldverhouding',
+       'fogg-aspect-help' => 'Beeldverhouding van de video kan 4:3 of 16:9 zijn. Meer over <a target="_new" href="http://nl.wikipedia.org/wiki/Aspect_ratio">beeldverhouding</a>.',
+       'fogg-keyframeInterval-title' => 'Keyframe-interval',
+       'fogg-keyframeInterval-help' => 'De keyframe-interval in beelden. De meeste codecs dwingen keyframes af als het verschil tussen de beelden groter is dan de gecodeerde grootte van het keyframe. Meer over <a href="http://en.wikipedia.org/wiki/I-frame">keyframes</a> (Engels).',
+       'fogg-denoise-title' => 'Ruisfilter',
+       'fogg-denoise-help' => 'Ruis verwijderen uit de videoinvoer. Meer over <a href="http://en.wikipedia.org/wiki/Video_denoising">ruis verwijderen</a> (Engels).',
+       'fogg-novideo-title' => 'Geen video',
+       'fogg-novideo-help' => 'video uitschakelen in de uitvoer',
+       'fogg-audioBitrate-title' => 'Bitsnelheid audio',
+       'fogg-samplerate-title' => 'Audiobemonsteringsfrequentie',
+       'fogg-samplerate-help' => 'bemonsteringsfrequentie van de uitvoer instellen (in Hz).',
+       'fogg-noaudio-title' => 'Geen audio',
+       'fogg-noaudio-help' => 'audio uitschakelen in de uitvoer',
+       'fogg-title-title' => 'Naam',
+       'fogg-title-help' => 'Een naam voor uw clip',
+       'fogg-artist-title' => 'Naam maker',
+       'fogg-artist-help' => 'De maker van deze clip',
+       'fogg-date-title' => 'Datum',
+       'fogg-date-help' => 'De datum waarop het materiaal is gemaakt of vrijgegeven',
+       'fogg-location-title' => 'Locatie',
+       'fogg-location-help' => 'De locatie van de opname',
+       'fogg-organization-title' => 'Organisatie',
+       'fogg-organization-help' => 'Naam van organisatie/studio',
+       'fogg-copyright-title' => 'Auteursrechten',
+       'fogg-copyright-help' => 'De auteursrechten van de clip',
+       'fogg-license-title' => 'Licentie',
+       'fogg-license-help' => 'De licentie van de clip (bij voorkeur een URL naar Creative Commons).',
+       'fogg-contact-title' => 'Contact',
+       'fogg-contact-help' => 'Verwijzing om contact op te nemen',
+       'mwe-add_media_wizard' => 'Wizard media toevoegen',
+       'mwe-media_search' => 'Media zoeken',
+       'rsd_box_layout' => 'Weergeven als kader',
+       'rsd_list_layout' => 'Weergeven als lijst',
+       'rsd_results_desc' => 'Resultaten $1 tot $2',
+       'rsd_results_desc_total' => 'Resultaten $1 tot $2 van $3',
+       'rsd_results_next' => 'volgende',
+       'rsd_results_prev' => 'vorige',
+       'rsd_no_results' => 'Geen zoekresultaten voor <b>$1</b>',
+       'mwe-upload_tab' => 'Uploaden',
+       'rsd_layout' => 'Vormgeving:',
+       'rsd_resource_edit' => 'Bron bewerken: $1',
+       'mwe-resource_description_page' => 'Pagina met bronbeschrijving',
+       'mwe-link' => 'verwijzing',
+       'rsd_local_resource_title' => 'Lokale bestandsnaam',
+       'rsd_do_insert' => 'Toevoegen',
+       'mwe-cc_title' => 'Creative Commons',
+       'mwe-cc_by_title' => 'Naamsvermelding',
+       'mwe-cc_nc_title' => 'Geen Commercieel Gebruik',
+       'mwe-cc_nd_title' => 'Geen afgeleide werken',
+       'mwe-cc_sa_title' => 'Gelijk Delen',
+       'mwe-cc_pd_title' => 'Publiek Domein',
+       'mwe-unknown_license' => 'Onbekende licentie',
+       'mwe-no_import_by_url' => 'Deze gebruiker of wiki kan <b>geen</b> bestanden importeren via een URL.<p>Moet u zich nog aanmelden?</p><p>Hebt u het recht "upload_by_url"?<br />Is voor de wiki <a href="http://www.mediawiki.org/wiki/Manual:$wgAllowCopyUploads">$wgAllowCopyUploads</a> ingeschakeld?</p>',
+       'mwe-results_from' => 'Resultaten van <a href="$1" target="_new" >$2</a>',
+       'mwe-missing_desc_see_source' => 'De beschrijving mist. Help met beschrijven met behulp van de [$1 bron].',
+       'rsd_config_error' => 'Er is een fout in de instellingen van de Wizard media toevoegen: $1',
+       'mwe-your_recent_uploads' => 'Uw recente uploads naar $1',
+       'mwe-upload_a_file' => 'Nieuw bestand uploaden naar $1',
+       'mwe-resource_page_desc' => 'Beschrijving:',
+       'mwe-edit_resource_desc' => 'Bronbeschrijving van het wikibestand wijzigen:',
+       'mwe-local_resource_title' => 'Lokale naam:',
+       'mwe-watch_this_page' => 'Deze pagina volgen',
+       'mwe-do_import_resource' => 'Bestand importeren',
+       'mwe-update_preview' => 'Voorvertoning bijwerken',
+       'mwe-cancel_import' => 'Importeren annuleren',
+       'mwe-importing_asset' => 'Bezig met het importeren van het bestand',
+       'mwe-preview_insert_resource' => 'Invoegen van bronbestand weergeven: $1',
+       'mwe-checking-resource' => 'Bezig met controle van bronbestand',
+       'mwe-resource-needs-import' => 'Het bronbestand $1 moet geïmporteerd worden in $2',
+       'mwe-ftype-svg' => 'SVF vectorbestand',
+       'mwe-ftype-jpg' => 'JPEG afbeeldingsbestand',
+       'mwe-ftype-png' => 'PNG afbeeldingsbestand',
+       'mwe-ftype-oga' => 'Ogg audiobestand',
+       'mwe-ftype-ogg' => 'Ogg videobestand',
+       'mwe-ftype-unk' => 'Onbekend bestandsformaat',
+       'rsd-wiki_commons-title' => 'Wikimedia Commons',
+       'rsd-wiki_commons' => 'Wikimedia Commons is een archief met vrij gelicenseerde educatieve media (afbeeldingen, geluid en video)',
+       'rsd-this_wiki-title' => 'Deze wiki',
+       'rsd-this_wiki-desc' => 'De lokale wiki-installatie',
+       'rsd-archive_org-desc' => 'Het Internet Archive, een digitale bibliotheek met culturele zaken',
+       'rsd-flickr-desc' => "Flickr.com, een website waar u foto's kunt delen",
+       'rsd-metavid-desc' => 'Metavid.org, een gemeenschapsarchief met de handelingen van de Amerikaanse Senaat',
+       'mwe-select_file' => 'Bestand selecteren',
+       'mwe-more_licence_options' => 'Gebruik de <a href="$1">reguliere uploadpagina</a> voor meer licentiemogelijkheden',
+       'mwe-select_ownwork' => 'Ik upload mijn eigen werk onder de volgende licentie:',
+       'mwe-licence_cc-by-sa' => 'Creative Commons Gelijk Delen (3.0)',
+       'mwe-upload' => 'Bestand uploaden',
+       'mwe-destfilename' => 'Nieuwe naam:',
+       'mwe-summary' => 'Beschrijving',
+       'mwe-error_not_loggedin' => 'u bent niet aangemeld of hebt geen uploadrechten.',
+       'mwe-watch-this-file' => 'Dit bestand volgen',
+       'mwe-ignore-any-warnings' => 'Waarschuwingen negeren',
+       'mwe-upload-transcode-in-progress' => 'Bezig met het converteren en uploaden (sluit dit venster niet)',
+       'mwe-upload-in-progress' => 'De upload wordt uitgevoerd - sluit dit venster niet',
+       'mwe-upload-transcoded-status' => 'Geconverteerd',
+       'mwe-uploaded-status' => 'De upload is afgerond',
+       'mwe-upload-stats-fileprogress' => '$1 van $2',
+       'mwe-upload_completed' => 'Uw upload is afgerond',
+       'mwe-upload_done' => '<a href="$1">Uw upload <i>is te bekijken</i></a>.',
+       'mwe-upload-unknown-size' => 'Onbekende grootte',
+       'mwe-cancel-confim' => 'Weet u zeker dat u wilt annuleren?',
+       'mwe-successfulupload' => 'Uploaden voltooid',
+       'mwe-uploaderror' => 'Er is een fout opgetreden bij het uploaden',
+       'mwe-uploadwarning' => 'Er is een waarschuwing gegeven bij het uploaden',
+       'mwe-unknown-error' => 'Er is een onbekende fout opgetreden:',
+       'mwe-return-to-form' => 'Terug naar het formulier',
+       'mwe-file-exists-duplicate' => 'Dit bestand is hetzelfde als het volgende bestand:',
+       'mwe-fileexists' => 'Er bestaat al een bestand met deze naam. Controleer <b><tt>$1</tt></b> als u niet zeker weet of u het huidige bestand wilt overschrijven.',
+       'mwe-fileexists-thumb' => '<center><b>Bestaande afbeelding</b></center>',
+       'mwe-ignorewarning' => 'Deze waarschuwing negeren en het bestand toch opslaan',
+       'mwe-file-thumbnail-no' => 'De bestandsnaam begint met <b><tt>$1</tt></b>',
+       'mwe-go-to-resource' => 'Naar de bronpagina teruggaan',
+       'mwe-upload-misc-error' => 'Er is een onbekende uploadfout opgetreden',
+       'mwe-wgfogg_warning_bad_extension' => 'U hebt een bestand met een extensie die niet wordt ondersteund geselecteerd (<a href="http://commons.wikimedia.org/wiki/Commons:Firefogg#Supported_File_Types">meer informatie</a>).',
+       'mwe-upload-multi' => '{{PLURAL:$1|Bestand|Bestanden}} uploaden',
+       'mwe-review-upload' => '{{PLURAL:$1|Bestandsupload|Bestandsuploads}} controleren',
+       'mwe-loading_plugin' => 'bezig met het laden van de uitbreiding...',
+       'mwe-select_playback' => 'Afspeelinstellingen instellen',
+       'mwe-link_back' => 'Terugverwijzen',
+       'mwe-error_swap_vid' => 'Fout: mv_embed kon de videotag voor de mv_embed-interface niet wisselen',
+       'mwe-add_to_end_of_sequence' => 'Aan het einde van de reeks toevoegen',
+       'mwe-missing_video_stream' => 'Het videobestand voor deze stream is niet aanwezig',
+       'mwe-play_clip' => 'Clip afspelen',
+       'mwe-pause_clip' => 'Clip pauzeren',
+       'mwe-volume_control' => 'Volumebeheer',
+       'mwe-player_options' => 'Mediaspelerinstellingen',
+       'mwe-closed_captions' => 'Ondertiteling',
+       'mwe-player_fullscreen' => 'Volledig scherm',
+       'mwe-next_clip_msg' => 'Volgende clip afspelen',
+       'mwe-prev_clip_msg' => 'Vorige clip afspelen',
+       'mwe-current_clip_msg' => 'Doorgaan met het afspelen van deze clip',
+       'mwe-seek_to' => 'Zoeken naar $1',
+       'mwe-paused' => 'gepauzeerd',
+       'mwe-download_segment' => 'Selectie downloaden:',
+       'mwe-download_full' => 'Volledig videobestand downloaden:',
+       'mwe-download_right_click' => 'Klik rechts en selecteer <i>Verwijzing opslaan als...</i> om het bestand te downloaden',
+       'mwe-download_clip' => 'Video downloaden',
+       'mwe-download_text' => 'Tekst downloaden (<a style="color:white" title="cmml" href="http://wiki.xiph.org/index.php/CMML">CMML</a> xml):',
+       'mwe-download' => 'Downloaden',
+       'mwe-share' => 'Delen',
+       'mwe-credits' => 'Vermeldingen',
+       'mwe-clip_linkback' => 'Bronpagina van de clip',
+       'mwe-chose_player' => 'Mediaspeler kiezen',
+       'mwe-share_this_video' => 'Deze video delen',
+       'mwe-video_credits' => 'Naamsvermeldingen video',
+       'mwe-menu_btn' => 'Menu',
+       'mwe-close_btn' => 'Sluiten',
+       'mwe-ogg-player-vlc-player' => 'VLC mediaspeler',
+       'mwe-ogg-player-videoElement' => 'Ogg-video',
+       'mwe-ogg-player-oggPlugin' => 'Algemene Ogg-plugin',
+       'mwe-ogg-player-quicktime-mozilla' => 'QuickTime-plugin',
+       'mwe-ogg-player-quicktime-activex' => 'QuickTime ActiveX',
+       'mwe-ogg-player-cortado' => 'Java Cortado',
+       'mwe-ogg-player-flowplayer' => 'Flowplayer',
+       'mwe-ogg-player-kplayer' => 'Kaltura mediaspeler',
+       'mwe-ogg-player-selected' => '(geselecteerd)',
+       'mwe-ogg-player-omtkplayer' => 'OMTK Flash Vorbis',
+       'mwe-generic_missing_plugin' => 'Uw browser lijkt het volgende bestandstype niet te ondersteunen: <b>$1</b><br />
+Via <a href="http://commons.wikimedia.org/wiki/Commons:Hulp_voor_mediabestanden">afspeelmethoden</a> kunt u een mediaspeler downloaden.<br />',
+       'mwe-for_best_experience' => 'Voor een betere kwaliteitsbeleving adviseren we:<br /><b><a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=mwEmbed">Firefox 3.5</a></b>',
+       'mwe-do_not_warn_again' => 'Niet waarschuwen',
+       'mwe-playerselect' => 'Mediaspelers',
+       'mwe-read_before_embed' => '<a href="http://mediawiki.org/wiki/Security_Notes_on_Remote_Embedding" target="_new">Lees dit</a> voordat u gaat embedden (Engels)!',
+       'mwe-embed_site_or_blog' => 'Toevoegen aan een pagina',
+       'mwe-related_videos' => "Gerelateerde video's",
+       'mwe-seeking' => 'bezig met zoeken',
+       'mwe-copy-code' => 'Code kopiëren',
+       'mwe-credit-title' => 'Naam: $1',
+);
+
+/** Occitan (Occitan)
+ * @author Cedric31
+ * @author McDutchie
+ */
+$messages['oc'] = array(
+       'mwe-crop' => "Retalhar l'imatge",
+       'mwe-apply_crop' => "Aplicar lo retalh a l'imatge",
+       'mwe-reset_crop' => 'Reïnicializar lo retalh',
+       'mwe-insert_image_page' => 'Inserir dins la pagina',
+       'mwe-insert_into_sequence' => 'Inserir dins la sequéncia',
+       'mwe-preview_insert' => "Previsualizar l'insercion",
+       'mwe-cancel_image_insert' => "Anullar l'insercion",
+       'mwe-sc_fileopts' => 'Modificar lo detalh del clip',
+       'mwe-sc_inoutpoints' => "Definir de punts d'entrada-sortida",
+       'mwe-sc_overlays' => 'Revestiments',
+       'mwe-sc_audio' => 'Contraròtle àudio',
+       'mwe-sc_duration' => 'Durada',
+       'mwe-template_properties' => 'Proprietats del modèl',
+       'mwe-custom_title' => 'Títol personalizat',
+       'mwe-edit_properties' => 'Modificar las proprietats',
+       'mwe-other_properties' => 'Autras proprietats',
+       'mwe-resource_page' => 'Pagina de la ressorsa :',
+       'mwe-set_in_out_points' => "Definir de punts d'entrada-sortida",
+       'mwe-start_time' => 'Ora de començament',
+       'mwe-end_time' => 'Ora de fin',
+       'mwe-preview_inout' => "Previsualizar los punts d'entrada-sortida",
+       'mwe-edit-tools' => 'Espleches de modificacion',
+       'mwe-inline-description' => "Descripcion ''inline''",
+       'mwe-edit-video-tools' => 'Espleches de modificacion de las vidèos :',
+       'mwe-duration' => 'Durada :',
+       'mwe-select_transcript_set' => 'Seleccionar los calques',
+       'mwe-auto_scroll' => 'desfilament automatic',
+       'mwe-close' => 'tampar',
+       'mwe-improve_transcript' => 'Melhorar',
+       'mwe-no_text_tracks_found' => 'Cap de traça de tèxte pas trobada',
+       'mwe-transition_in' => 'Transicion entranta',
+       'mwe-transition_out' => 'Transicion sortenta',
+       'mwe-effects' => "Pila d'efièches",
+       'mwe-remove_transition' => 'Suprimir la transicion',
+       'mwe-edit_transin' => 'Modificar la transicion cap al clip',
+       'mwe-edit_transout' => 'Modificar la transicion en defòta del clip',
+       'mwe-menu_clipedit' => 'Modificar lo mèdia',
+       'mwe-menu_transition' => 'Transicions e efièches',
+       'mwe-menu_cliplib' => 'Apondre un mèdia',
+       'mwe-menu_resource_overview' => "Vista d'ensemble de la ressorsa",
+       'mwe-menu_options' => 'Opcions',
+       'mwe-loading_timeline' => 'Cargament de la cronologia ...',
+       'mwe-loading_user_rights' => "Cargament dels dreches d'utilizaire ...",
+       'mwe-no_edit_permissions' => "Avètz pas l'autorizacion de salvar los cambiaments aportats a aquesta sequéncia",
+       'mwe-edit_clip' => 'Modificar lo clip',
+       'mwe-edit_save' => 'Salvar las modificacions de la sequéncia',
+       'mwe-saving_wait' => 'Salvament en cors (pacientatz)',
+       'mwe-save_done' => 'Salvament acabat',
+       'mwe-edit_cancel' => 'Anullar la modificacion de la sequéncia',
+       'mwe-edit_cancel_confirm' => 'Sètz segur que volètz anullar vòstra modificacion ? Los cambiaments seràn perduts.',
+       'mwe-zoom_in' => 'Agrandir',
+       'mwe-zoom_out' => 'Reduire',
+       'mwe-cut_clip' => 'Copar los clips',
+       'mwe-expand_track' => 'Espandir la pista',
+       'mwe-collapse_track' => 'Reduire la pista',
+       'mwe-play_from_position' => 'Legir a partir de la posicion de lectura',
+       'mwe-pixle2sec' => 'pixèls cap a segondas',
+       'mwe-rmclip' => 'Suprimir lo clip',
+       'mwe-clip_in' => 'estacar',
+       'mwe-clip_out' => 'destacar',
+       'mwe-no_selected_resource' => "<h3>Cap de ressorsa pas seleccionada</h3> Seleccionatz un clip per activar l'edicion",
+       'mwe-error_edit_multiple' => '<h3>Mantuna ressorsa seleccionada</h3> Seleccionatz un sol clip per lo modificar',
+       'mwe-editor_options' => "Opcions de l'editor",
+       'mwe-editor_mode' => "Mòde de l'editor",
+       'mwe-simple_editor_desc' => 'editor simple (estil iMovie)',
+       'mwe-advanced_editor_desc' => 'editor avançat (estil Final Cut)',
+       'mwe-other_options' => 'Autras opcions',
+       'mwe-contextmenu_opt' => 'Activar los menuts contextuals',
+       'mwe-sequencer_credit_line' => 'Desvolopat per <a href="http://kaltura.com">Kaltura, Inc.</a> en partenariat amb la <a href="http://wikimediafoundation.org/wiki/Home">Wikimedia Foundation</a> (<a href="#">mai d\'entresenhas</a>).',
+       'mwe-loading_txt' => 'cargament ...',
+       'mwe-error_load_lib' => 'Error : JavaScript $1 a pas pogut èsser trobat o definís pas $2',
+       'mwe-loading-add-media-wiz' => "Cargament de l'assistent d'apondon de mèdia",
+       'mwe-apiproxy-setup' => 'Configuracion del proxy API',
+       'mwe-load-drag-item' => 'Cargament de l’element depausat',
+       'mwe-ok' => 'OK',
+       'mwe-cancel' => 'Anullar',
+       'mwe-setting-up-proxy' => 'Parametratge del proxy...',
+       'mwe-re-try' => 'Tornar ensajar la requèsta API',
+       'mwe-re-trying' => 'Novèla temptativa de requèsta API...',
+       'mwe-proxy-not-ready' => 'Lo proxy es pas configurat',
+       'mwe-please-login' => 'Sètz pas <a target="_new" href="$1">connectat</a> sus $2 o mwEmbed es pas estat activat. Corregissètz lo problèma, puèi ensajatz tornamai vòstra requèsta.',
+       'mwe-remember-loging' => "Rapèl de seguretat : vos connectetz pas a un site internet que quand l’adreça d'aquel site es afichada dins vòstra barra d’adreça.",
+       'fogg-select_file' => 'Seleccionatz un fichièr',
+       'fogg-select_new_file' => 'Seleccionatz un fichièr novèl',
+       'fogg-select_url' => 'Seleccionatz una URL',
+       'fogg-save_local_file' => 'Salvar al format Ogg',
+       'fogg-check_for_firefogg' => 'Verificacion de Firefogg ...',
+       'fogg-installed' => 'Firefogg es installat',
+       'fogg-for_improved_uploads' => 'Per de telecargaments melhorats :',
+       'fogg-please_install' => '<a href="$1">Installer Firefogg</a>. Mai d\'entresenhas <a href="http://commons.wikimedia.org/wiki/Commons:Firefogg">sus Firefogg</a>',
+       'fogg-use_latest_firefox' => 'D\'en primièr, installatz <a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=firefogg">Firefox 3.5</a> (o mai recent). <i>Puèi tornatz sus aquesta pagina per installar l\'extension <b>Firefogg</b>.</i>',
+       'fogg-passthrough_mode' => "Lo fichièr qu'avètz seleccionat es ja al format Ogg o es pas un fichièr vidèo",
+       'fogg-transcoding' => "Encodatge d'una vidèo al format Ogg",
+       'fogg-encoding-done' => 'Encodatge acabat',
+       'fogg-badtoken' => 'Lo geton es pas valid',
+       'fogg-preview' => 'Previsualizar la vidèo',
+       'fogg-hidepreview' => 'Amagar la previsualizacion',
+       'mwe-imported_from' => "$1 a importat dempuèi [$2 $3]. Vejatz la [$4 pagina de la ressorsa] originala per mai d'entresenhas.",
+       'mwe-stream_title' => '$1 $2 cap a $3',
+       'fogg-help-sticky' => 'Ajuda (clicar per manténer)',
+       'fogg-cg-preset' => 'Predefinit : <strong>$1</strong>',
+       'fogg-cg-quality' => 'Qualitat basica e contraròtle de la resolucion',
+       'fogg-cg-meta' => 'Metadonadas pel clip',
+       'fogg-cg-range' => "Portada de l'encodatge",
+       'fogg-cg-advVideo' => "Contraròtles avançats de l'encodatge vidèo",
+       'fogg-cg-advAudio' => "Contraròtles avançats de l'encodatge àudio",
+       'fogg-preset-custom' => 'Paramètres personalizats',
+       'fogg-webvideo-desc' => 'Video web Theroa, Vorbis 400 kbit/s e 400px de largor maximala',
+       'fogg-savebandwith-desc' => 'Theora de benda passanta febla, Vorbis 164 kbit/s e 200px de largor maximala',
+       'fogg-highquality-desc' => 'Theora de nauta qualitat, Vorbis 1080px de largor maximala',
+       'fogg-videoQuality-title' => 'Qualitat vidèo',
+       'fogg-videoQuality-help' => 'Utilizat per definir la <i>qualitat visuala</i> de la vidèo encodada (pas utilizat se definissètz lo debit binari dins los contraròtles avançats çaijós).',
+       'fogg-starttime-title' => 'Segonda de començament',
+       'fogg-starttime-help' => "Encodar solament a partir d'una durada en segondas",
+       'fogg-endtime-title' => 'Segonda de fin',
+       'fogg-endtime-help' => 'Encodar solament cap a una durada en segondas',
+       'fogg-audioQuality-title' => 'Qualitat àudio',
+       'fogg-audioQuality-help' => "Utilizat per definir la <i>qualitat acostica</i> de l'àudio encodat (pas utilizat se definissètz lo debit binari dins los contraròtles avançats çaijós).",
+       'fogg-videoCodec-title' => 'Codec vidèo',
+       'fogg-videoCodec-help' => 'Utilizat per seleccionar lo codec del clip vidèo. Actualament, sol Theora es disponible. Mai d\'entresenhas sul <a target="_new" href="http://oc.wikipedia.org/wiki/Theora">codec Theora</a>.',
+       'fogg-audioCodec-title' => 'Codec àudio',
+       'fogg-audioCodec-help' => 'Utilizat per definir lo codec del clip àudio. Actualament, sol Vorbis es disponible. Mai d\'entresenhas sul <a target="_new" href="http://oc.wikipedia.org/wiki/Vorbis">codec Vorbis</a>.',
+       'fogg-width-title' => 'Largor de la vidèo',
+       'fogg-width-help' => 'Redimensionar a la largor especificada.',
+       'fogg-height-title' => 'Nautor de la vidèo',
+       'fogg-height-help' => 'Redimensionar a la nautor especificada.',
+       'fogg-videoBitrate-title' => 'Debit binari de la vidèo',
+       'fogg-videoBitrate-help' => "Lo debit binari de la vidèo definís lo debit de l'encodatge per la vidèo en kb/s",
+       'fogg-twopass-title' => 'Encodatge de doas passas',
+       'fogg-twopass-help' => "L'encodatge de doas passas permet una qualitat mai constanta en efectuant dos percorses del fichièr vidèo",
+       'fogg-framerate-title' => "Frequéncia d'imatges",
+       'fogg-framerate-help' => 'Lo nombre d\'imatges per segonda de la vidèo. Mai d\'entresenhas sus <a target="_new" href="http://oc.wikipedia.org/wiki/Imatges_per_segonda">la frequéncia d\'imatges</a>.',
+       'fogg-aspect-title' => 'Rapòrt largor/nautor',
+       'fogg-aspect-help' => 'Lo rapòrt largor/nautor de la vidèo pòt èsser una fraccion 4:3 o 16:9. Mai d\'entresenhas suls <a target="_new" href="http://oc.wikipedia.org/wiki/Rapòrt_largor/nautor">rapòrts largor/nautor</a>.',
+       'fogg-keyframeInterval-title' => 'Interval dels imatges-claus',
+       'fogg-keyframeInterval-help' => "L'interval dels imatges-claus dins los imatges. Nòta : la màger part dels codecs impausan los imatges-claus se la diferéncia entre los imatges es mai granda que la talha d'encodatge de l'imatge-clau. Mai d'entresenhas suls <a href=\"http://en.wikipedia.org/wiki/Video_compression_picture_types\">imatges-claus</a>.",
+       'fogg-denoise-title' => 'Filtre antibruch',
+       'fogg-denoise-help' => 'Desbruchatge de la vidèo en entrada. Mai d\'entresenhas sus <a href="http://en.wikipedia.org/wiki/Video_denoising">debruchatge</a>.',
+       'fogg-novideo-title' => 'Pas de vidèo',
+       'fogg-novideo-help' => 'desactivar la vidèo dins la sortida',
+       'fogg-audioBitrate-title' => 'Debit binari àudio',
+       'fogg-samplerate-title' => "Taus d'escandalhatge àudio",
+       'fogg-samplerate-help' => "definir lo taus d'escandalhatge de la sortida (en Hz).",
+       'fogg-noaudio-title' => "Pas d'àudio",
+       'fogg-noaudio-help' => "desactivar l'àudio dins la sortida",
+       'fogg-title-title' => 'Títol',
+       'fogg-title-help' => 'Un títol per vòstre clip',
+       'fogg-artist-title' => 'Nom del creator',
+       'fogg-artist-help' => "Lo creator d'aqueste clip",
+       'fogg-date-title' => 'Data',
+       'fogg-date-help' => 'La data a la quala lo metratge es estat creat o publicat',
+       'fogg-location-title' => 'Localizacion',
+       'fogg-location-help' => 'La localizacion del metratge',
+       'fogg-organization-title' => 'Societat',
+       'fogg-organization-help' => 'Nom de la societat (estudiò)',
+       'fogg-copyright-title' => 'Copyright',
+       'fogg-copyright-help' => 'Lo copyright del clip',
+       'fogg-license-title' => 'Licéncia',
+       'fogg-license-help' => "La licéncia d'aqueste clip (preferiblament una URL Creative Commons).",
+       'fogg-contact-title' => 'Contacte',
+       'fogg-contact-help' => 'Ligam del contacte',
+       'mwe-add_media_wizard' => "Assistent d'apondon de mèdia",
+       'mwe-media_search' => 'Recèrca de mèdias',
+       'rsd_box_layout' => 'Disposicion de la bóstia',
+       'rsd_list_layout' => 'Disposicion de la lista',
+       'rsd_results_desc' => 'Resultats $1 a $2',
+       'rsd_results_desc_total' => 'Resultats $1 a $2 de $3',
+       'rsd_results_next' => 'seguent',
+       'rsd_results_prev' => 'precedent',
+       'rsd_no_results' => 'Pas cap de resultat per <b>$1</b>',
+       'mwe-upload_tab' => 'Telecargament',
+       'rsd_layout' => 'Aparéncia :',
+       'rsd_resource_edit' => 'Modificar la ressorsa : $1',
+       'mwe-resource_description_page' => 'Pagina de descripcion de la ressorsa',
+       'mwe-link' => 'ligam',
+       'rsd_local_resource_title' => 'Títol de la ressorsa locala',
+       'rsd_do_insert' => "Far l'insercion",
+       'mwe-cc_by_title' => 'Atribucion',
+       'mwe-cc_nc_title' => 'Pas comercial',
+       'mwe-cc_nd_title' => 'Pas de trabalhs derivats',
+       'mwe-cc_sa_title' => "Partatge a l'identic",
+       'mwe-cc_pd_title' => 'Domeni public',
+       'mwe-unknown_license' => 'Licéncia desconeguda',
+       'mwe-no_import_by_url' => "Aqueste utilizaire o aqueste wiki <b>pòt pas</b> importar d'assets dempuèi las URLs distantas.<p>Avètz besonh de vos connectar ?</p><p>Dispausatz de la permission ''upload_by_url'' ?<br /><a href=\"http://www.mediawiki.org/wiki/Manual:\$wgAllowCopyUploads\">\$wgAllowCopyUploads</a> es activat sul wiki ?</p>",
+       'mwe-results_from' => 'Resultats dempuèi <a href="$1" target="_new" >$2</a>',
+       'mwe-missing_desc_see_source' => "Manca una descripcion per aqueste asset. Consultatz la [$1 font d'origina] e ajudatz a lo descriure.",
+       'rsd_config_error' => "Error de configuracion de l'assistent d'apondon de mèdia : $1",
+       'mwe-your_recent_uploads' => 'Vòstres darrièrs telecargaments sus $1',
+       'mwe-upload_a_file' => 'Telecargar un fichièr novèl sus $1',
+       'mwe-resource_page_desc' => 'Pagina de  descripcion de la ressorsa :',
+       'mwe-edit_resource_desc' => 'Modificar lo wiki tèxte de la descripcion de la ressorsa :',
+       'mwe-local_resource_title' => 'Títol de la ressorsa locala :',
+       'mwe-watch_this_page' => 'Seguir aquesta pagina',
+       'mwe-do_import_resource' => 'Importar la ressorsa',
+       'mwe-update_preview' => 'Metre a jorn la previsualizacion',
+       'mwe-cancel_import' => "Anullar l'importacion",
+       'mwe-importing_asset' => "Impòrt de l'asset",
+       'mwe-preview_insert_resource' => "Previsualizar l'insercion de la ressorsa : $1",
+       'mwe-checking-resource' => 'Verificacion de la ressorsa',
+       'mwe-resource-needs-import' => 'La ressorsa $1 deu èsser importada sus $2',
+       'mwe-ftype-svg' => 'Fichièr vectorial SVG',
+       'mwe-ftype-jpg' => 'Fichièr imatge JPEG',
+       'mwe-ftype-png' => 'Fichièr imatge PNG',
+       'mwe-ftype-oga' => 'Fichièr àudio Ogg',
+       'mwe-ftype-ogg' => 'Fichièr vidèo Ogg',
+       'mwe-ftype-unk' => 'Format de fichièr desconegut',
+       'mwe-select_file' => 'Seleccionatz un fichièr',
+       'mwe-more_licence_options' => 'Per mai d\'opcions de licéncias, consultatz la <a href="$1">pagina de telecargament normal</a>',
+       'mwe-select_ownwork' => 'Telecargui unicament mas pròprias òbras, e las placi jos licéncia :',
+       'mwe-licence_cc-by-sa' => "Creative Commons Pertatge a l'identic (3.0)",
+       'mwe-upload' => 'Telecargar un fichièr',
+       'mwe-destfilename' => 'Nom del fichièr de destinacion :',
+       'mwe-summary' => 'Resumir',
+       'mwe-error_not_loggedin' => "Sembla que sètz pas connectat o qu'avètz pas lo drech de telecargar.",
+       'mwe-watch-this-file' => 'Seguir aqueste fichièr',
+       'mwe-ignore-any-warnings' => 'Ignorar los avertiments',
+       'mwe-upload-transcode-in-progress' => 'Transcodatge e telecargament en cors (tampetz pas aquesta fenèstra)',
+       'mwe-upload-in-progress' => 'Telecargament en cors (tampetz pas aquesta fenèstra)',
+       'mwe-upload-transcoded-status' => 'Transcodat',
+       'mwe-uploaded-status' => 'Telecargat',
+       'mwe-upload-stats-fileprogres' => '$1 de $2',
+       'mwe-upload_completed' => 'Vòstre telecargament es acabat',
+       'mwe-upload_done' => '<a href="$1">Vòstre telecargament <i>deuriá èsser</i> accessible</a>.',
+       'mwe-upload-unknown-size' => 'Talha desconeguda',
+       'mwe-cancel-confim' => 'Sètz segur que volètz anullar ?',
+       'mwe-successfulupload' => 'Telecargament capitat',
+       'mwe-uploaderror' => 'Error al moment del telecargament',
+       'mwe-uploadwarning' => 'Avertiment al moment del telecargament',
+       'mwe-unknown-error' => 'Error desconeguda :',
+       'mwe-return-to-form' => 'Tornar al formulari',
+       'mwe-file-exists-duplicate' => 'Aqueste fichièr es un doblon del fichièr seguent :',
+       'mwe-fileexists' => 'Un fichièr amb aqueste nom existís ja. Mercé de verificar <b><tt>$1</tt></b> se sètz pas segur que lo volètz cambiar.',
+       'mwe-fileexists-thumb' => '<center><b>Fichièr existent</b></center>',
+       'mwe-ignorewarning' => 'Ignorar l’avertiment e salvar quitament lo fichièr',
+       'mwe-file-thumbnail-no' => 'Lo nom de fichièr comença per <b><tt>$1</tt></b>',
+       'mwe-go-to-resource' => 'Anar a la pagina de la ressorsa',
+       'mwe-upload-misc-error' => 'Error desconeguda al moment del telecargament',
+       'mwe-wgfogg_warning_bad_extension' => 'Avètz seleccionat un fichièr que compòrta una extension pas suportada (<a href="http://commons.wikimedia.org/wiki/Commons:Firefogg#Supported_File_Types">mai d\'entresenhas</a>).',
+       'mwe-upload-multi' => 'Cargar {{PLURAL:$1|lo fichièr|los fichièrs}}',
+       'mwe-loading_plugin' => 'cargament del plugin ...',
+       'mwe-select_playback' => 'Definir las preferéncias de lectura',
+       'mwe-link_back' => 'Ligam retorn',
+       'mwe-error_swap_vid' => "Erreur : mv_embed a pas capitat d'escambiar l'atribut de la vidèo per l'interfàcia mv_embed",
+       'mwe-add_to_end_of_sequence' => 'Apondre a la fin de la sequéncia',
+       'mwe-missing_video_stream' => 'Lo fichièr vidèo per aqueste flus es mancant',
+       'mwe-play_clip' => 'Legir lo clip',
+       'mwe-pause_clip' => 'Metre lo clip en pausa',
+       'mwe-volume_control' => 'Contraròtle del volum',
+       'mwe-player_options' => 'Opcions del lector',
+       'mwe-closed_captions' => 'Tampar las legendas',
+       'mwe-player_fullscreen' => 'Ecran plen',
+       'mwe-next_clip_msg' => 'Legir lo clip seguent',
+       'mwe-prev_clip_msg' => 'Legir lo clip precedent',
+       'mwe-current_clip_msg' => "Perseguir la lectura d'aqueste clip",
+       'mwe-seek_to' => 'Aténher $1',
+       'mwe-paused' => 'en pausa',
+       'mwe-download_segment' => 'Telecargar la seleccion :',
+       'mwe-download_full' => 'Telecargar lo fichièr de la vidèo completa :',
+       'mwe-download_right_click' => 'Per telecargar, clicatz-drech e seleccionatz <i>Enregistrar la cibla del ligam jos...</i>',
+       'mwe-download_clip' => 'Telecargar la vidèo',
+       'mwe-download_text' => 'Telecargar lo tèxte (<a style="color:white" title="cmml" href="http://wiki.xiph.org/index.php/CMML">CMML</a> xml) :',
+       'mwe-download' => 'Telecargar',
+       'mwe-share' => 'Partejar',
+       'mwe-credits' => 'Credits',
+       'mwe-clip_linkback' => 'Pagina font del clip',
+       'mwe-chose_player' => 'Causir lo lector vidèo',
+       'mwe-share_this_video' => 'Partejar aquesta vidèo',
+       'mwe-video_credits' => 'Credits de la vidèo',
+       'mwe-menu_btn' => 'Menut',
+       'mwe-close_btn' => 'Tampar',
+       'mwe-ogg-player-videoElement' => 'Vidèo Ogg en natiu',
+       'mwe-ogg-player-oggPlugin' => 'Modul generic Ogg',
+       'mwe-ogg-player-quicktime-mozilla' => 'Modul QuickTime',
+       'mwe-ogg-player-quicktime-activex' => 'ActiveX QuickTime',
+       'mwe-ogg-player-cortado' => 'Java Cortado',
+       'mwe-ogg-player-flowplayer' => 'Flowplayer',
+       'mwe-ogg-player-selected' => '(seleccionat)',
+       'mwe-ogg-player-omtkplayer' => 'OMTK Flash Vorbis',
+       'mwe-generic_missing_plugin' => 'Vòstre navigador sembla pas compatible amb lo tipe de lectura seguent : <b>$1</b><br />Visitatz la pagina dels <a href="http://commons.wikimedia.org/wiki/Commons:Media_help">metòdes de visionatge</a> per telecargar un lector.<br />',
+       'mwe-for_best_experience' => 'Per un melhor visionatge recomandam :<br /><b><a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=mwEmbed">Firefox 3.5</a>.</b>',
+       'mwe-do_not_warn_again' => 'Interrompre pel moment.',
+       'mwe-playerselect' => 'Lectors',
+       'mwe-read_before_embed' => 'Legissètz <a href="http://mediawiki.org/wiki/Security_Notes_on_Remote_Embedding" target="_new">aquò</a> abans de procedir !',
+       'mwe-embed_site_or_blog' => 'Integrar dins una pagina',
+       'mwe-related_videos' => 'Vidèos associadas',
+       'mwe-seeking' => 'recèrca',
+       'mwe-copy-code' => 'Copiar lo còde',
+);
+
+/** Deitsch (Deitsch)
+ * @author Xqt
+ */
+$messages['pdc'] = array(
+       'mwe-ok' => 'OK',
+       'rsd_results_next' => 'weiter',
+       'rsd_results_prev' => 'zerick',
+);
+
+/** Polish (Polski)
+ * @author McDutchie
+ * @author Sp5uhe
+ */
+$messages['pl'] = array(
+       'mwe-crop' => 'Kadruj',
+       'mwe-apply_crop' => 'Skadruj obrazek',
+       'mwe-reset_crop' => 'Ponów kadrowanie',
+       'mwe-insert_image_page' => 'Wstaw na stronę',
+       'mwe-insert_into_sequence' => 'Wstaw do sekwencji',
+       'mwe-preview_insert' => 'Podgląd wstawienia',
+       'mwe-cancel_image_insert' => 'Anuluj wstawienie',
+       'mwe-sc_fileopts' => 'Edycja opisu klipu',
+       'mwe-sc_inoutpoints' => 'Ustaw czasy początku i końca',
+       'mwe-sc_overlays' => 'Nakładki',
+       'mwe-sc_audio' => 'Kontrola dźwięku',
+       'mwe-sc_duration' => 'Czas trwania',
+       'mwe-template_properties' => 'Właściwości szablonu',
+       'mwe-custom_title' => 'Niestandardowy tytuł',
+       'mwe-edit_properties' => 'Edycja właściwości',
+       'mwe-other_properties' => 'Inne właściwości',
+       'mwe-resource_page' => 'Strona zasobów',
+       'mwe-set_in_out_points' => 'Ustaw czasy rozpoczęcia i zakończenia',
+       'mwe-start_time' => 'Czas rozpoczęcia',
+       'mwe-end_time' => 'Czas zakończenia',
+       'mwe-preview_inout' => 'Podgląd dla obecnie ustawionych czasów',
+       'mwe-edit-tools' => 'Narzędzia edycyjne',
+       'mwe-inline-description' => 'Nagłówek',
+       'mwe-edit-video-tools' => 'Narzędzia edycji wideo:',
+       'mwe-duration' => 'Czas trwania',
+       'mwe-upload-subs-file' => 'Prześlij listę dialogową',
+       'mwe-add-subs-file-title' => 'Wybór listy dialogowej do przesłania',
+       'mwe-error-only-srt' => 'Możesz przesyłać wyłącznie pliki srt.',
+       'mwe-watch-video' => 'Pokaż film',
+       'mwe-select-other-language' => 'Wybór innego języka',
+       'mwe-saving' => 'zapisywanie...',
+       'mwe-select_transcript_set' => 'Wybór list dialogowych',
+       'mwe-auto_scroll' => 'automatyczne przewijanie',
+       'mwe-close' => 'zamknij',
+       'mwe-improve_transcript' => 'Popraw',
+       'mwe-no_text_tracks_found' => 'Nie znaleziono listy dialogowej',
+       'mwe-add-edit-subs' => 'Dodaj lub edytuj listy dialogowe',
+       'mwe-transition_in' => 'Wejście',
+       'mwe-transition_out' => 'Wyjście',
+       'mwe-effects' => 'Stos efektów',
+       'mwe-remove_transition' => 'Usuń przejście',
+       'mwe-edit_transin' => 'Edytuj przejście do klipu',
+       'mwe-edit_transout' => 'Edytuj przejście zakończenia klipu',
+       'mwe-menu_clipedit' => 'Edytuj multimeda',
+       'mwe-menu_transition' => 'Przejścia i efekty',
+       'mwe-menu_cliplib' => 'Dodaj media',
+       'mwe-menu_resource_overview' => 'Przegląd zasobów',
+       'mwe-menu_options' => 'Opcje',
+       'mwe-loading_timeline' => 'Ładowanie osi czasu ...',
+       'mwe-loading_user_rights' => 'Ładowanie praw użytkowników ...',
+       'mwe-no_edit_permissions' => 'Nie masz uprawnień, aby zapisać zmiany w tej kolejności',
+       'mwe-edit_clip' => 'Edytuj klip',
+       'mwe-edit_save' => 'Zapisz sekwencję zmian',
+       'mwe-saving_wait' => 'Zapisywanie trwa (proszę czekać)',
+       'mwe-save_done' => 'Zapisano',
+       'mwe-edit_cancel' => 'Anuluj sekwencję zmian',
+       'mwe-edit_cancel_confirm' => 'Czy na pewno chcesz anulować edycję? Zmiany zostaną utracone.',
+       'mwe-zoom_in' => 'Powiększ',
+       'mwe-zoom_out' => 'Pomniejsz',
+       'mwe-cut_clip' => 'Przytnij klipy',
+       'mwe-rmclip' => 'Usuń klip',
+       'mwe-clip_in' => 'początek klipu',
+       'mwe-clip_out' => 'koniec klipu',
+       'mwe-no_selected_resource' => '<h3>Nie wybrano zasobu</h3> Wybierz klip, jeśli chcesz edytować.',
+       'mwe-error_edit_multiple' => '<h3>Wybrano wiele zasobów</h3> Wybierz jeden klip, jeśli chcesz edytować.',
+       'mwe-editor_options' => 'Opcje edytora',
+       'mwe-editor_mode' => 'Tryb pracy edytora',
+       'mwe-simple_editor_desc' => 'prosty edytor tekstu (w stylu iMovie)',
+       'mwe-advanced_editor_desc' => 'zaawansowany edytor (w stylu Final Cut)',
+       'mwe-other_options' => 'Inne opcje',
+       'mwe-contextmenu_opt' => 'Włącz menu kontekstowe',
+       'mwe-sequencer_credit_line' => 'Wykonane przez <a href="http://kaltura.com">Kaltura, Inc,</a> we współpracy z <a href="http://wikimediafoundation.org/wiki/Home">Fundacją Wikimedia</a> (<a href="#">więcej informacji</a>).',
+       'mwe-loading_txt' => 'ładowanie ...',
+       'mwe-error_load_lib' => 'Błąd – W plik JavaScript $1 brak jest możliwości pobrania oraz definicji $2',
+       'fogg-select_file' => 'Wybierz plik',
+       'fogg-select_new_file' => 'Wybierz nowy plik',
+       'fogg-select_url' => 'Wybierz adres URL',
+       'fogg-save_local_file' => 'Zapisz w formacie Ogg',
+       'fogg-check_for_firefogg' => 'Sprawdzanie czy używasz Firefogg ...',
+       'fogg-installed' => 'Firefogg jest zainstalowany',
+       'fogg-for_improved_uploads' => 'Dla poprawy przesyłania:',
+       'fogg-please_install' => '<a href="$1">Zainstaluj Firefogg</a>. Więcej <a href="http://commons.wikimedia.org/wiki/Commons:Firefogg">o Firefogg</a>',
+       'fogg-use_latest_firefox' => 'Należy najpierw zainstalować <a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=firefogg">Firefox 3.5</a> (lub nowszy). <i>Następnie wejść ponownie na tę stronę, aby zainstalować rozszerzenie <b>Firefogg.</b></i>',
+       'fogg-passthrough_mode' => 'Wybrany przez Ciebie plik jest już w formacie Ogg lub nie jest plikiem wideo',
+       'fogg-transcoding' => 'Kodowanie wideo do formatu Ogg',
+       'fogg-encoding-done' => 'Kodowanie zakończone',
+       'fogg-badtoken' => 'Token jest nieprawidłowy',
+       'fogg-preview' => 'Podgląd wideo',
+       'fogg-hidepreview' => 'Ukryj podgląd',
+       'fogg-help-sticky' => 'Pomoc (kliknij, aby przylepić)',
+       'fogg-cg-preset' => 'Domyślnie – <strong>$1</strong>',
+       'fogg-cg-quality' => 'Podstawowe ustawienia jakości i rozdzielczości',
+       'fogg-cg-meta' => 'Metadane klipu',
+       'fogg-cg-range' => 'Zakres kodowania',
+       'fogg-cg-advVideo' => 'Zaawansowane ustawienia kodowania wideo',
+       'fogg-cg-advAudio' => 'Zaawansowane ustawienia kodowania dźwięku',
+       'fogg-preset-custom' => 'Ustawienia niestandardowe',
+       'rsd_box_layout' => 'Układ okna',
+       'rsd_list_layout' => 'Układ listy',
+       'rsd_results_desc' => 'Wyniki od $1 do $2',
+       'rsd_results_desc_total' => 'Wyniki od $1 do $2 z $3',
+       'rsd_results_next' => 'następne',
+       'rsd_results_prev' => 'poprzednie',
+       'rsd_no_results' => 'Brak wyników wyszukiwania <b>$1</b>',
+       'mwe-upload_tab' => 'Prześlij',
+       'rsd_layout' => 'Układ',
+       'rsd_resource_edit' => 'Edytuj zasób $1',
+       'mwe-resource_description_page' => 'Strona opisu zasobu',
+       'rsd_local_resource_title' => 'Nazwa zasobu lokalnego',
+       'rsd_do_insert' => 'Wstaw',
+       'mwe-cc_by_title' => 'Wskazanie autorów',
+       'mwe-cc_nc_title' => 'Użycie niekomercyjne',
+       'mwe-cc_nd_title' => 'Bez utworów zależnych',
+       'mwe-cc_sa_title' => 'Na tych samych zasadach',
+       'mwe-cc_pd_title' => 'Domena publiczna',
+       'mwe-unknown_license' => 'Licencja nieznana',
+       'rsd_config_error' => 'Błąd konfiguracji kreatora dodawania mediów – $1',
+       'mwe-your_recent_uploads' => 'Ostatnio przez Ciebie przesłane',
+       'mwe-upload_a_file' => 'Przesłanie nowego pliku',
+       'mwe-watch_this_page' => 'Obserwuj tę stronę',
+       'rsd-wiki_commons-title' => 'Wikimedia Commons',
+       'rsd-wiki_commons' => 'Wikimedia Commons — archiwum edukacyjnych multimediów dostępnych na wolnych licencjach (grafiki, pliki dźwiękowe i wideo)',
+       'rsd-this_wiki-title' => 'Ta wiki',
+       'rsd-this_wiki-desc' => 'Lokalna instalacja wiki',
+       'rsd-archive_org-desc' => 'Archiwum Internetowe — cyfrowa biblioteka zabytków kultury',
+       'rsd-flickr-desc' => 'Flickr.com — witryna udostępniania zdjęć',
+       'rsd-metavid-desc' => 'Metavid.org — wspólne archiwum Izby oraz Senatu USA',
+       'mwe-select_file' => 'Wybór pliku',
+       'mwe-more_licence_options' => 'Bardziej złożone licencje dostępne są na <a href="$1">standardowej stronie przesyłania plików</a>',
+       'mwe-licence_cc-by-sa' => 'Creative Commons: uznanie autorstwa, na tych samych warunkach (3.0)',
+       'mwe-upload' => 'Prześlij plik',
+       'mwe-summary' => 'Podsumowanie',
+       'mwe-upload-in-progress' => 'Przesyłanie w toku (nie zamykaj tego okna)',
+       'mwe-uploaded-status' => 'Przesłano',
+       'mwe-upload_completed' => 'Przesyłanie zakończone',
+       'mwe-upload-unknown-size' => 'Nieznany rozmiar',
+       'mwe-successfulupload' => 'Przesłano',
+       'mwe-uploaderror' => 'Błąd w trakcie przesyłania',
+       'mwe-uploadwarning' => 'Ostrzeżenie dotyczące przesyłania',
+       'mwe-unknown-error' => 'Nieznany błąd –',
+       'mwe-return-to-form' => 'Powrót do formularza',
+       'mwe-file-exists-duplicate' => 'Ten plik jest identyczny z plikiem',
+       'mwe-fileexists' => 'Plik o tej nazwie już istnieje. Sprawdź <b><tt>$1</tt></b> jeśli nie jesteś pewien czy chcesz go zastąpić.',
+       'mwe-fileexists-thumb' => '<center><b>Istniejący plik</b></center>',
+       'mwe-ignorewarning' => 'Zignoruj ostrzeżenie i zapisz plik mimo wszystko',
+       'mwe-file-thumbnail-no' => 'Nazwa pliku zaczyna się od <b><tt>$1</tt></b>',
+       'mwe-go-to-resource' => 'Przejdź do strony zasobu',
+       'mwe-upload-misc-error' => 'Nieznany błąd przesyłania',
+       'mwe-wgfogg_warning_bad_extension' => 'Wybrałeś plik z nieobsługiwanym rozszerzeniem (<a href="http://commons.wikimedia.org/wiki/Commons:Firefogg#Supported_File_Types">więcej informacji</a>).',
+       'mwe-loading_plugin' => 'trwa ładowanie wtyczki...',
+       'mwe-select_playback' => 'Ustaw preferencje odtwarzania',
+       'mwe-link_back' => 'Link powrotny',
+       'mwe-error_swap_vid' => 'Błąd – mv_embed nie był w stanie zamieniać znacznika filmu dla interfejsu mv_embed',
+       'mwe-add_to_end_of_sequence' => 'Dodaj na koniec sekwencji',
+       'mwe-missing_video_stream' => 'Brak pliku z filmem dla tego strumienia',
+       'mwe-play_clip' => 'Odtwórz klip',
+       'mwe-pause_clip' => 'Wstrzymaj odtwarzanie klipu',
+       'mwe-volume_control' => 'Regulacja głośności',
+       'mwe-player_options' => 'Opcje odtwarzacza',
+       'mwe-closed_captions' => 'Podtytuły',
+       'mwe-player_fullscreen' => 'Pełny ekran',
+       'mwe-next_clip_msg' => 'Odtwórz następny klip',
+       'mwe-prev_clip_msg' => 'Odtwórz poprzedni klip',
+       'mwe-current_clip_msg' => 'Kontynuuj odtwarzanie tego klipu',
+       'mwe-seek_to' => 'Przewiń $1',
+       'mwe-download_clip' => 'Pobierz film',
+       'mwe-download' => 'Pobierz',
+       'mwe-share' => 'Udostępnij',
+       'mwe-credits' => 'Twórcy',
+       'mwe-clip_linkback' => 'Strona źródłowa klipu',
+       'mwe-chose_player' => 'Wybierz odtwarzacz wideo',
+       'mwe-share_this_video' => 'Udostępnij ten film',
+       'mwe-video_credits' => 'Twórcy filmu',
+       'mwe-menu_btn' => 'Menu',
+       'mwe-close_btn' => 'Zamknij',
+       'mwe-ogg-player-vlc-player' => 'Odtwarzacz VLC',
+       'mwe-ogg-player-videoElement' => 'Własna obsługa wideo w formacie Ogg',
+       'mwe-ogg-player-oggPlugin' => 'Pierwotna wtyczka Ogg',
+       'mwe-ogg-player-quicktime-mozilla' => 'Wtyczka QuickTime',
+       'mwe-ogg-player-quicktime-activex' => 'QuickTime ActiveX',
+       'mwe-ogg-player-cortado' => 'Cortado w Java',
+       'mwe-ogg-player-flowplayer' => 'Flowplayer',
+       'mwe-ogg-player-kplayer' => 'Odtwarzacz Kaltura',
+       'mwe-ogg-player-selected' => '(zaznaczone)',
+       'mwe-ogg-player-omtkplayer' => 'OMTK Flash Vorbis',
+       'mwe-generic_missing_plugin' => 'Twoja przeglądarka nie obsługuje odtwarzania następujących formatów: <b>$1</b><br />Odwiedź stronę opisującą <a href="http://commons.wikimedia.org/wiki/Commons:Media_help">sposoby odtwarzania</a>, aby pobrać odpowiednie oprogramowanie.<br />',
+       'mwe-do_not_warn_again' => 'Od teraz ignoruj.',
+       'mwe-playerselect' => 'Odtwarzacze',
+       'mwe-embed_site_or_blog' => 'Umieść na swojej stronie lub blogu',
+       'mwe-related_videos' => 'Podobne filmy',
+);
+
+/** Portuguese (Português)
+ * @author Hamilton Abreu
+ * @author Lijealso
+ * @author Luckas Blade
+ * @author Malafaya
+ */
+$messages['pt'] = array(
+       'mwe-crop' => 'Cortar imagem',
+       'mwe-apply_crop' => 'Aplicar corte à imagem',
+       'mwe-reset_crop' => 'Reiniciar corte',
+       'mwe-insert_image_page' => 'Inserir na página',
+       'mwe-insert_into_sequence' => 'Inserir na sequência',
+       'mwe-preview_insert' => 'Antever inserção',
+       'mwe-cancel_image_insert' => 'Cancelar a inserção',
+       'mwe-sc_fileopts' => 'Edição de detalhes do clipe',
+       'mwe-sc_inoutpoints' => 'Estabelecer pontos de entrada e saída',
+       'mwe-sc_overlays' => 'Sobreposições',
+       'mwe-sc_audio' => 'Controlo de áudio',
+       'mwe-sc_duration' => 'Duração',
+       'mwe-template_properties' => 'Propriedades do modelo',
+       'mwe-custom_title' => 'Título personalizado',
+       'mwe-edit_properties' => 'Editar propriedades',
+       'mwe-other_properties' => 'Outras propriedades',
+       'mwe-resource_page' => 'Página de recursos:',
+       'mwe-set_in_out_points' => 'Estabelecer pontos de entrada e saída',
+       'mwe-start_time' => 'Tempo de início',
+       'mwe-end_time' => 'Tempo de fim',
+       'mwe-preview_inout' => 'Antever pontos de entrada e saída',
+       'mwe-edit-tools' => 'Instrumentos de edição',
+       'mwe-inline-description' => 'Descrição',
+       'mwe-edit-video-tools' => 'Ferramentas de edição de vídeo:',
+       'mwe-duration' => 'Duração:',
+       'mwe-upload-subs-file' => 'Carregar legendas',
+       'mwe-add-subs-file-title' => 'Seleccionar legendas a carregar',
+       'mwe-error-only-srt' => 'Só pode carregar ficheiros srt.',
+       'mwe-watch-video' => 'Ver vídeo',
+       'mwe-select-other-language' => 'Seleccionar outra língua',
+       'mwe-saving' => 'a gravar...',
+       'mwe-select_transcript_set' => 'Seleccionar legendas',
+       'mwe-auto_scroll' => 'deslocamento automático',
+       'mwe-close' => 'fechar',
+       'mwe-improve_transcript' => 'Melhorar',
+       'mwe-no_text_tracks_found' => 'Não foram encontradas legendas',
+       'mwe-add-edit-subs' => 'Adicionar/editar legendas',
+       'mwe-transition_in' => 'Entrada da transição',
+       'mwe-transition_out' => 'Saída da transição',
+       'mwe-effects' => 'Pilha de efeitos',
+       'mwe-remove_transition' => 'Remover transição',
+       'mwe-edit_transin' => 'Inserir transição no clipe',
+       'mwe-edit_transout' => 'Remover transição do clipe',
+       'mwe-add-transition' => 'Adicionar uma transição',
+       'mwe-menu_clipedit' => 'Editar multimédia',
+       'mwe-menu_transition' => 'Transições e efeitos',
+       'mwe-menu_cliplib' => 'Adicionar multimédia',
+       'mwe-menu_resource_overview' => 'Visão geral dos recursos',
+       'mwe-menu_options' => 'Opções',
+       'mwe-loading_timeline' => 'A carregar linha do tempo ...',
+       'mwe-loading_user_rights' => 'A carregar os direitos do utilizador ...',
+       'mwe-no_edit_permissions' => 'Não tem permissões para gravar alterações a esta sequência',
+       'mwe-edit_clip' => 'Editar clipe',
+       'mwe-edit_save' => 'Gravar mudanças na sequência',
+       'mwe-saving_wait' => 'Gravação em progresso (por favor, aguarde)',
+       'mwe-save_done' => 'Gravação completa',
+       'mwe-edit_cancel' => 'Cancelar edição da sequência',
+       'mwe-edit_cancel_confirm' => 'Tem a certeza de que quer cancelar a edição? As alterações serão perdidas.',
+       'mwe-zoom_in' => 'Aproximar',
+       'mwe-zoom_out' => 'Afastar',
+       'mwe-cut_clip' => 'Cortar clipes',
+       'mwe-expand_track' => 'Expandir faixa',
+       'mwe-collapse_track' => 'Colapsar faixa',
+       'mwe-play_from_position' => 'Começar a partir da posicão na linha',
+       'mwe-pixle2sec' => 'pixels para segundos',
+       'mwe-rmclip' => 'Remover clipe',
+       'mwe-clip_in' => 'entrada do clipe',
+       'mwe-clip_out' => 'saída do clipe',
+       'mwe-no_selected_resource' => '<h3>Nenhum recurso seleccionado</h3> Seleccione um clip para possibilitar edição.',
+       'mwe-error_edit_multiple' => '<h3>Vários recursos seleccionados</h3> Seleccione um único clipe para editá-lo.',
+       'mwe-editor_options' => 'Opções do editor',
+       'mwe-editor_mode' => 'Modo editor',
+       'mwe-simple_editor_desc' => 'editor simples (estilo iMovie)',
+       'mwe-advanced_editor_desc' => 'editor avançado (estilo Final Cut)',
+       'mwe-other_options' => 'Outras opções',
+       'mwe-contextmenu_opt' => 'Possibilitar menus de contexto',
+       'mwe-sequencer_credit_line' => 'Desenvolvido por <a href="http://kaltura.com">Kaltura, Inc.</a> em parceria com a <a href="http://wikimediafoundation.org/wiki/Home">Wikimedia Foundation</a> (<a href="#">mais informações</a>).',
+       'mwe-loading_txt' => 'A carregar ...',
+       'mwe-error_load_lib' => 'Erro: O JavaScript $1 não pode ser importado ou não define $2',
+       'mwe-loading-add-media-wiz' => "''Wizard'' de carregamento e multimédia",
+       'mwe-apiproxy-setup' => "A preparar o ''proxy'' da API",
+       'mwe-load-drag-item' => 'Carregando o objecto arrastado',
+       'mwe-ok' => 'OK',
+       'mwe-cancel' => 'Cancelar',
+       'mwe-setting-up-proxy' => "A preparar o ''proxy''...",
+       'mwe-re-try' => 'Repetir pedido API',
+       'mwe-re-trying' => 'A repetir pedido API...',
+       'mwe-proxy-not-ready' => "O ''proxy'' não está configurado",
+       'mwe-please-login' => 'Não está <a target="_new" href="$1">autenticado</a> em $2 ou o mwEmbed não foi activado. Resolva o problema e depois repita o pedido.',
+       'mwe-remember-loging' => 'Recomendação geral de segurança: Ao entrar em sítios na internet, certifique-se de que a barra do endereço mostra o endereço do sítio.',
+       'fogg-select_file' => 'Seleccione ficheiro',
+       'fogg-select_new_file' => 'Seleccione novo ficheiro',
+       'fogg-select_url' => 'Seleccione endereço (URL)',
+       'fogg-save_local_file' => 'Gravar Ogg',
+       'fogg-check_for_firefogg' => 'A procurar o Firefogg...',
+       'fogg-installed' => 'Firefogg está instalado',
+       'fogg-for_improved_uploads' => 'Para optimizar os carregamentos:',
+       'fogg-please_install' => '<a href="$1">Instalar o Firefogg</a>. Mais <a href="http://commons.wikimedia.org/wiki/Commons:Firefogg">informações sobre o Firefogg</a>.',
+       'fogg-use_latest_firefox' => 'Por favor, instale primeiro o <a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=firefogg">Firefox 3.5</a> (ou versão mais recente). <i>Depois volte a esta página para instalar a extensão <b>Firefogg</b>.</i>',
+       'fogg-passthrough_mode' => 'O ficheiro seleccionado já é de formato Ogg ou não é um ficheiro de vídeo',
+       'fogg-transcoding' => 'Codificar vídeo para Ogg',
+       'fogg-encoding-done' => 'Codificação finalizada',
+       'fogg-badtoken' => "''Token'' inválido",
+       'fogg-preview' => 'Antever vídeo',
+       'fogg-hidepreview' => 'Esconder a antevisão',
+       'mwe-imported_from' => '$1 importado de [$2 $3]. Consulte a [$4 página do recurso] original para mais informações.',
+       'mwe-stream_title' => '$1 $2 a $3',
+       'fogg-help-sticky' => 'Ajuda (clique para fixar)',
+       'fogg-cg-preset' => 'Predefinido: <strong>$1</strong>',
+       'fogg-cg-quality' => 'Controle básico de qualidade e resolução',
+       'fogg-cg-meta' => 'Metadados para o clipe',
+       'fogg-cg-range' => 'Gama de codificação',
+       'fogg-cg-advVideo' => 'Controles avançados da codificação de vídeo',
+       'fogg-cg-advAudio' => 'Controles avançados da codificação de áudio',
+       'fogg-preset-custom' => 'Configurações personalizadas',
+       'fogg-webvideo-desc' => 'Theora vídeo internet, Vorbis 400 kbit/s e 400px largura máx.',
+       'fogg-savebandwidth-desc' => 'Theora larg. banda reduzida, Vorbis 164 kbit/s e 200px largura máx.',
+       'fogg-highquality-desc' => 'Theora alta qualidade, Vorbis 1080px largura máx.',
+       'fogg-videoQuality-title' => 'Qualidade de vídeo',
+       'fogg-videoQuality-help' => "Usado para definir a <i>qualidade visual</i> do vídeo codificado (não será usado se definir a taxa de bits ''(bitrate)'' nos controles avançados em baixo).",
+       'fogg-starttime-title' => 'Segundo de início',
+       'fogg-starttime-help' => 'Codificar só a partir do tempo em segundos',
+       'fogg-endtime-title' => 'Segundo de fim',
+       'fogg-endtime-help' => 'Codificar só até ao tempo em segundos',
+       'fogg-audioQuality-title' => 'Qualidade de áudio',
+       'fogg-audioQuality-help' => "Usado para definir a <i>qualidade acústica</i> do áudio codificado (não será usado se definir a taxa de bits ''(bitrate)'' nos controles avançados em baixo).",
+       'fogg-videoCodec-title' => "''Codec'' de vídeo",
+       'fogg-videoCodec-help' => "Usado para seleccionar o ''codec'' de vídeo do clipe. Presentemente, só o Theora é suportado. Mais informações acerca do <a target=\"_new\" href=\"http://pt.wikipedia.org/wiki/Theora\">''Codec Theora</a>.",
+       'fogg-audioCodec-title' => "''Codec'' de áudio",
+       'fogg-audioCodec-help' => "Usado para seleccionar o ''codec'' de áudio do clipe. Presentemente, só o Vorbis é suportado. Mais informações acerca do <a target=\"_new\" href=\"http://pt.wikipedia.org/wiki/Vorbis\">''Codec Vorbis</a>.",
+       'fogg-width-title' => 'Largura do vídeo',
+       'fogg-width-help' => 'Redimensionar para largura especificada.',
+       'fogg-height-title' => 'Altura do vídeo',
+       'fogg-height-help' => 'Redimensionar para altura especificada.',
+       'fogg-videoBitrate-title' => "Taxa de bits ''(bitrate)'' do vídeo",
+       'fogg-videoBitrate-help' => 'A taxa de bits do vídeo determina a qualidade da codificação do vídeo em (kb/s)',
+       'fogg-twopass-title' => "Codificação em passagem dupla ''(two pass)''",
+       'fogg-twopass-help' => 'A codificação em passagem dupla mantém um nível de qualidade mais constante ao fazer duas passagens sobre o ficheiro vídeo',
+       'fogg-framerate-title' => "Taxa de fotogramas ''(frame rate)''",
+       'fogg-framerate-help' => 'A taxa de fotogramas do vídeo. Mais informações acerca da <a target="_new" href="http://en.wikipedia.org/wiki/Frame_rate">taxa de fotogramas</a>.',
+       'fogg-aspect-title' => "Rácio de aspecto ''(aspect ratio)''",
+       'fogg-aspect-help' => 'O rácio de aspecto do vídeo pode ser $:3 ou 16:9. Mais informações acerca de <a target="_new" href="http://en.wikipedia.org/wiki/Aspect_ratio_%28image%29">rácios de aspecto</a>.',
+       'fogg-keyframeInterval-title' => 'Intervalo dos fotogramas chave',
+       'fogg-keyframeInterval-help' => "O intervalo dos fotogramas chave, em fotogramas. Nota: A maioria dos ''codecs'' forçam fotogramas chave se a diferença entre fotogramas é maior do que o tamanho do fotograma chave codificado. Mais informações acerca dos <a href=\"http://en.wikipedia.org/wiki/I-frame\">fotogramas chave</a>.",
+       'fogg-denoise-title' => "Filtro de eliminação de ruído ''(denoise)''",
+       'fogg-denoise-help' => "Eliminar ruído ''(denoise)'' do vídeo de entrada. Mais informações acerca da <a href=\"http://en.wikipedia.org/wiki/Video_denoising\">eliminação de ruído</a>.",
+       'fogg-novideo-title' => 'Sem vídeo',
+       'fogg-novideo-help' => 'desactivar vídeo na saída',
+       'fogg-audioBitrate-title' => 'Taxa de bits do áudio',
+       'fogg-samplerate-title' => 'Taxa de amostragem do áudio',
+       'fogg-samplerate-help' => 'definir taxa de amostragem de saída (em Hz).',
+       'fogg-noaudio-title' => 'Sem áudio',
+       'fogg-noaudio-help' => 'desactivar áudio na saída',
+       'fogg-title-title' => 'Título',
+       'fogg-title-help' => 'Um título para este clipe',
+       'fogg-artist-title' => 'Nome do criador',
+       'fogg-artist-help' => 'O criador deste clipe',
+       'fogg-date-title' => 'Data',
+       'fogg-date-help' => 'A data de criação ou publicação da filmagem',
+       'fogg-location-title' => 'Localização',
+       'fogg-location-help' => 'O local da filmagem',
+       'fogg-organization-title' => 'Organização',
+       'fogg-organization-help' => 'Nome da organização (estúdio)',
+       'fogg-copyright-title' => 'Direitos de reprodução',
+       'fogg-copyright-help' => 'Os direitos de reprodução do clipe',
+       'fogg-license-title' => 'Licença',
+       'fogg-license-help' => 'A licença do clipe (de preferência, uma URL Creative Commons).',
+       'fogg-contact-title' => 'Contacto',
+       'fogg-contact-help' => 'Ligação de contacto',
+       'mwe-add_media_wizard' => "''Wizard'' de carregamentos multimédia",
+       'mwe-media_search' => 'Pesquisa de multimédia',
+       'rsd_box_layout' => 'Disposição em caixa',
+       'rsd_list_layout' => 'Disposição em lista',
+       'rsd_results_desc' => 'Resultados de $1 a $2',
+       'rsd_results_desc_total' => 'Resultados $1 a $2 de $3',
+       'rsd_results_next' => 'próximo',
+       'rsd_results_prev' => 'anterior',
+       'rsd_no_results' => 'A busca não produziu resultados para <b>$1</b>',
+       'mwe-upload_tab' => 'Carregar',
+       'rsd_layout' => 'Disposição:',
+       'rsd_resource_edit' => 'Editar recurso: $1',
+       'mwe-resource_description_page' => 'Página de descrição do recurso',
+       'mwe-link' => 'ligação',
+       'rsd_local_resource_title' => 'Título do recurso local',
+       'rsd_do_insert' => 'Fazer inserção',
+       'mwe-cc_by_title' => 'Atribuição',
+       'mwe-cc_nc_title' => 'Uso Não-Comercial',
+       'mwe-cc_nd_title' => 'Não a Obras Derivadas',
+       'mwe-cc_sa_title' => 'Partilha nos termos da mesma licença',
+       'mwe-cc_pd_title' => 'Domínio Público',
+       'mwe-unknown_license' => 'Licença desconhecida',
+       'mwe-no_import_by_url' => 'Este utilizador ou wiki <b>não pode</b> importar elementos de URLs remotas.<p>Precisa de se autenticar?</p><p>Tem a permissão upload_by_url?<br />A wiki tem a <a href="http://www.mediawiki.org/wiki/Manual:$wgAllowCopyUploads">$wgAllowCopyUploads</a> activada?</p>',
+       'mwe-results_from' => 'Resultados de <a href="$1" target="_new" >$2</a>',
+       'mwe-missing_desc_see_source' => 'Este elemento não tem descrição. Por favor, consulte a [$1 fonte original] e ajude a descrevê-lo.',
+       'rsd_config_error' => "Erro de configuração do ''wizard'' de carregamentos multimédia: $1",
+       'mwe-your_recent_uploads' => 'Os seus carregamentos recentes em $1',
+       'mwe-upload_a_file' => 'Carregar um novo ficheiro em $1',
+       'mwe-resource_page_desc' => 'Descrição da página do recurso:',
+       'mwe-edit_resource_desc' => 'Editar descrição do recurso em texto wiki:',
+       'mwe-local_resource_title' => 'Título do recurso local:',
+       'mwe-watch_this_page' => 'Vigiar esta página',
+       'mwe-do_import_resource' => 'Importar recurso',
+       'mwe-update_preview' => 'Actualizar antevisão',
+       'mwe-cancel_import' => 'Cancelar importação',
+       'mwe-importing_asset' => 'A importar elemento',
+       'mwe-preview_insert_resource' => 'Antever inserção do recurso: $1',
+       'mwe-checking-resource' => 'A procurar o recurso',
+       'mwe-resource-needs-import' => 'O recurso $1 precisa de ser importado para $2',
+       'mwe-ftype-svg' => 'Ficheiro vectorial SVG',
+       'mwe-ftype-jpg' => 'Ficheiro de imagem JPEG',
+       'mwe-ftype-png' => 'Ficheiro de imagem PNG',
+       'mwe-ftype-oga' => 'Ficheiro de áudio Ogg',
+       'mwe-ftype-ogg' => 'Ficheiro de vídeo Ogg',
+       'mwe-ftype-unk' => 'Formato de ficheiro desconhecido',
+       'rsd-wiki_commons-title' => 'Wikimedia Commons',
+       'rsd-wiki_commons' => 'Wikimedia Commons, um arquivo de conteúdos multimédia educativos, de licenciamento gratuito (imagens, som e clipes de vídeo)',
+       'rsd-this_wiki-title' => 'Esta wiki',
+       'rsd-this_wiki-desc' => 'A instalação local da wiki',
+       'rsd-archive_org-desc' => 'A Internet Archive, uma biblioteca digital de artefactos culturais',
+       'rsd-flickr-desc' => "Flickr.com, um sítio de partilha de fotos ''online''",
+       'rsd-metavid-desc' => 'Metavid.org, um arquivo comunitário dos trabalhos da Câmara e Senado dos Estados Unidos',
+       'mwe-select_file' => 'Seleccione o ficheiro',
+       'mwe-more_licence_options' => 'Para mais opções de licenciamento, consulte a <a href="$1">página de carregamento normal</a>',
+       'mwe-select_ownwork' => 'Carrego uma obra de minha completa autoria que publico nos termos da:',
+       'mwe-licence_cc-by-sa' => 'Atribuição – Partilha nos Termos da Mesma Licença',
+       'mwe-upload' => 'Carregar ficheiro',
+       'mwe-destfilename' => 'Nome de ficheiro de destino:',
+       'mwe-summary' => 'Sumário',
+       'mwe-error_not_loggedin' => 'Parece não estar autenticado ou não tem privilégios para carregar ficheiros.',
+       'mwe-watch-this-file' => 'Vigiar este ficheiro',
+       'mwe-ignore-any-warnings' => 'Ignorar quaisquer avisos',
+       'mwe-upload-transcode-in-progress' => 'Transcodificação e carregamento em progresso (não feche esta janela)',
+       'mwe-upload-in-progress' => 'Carregamento em progresso (não feche esta janela)',
+       'mwe-upload-transcoded-status' => 'Transcodificado',
+       'mwe-uploaded-status' => 'Carregado',
+       'mwe-upload-stats-fileprogress' => '$1 de $2',
+       'mwe-upload_completed' => 'O seu carregamento está completo',
+       'mwe-upload_done' => '<a href="$1">O carregamento <i>deve estar</i> accessível</a>.',
+       'mwe-upload-unknown-size' => 'Tamanho desconhecido',
+       'mwe-cancel-confim' => 'Tem a certeza que quer cancelar?',
+       'mwe-successfulupload' => 'Carregamento com sucesso',
+       'mwe-uploaderror' => 'Erro no carregamento',
+       'mwe-uploadwarning' => 'Aviso de carregamento',
+       'mwe-unknown-error' => 'Erro desconhecido:',
+       'mwe-return-to-form' => 'Regressar ao formulário',
+       'mwe-file-exists-duplicate' => 'O ficheiro é um duplicado do seguinte ficheiro:',
+       'mwe-fileexists' => 'Já existe um ficheiro com este nome. Por favor, verifique <b><tt>$1</tt></b> se não tem a certeza de que deseja alterá-lo.',
+       'mwe-fileexists-thumb' => '<center><b>Ficheiro existente</b></center>',
+       'mwe-ignorewarning' => 'Ignorar aviso e carregar ficheiro',
+       'mwe-file-thumbnail-no' => 'O nome de ficheiro começa por <b><tt>$1</tt></b>',
+       'mwe-go-to-resource' => 'Ir para a página do recurso',
+       'mwe-upload-misc-error' => 'Erro de carregamento desconhecido',
+       'mwe-wgfogg_warning_bad_extension' => 'Seleccionou um ficheiro com uma extensão não suportada (<a href="http://commons.wikimedia.org/wiki/Commons:Firefogg#Supported_File_Types">mais informações</a>).',
+       'mwe-upload-multi' => 'Carregar {{PLURAL:$1|ficheiro|ficheiros}}',
+       'mwe-review-upload' => 'Rever o carregamento {{PLURAL:$1|do ficheiro|dos ficheiros}}',
+       'mwe-credit-title' => 'Título: $1',
+       'mwe-loading_plugin' => "a carregar o ''plugin'' ...",
+       'mwe-select_playback' => 'Definir a preferência de reprodução',
+       'mwe-link_back' => 'Ligar atrás',
+       'mwe-error_swap_vid' => "Erro: o mv_embed não conseguiu trocar a marca ''(tag)'' vídeo pela interface mv_embed",
+       'mwe-add_to_end_of_sequence' => 'Adicionar ao fim da sequência',
+       'mwe-missing_video_stream' => "Ficheiro vídeo para esta ''stream'' em falta",
+       'mwe-play_clip' => 'Reproduzir clipe',
+       'mwe-pause_clip' => 'Pausar clipe',
+       'mwe-volume_control' => 'Controlo de volume',
+       'mwe-player_options' => 'Opções do leitor',
+       'mwe-closed_captions' => "Legendas ocultas ''(Closed captions)''",
+       'mwe-player_fullscreen' => 'Ecrã inteiro',
+       'mwe-next_clip_msg' => 'Reproduzir clipe seguinte',
+       'mwe-prev_clip_msg' => 'Reproduzir clipe anterior',
+       'mwe-current_clip_msg' => 'Continuar a reproduzir este clipe',
+       'mwe-seek_to' => 'Procurar $1',
+       'mwe-paused' => 'em pausa',
+       'mwe-download_segment' => 'Descarregar selecção:',
+       'mwe-download_full' => 'Descarregar todo o ficheiro vídeo:',
+       'mwe-download_right_click' => 'Para descarregar, clique com o botão direito do rato e seleccione <i>Guardar ligação como...</i>',
+       'mwe-download_clip' => 'Descarregar vídeo',
+       'mwe-download_text' => 'Descarregar texto (<a style="color:white" title="cmml" href="http://wiki.xiph.org/index.php/CMML">CMML</a> xml):',
+       'mwe-download' => 'Descarregar',
+       'mwe-share' => 'Partilhar',
+       'mwe-credits' => 'Créditos',
+       'mwe-clip_linkback' => 'Página fonte do clipe',
+       'mwe-chose_player' => 'Escolher leitor de vídeo',
+       'mwe-share_this_video' => 'Partilhar este vídeo',
+       'mwe-video_credits' => 'Créditos do vídeo',
+       'mwe-menu_btn' => 'Menu',
+       'mwe-close_btn' => 'Fechar',
+       'mwe-ogg-player-vlc-player' => 'Leitor VLC',
+       'mwe-ogg-player-videoElement' => 'Vídeo Ogg nativo',
+       'mwe-ogg-player-oggPlugin' => 'Plugin Ogg genérico',
+       'mwe-ogg-player-quicktime-mozilla' => 'Plugin QuickTime',
+       'mwe-ogg-player-quicktime-activex' => 'QuickTime ActiveX',
+       'mwe-ogg-player-cortado' => 'Java Cortado',
+       'mwe-ogg-player-flowplayer' => 'Flowplayer',
+       'mwe-ogg-player-kplayer' => 'Leitor Kaltura',
+       'mwe-ogg-player-selected' => '(seleccionado)',
+       'mwe-ogg-player-omtkplayer' => 'OMTK Flash Vorbis',
+       'mwe-generic_missing_plugin' => 'O seu navegador não parece suportar o seguinte tipo de reprodução: <b>$1</b><br />Visite a página <a href="http://commons.wikimedia.org/wiki/Commons:Media_help">Playback Methods</a> para descarregar um leitor.<br />',
+       'mwe-for_best_experience' => 'Para uma melhor experiência de reprodução de vídeo recomendamos::<br /><b><a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=mwEmbed">Firefox 3.5</a>.</b>',
+       'mwe-do_not_warn_again' => 'Ignorar por agora.',
+       'mwe-playerselect' => 'Leitores',
+       'mwe-read_before_embed' => '<a href="http://mediawiki.org/wiki/Security_Notes_on_Remote_Embedding" target="_new">Leia isto</a> antes de incorporar.',
+       'mwe-embed_site_or_blog' => 'Incorporar numa página',
+       'mwe-related_videos' => 'Vídeos relacionados',
+       'mwe-seeking' => 'a procurar',
+       'mwe-copy-code' => 'Copiar código',
+       'mwe-video-h264' => 'Vídeo H.264',
+       'mwe-video-flv' => 'Vídeo Flash',
+       'mwe-video-ogg' => 'Vídeo Ogg',
+       'mwe-video-audio' => 'Áudio Ogg',
+);
+
+/** Brazilian Portuguese (Português do Brasil)
+ * @author Hamilton Abreu
+ * @author Luckas Blade
+ */
+$messages['pt-br'] = array(
+       'mwe-preview_insert' => 'Prever inserção',
+       'mwe-sc_duration' => 'Duração',
+       'mwe-other_properties' => 'Outras propriedades',
+       'mwe-menu_options' => 'Opções',
+       'mwe-loading_user_rights' => 'A carregar direitos de usuário ...',
+       'mwe-other_options' => 'Outras opções',
+       'mwe-contextmenu_opt' => 'Habilitar menus de contexto',
+       'rsd_results_desc' => 'Resultados',
+       'rsd_results_prev' => 'anterior',
+       'mwe-cc_pd_title' => 'Domínio público',
+       'mwe-unknown_license' => 'Licença desconhecida',
+       'mwe-preview_insert_resource' => 'Prever inserção de recurso: $1',
+       'mwe-select_file' => 'Selecionar arquivo',
+       'mwe-summary' => 'Sumário',
+       'mwe-upload-unknown-size' => 'Tamanho desconhecido',
+       'mwe-unknown-error' => 'Erro desconhecido:',
+       'mwe-play_clip' => 'Tocar videoclipe',
+       'mwe-player_fullscreen' => 'Tela inteira',
+       'mwe-next_clip_msg' => 'Tocar próximo videoclipe',
+       'mwe-prev_clip_msg' => 'Tocar anterior videoclipe',
+       'mwe-current_clip_msg' => 'Continue a tocar este videoclipe',
+       'mwe-download_clip' => 'Baixar vídeo',
+       'mwe-download' => 'Baixar',
+       'mwe-related_videos' => 'Vídeos relacionados',
+);
+
+/** Russian (Русский)
+ * @author Ferrer
+ * @author Lockal
+ * @author Александр Сигачёв
+ */
+$messages['ru'] = array(
+       'mwe-crop' => 'Кадрировать изображение',
+       'mwe-apply_crop' => 'Применить кадрирование к изображению',
+       'mwe-reset_crop' => 'Сбросить кадрирование',
+       'mwe-insert_image_page' => 'Вставить на страницу',
+       'mwe-insert_into_sequence' => 'Вставить в последовательность',
+       'mwe-preview_insert' => 'Предпросмотр вставки',
+       'mwe-cancel_image_insert' => 'Отменить вставку',
+       'mwe-sc_fileopts' => 'Правка подробностей клипа',
+       'mwe-sc_inoutpoints' => 'Установить очки ввода-вывода',
+       'mwe-sc_overlays' => 'Перекрытия',
+       'mwe-sc_audio' => 'Аудиоконтроль',
+       'mwe-sc_duration' => 'Длительность',
+       'mwe-template_properties' => 'Настройки шаблона',
+       'mwe-custom_title' => 'Свой заголовок',
+       'mwe-edit_properties' => 'Править настройки',
+       'mwe-other_properties' => 'Другие настройки',
+       'mwe-resource_page' => 'Страница ресурса:',
+       'mwe-set_in_out_points' => 'Установить очки ввода-вывода',
+       'mwe-start_time' => 'Время начала',
+       'mwe-end_time' => 'Время окончания',
+       'mwe-preview_inout' => 'Просмотр точек ввода-вывода',
+       'mwe-edit-tools' => 'Инструменты редактирования',
+       'mwe-inline-description' => 'Заголовок',
+       'mwe-edit-video-tools' => 'Инструменты редактирования видео:',
+       'mwe-duration' => 'Длительность:',
+       'mwe-upload-subs-file' => 'Загрузить субтитры',
+       'mwe-add-subs-file-title' => 'Выбор субтитров для загрузки',
+       'mwe-error-only-srt' => 'Сейчас могут загружаться только srt-файлы.',
+       'mwe-watch-video' => 'Просмотреть видео',
+       'mwe-select-other-language' => 'Выбрать другой язык',
+       'mwe-saving' => 'сохранение…',
+       'mwe-select_transcript_set' => 'Выбор субтитров',
+       'mwe-auto_scroll' => 'автопрокрутка',
+       'mwe-close' => 'закрыть',
+       'mwe-improve_transcript' => 'Улучшить',
+       'mwe-no_text_tracks_found' => 'Не найдено текстовых дорожек',
+       'mwe-add-edit-subs' => 'Добавить/править субтитры',
+       'mwe-transition_in' => 'Переход в',
+       'mwe-transition_out' => 'Переход из',
+       'mwe-effects' => 'Набор эффектов',
+       'mwe-remove_transition' => 'Удалить переход',
+       'mwe-edit_transin' => 'Изменить переход в клипе',
+       'mwe-edit_transout' => 'Изменить переход-выход в клипе',
+       'mwe-add-transition' => 'Добавить переход',
+       'mwe-menu_clipedit' => 'Изменить медиа',
+       'mwe-menu_transition' => 'Переходы и эффекты',
+       'mwe-menu_cliplib' => 'Добавить медиа',
+       'mwe-menu_resource_overview' => 'Обзор ресурсов',
+       'mwe-menu_options' => 'Настройки',
+       'mwe-loading_timeline' => 'Загружается хронология …',
+       'mwe-loading_user_rights' => 'Загружаются права участников …',
+       'mwe-no_edit_permissions' => 'У вас нет разрешения сохранять изменения последовательности',
+       'mwe-edit_clip' => 'Редактировать клип',
+       'mwe-edit_save' => 'Сохранить изменения последовательности',
+       'mwe-saving_wait' => 'Идёт сохранение (пожалуйста, подождите)',
+       'mwe-save_done' => 'Сохранение завершено',
+       'mwe-edit_cancel' => 'Отменить правку последовательности',
+       'mwe-edit_cancel_confirm' => 'Вы уверены, что хотите отменить Вашу правку? Изменения будут потеряны.',
+       'mwe-zoom_in' => 'Увеличить',
+       'mwe-zoom_out' => 'Уменьшить',
+       'mwe-cut_clip' => 'Кадрирование клипов',
+       'mwe-expand_track' => 'Развернуть трек',
+       'mwe-collapse_track' => 'Свернуть трек',
+       'mwe-play_from_position' => 'Проигрывать с позиции линии воспроизведения',
+       'mwe-pixle2sec' => 'пикселов в секунду',
+       'mwe-rmclip' => 'Удалить клип',
+       'mwe-clip_in' => 'добавить клип',
+       'mwe-clip_out' => 'убрать клип',
+       'mwe-no_selected_resource' => '<h3>Не выбран ресурс</h3>Выберите клип для редактирования.',
+       'mwe-error_edit_multiple' => '<h3>Выбрано несколько ресурсов</h3> Выберите один клип для редактирования.',
+       'mwe-editor_options' => 'Настройки редактора',
+       'mwe-editor_mode' => 'Режим редактора',
+       'mwe-simple_editor_desc' => 'простой редактор (стиль iMovie)',
+       'mwe-advanced_editor_desc' => 'улучшенный редактор (стиль Final Cut)',
+       'mwe-other_options' => 'Другие настройки',
+       'mwe-contextmenu_opt' => 'Включить контекстные меню',
+       'mwe-sequencer_credit_line' => 'Разработано <a href="http://kaltura.com">Kaltura, Inc</a> в сотрудничестве с <a href="http://wikimediafoundation.org/wiki/Home">Фондом Викимедиа</a> (<a href="#">подробнее</a>).',
+       'mwe-loading_txt' => 'загрузка …',
+       'mwe-error_load_lib' => 'Ошибка. JavaScript $1 не доступен или не определяет $2',
+       'mwe-loading-add-media-wiz' => 'Загрузка мастера добавления медиа',
+       'mwe-apiproxy-setup' => 'Настройка API-прокси',
+       'mwe-load-drag-item' => 'Загрузка перетащенного элемента',
+       'mwe-ok' => 'OK',
+       'mwe-cancel' => 'Отмена',
+       'mwe-setting-up-proxy' => 'Настройка прокси…',
+       'mwe-re-try' => 'Повторить API-запрос',
+       'mwe-re-trying' => 'Повторение API-запроса…',
+       'mwe-proxy-not-ready' => 'Прокси не настроен',
+       'mwe-please-login' => 'Вы не <a target="_new" href="$1">представились системе</a> $2 или mwEmbed не был включён. Решите проблему и затем повторите запрос.',
+       'mwe-remember-loging' => 'Общее напоминание о безопасности. Представляйтесь системе только в том случае, если в строке адреса отображается адрес ожидаемого сайта.',
+       'fogg-select_file' => 'Выберите файл',
+       'fogg-select_new_file' => 'Выберите новый файл',
+       'fogg-select_url' => 'Выберите URL',
+       'fogg-save_local_file' => 'Сохранить Ogg',
+       'fogg-check_for_firefogg' => 'Проверка Firefogg …',
+       'fogg-installed' => 'Firefogg установлен',
+       'fogg-for_improved_uploads' => 'Для улучшенных загрузок:',
+       'fogg-please_install' => '<a href="$1">Установить Firefogg</a>. Подробнее <a href="http://commons.wikimedia.org/wiki/Commons:Firefogg">о Firefogg</a>',
+       'fogg-use_latest_firefox' => 'Пожалуйста, сначала установите <a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=firefogg">Firefox 3.5</a> (или выше). <i>Затем повторно обратитесь к этой странице, чтобы установить расширение <b>Firefogg</b>.</i>',
+       'fogg-passthrough_mode' => 'Выбранный файл уже Ogg или не является видео-файлом',
+       'fogg-transcoding' => 'Перекодирование видео в Ogg',
+       'fogg-encoding-done' => 'Перекодирование завершено',
+       'fogg-badtoken' => 'Данный маркер не действителен',
+       'fogg-preview' => 'Предпросмотр видео',
+       'fogg-hidepreview' => 'Скрыть предпросмотр',
+       'mwe-imported_from' => '$1 импортирован из [$2 $3]. Для получения дополнительной информации см. исходную [$4 страницу ресурса].',
+       'mwe-stream_title' => '$1 $2 до $3',
+       'fogg-help-sticky' => 'Справка (нажмите для прикрепления)',
+       'fogg-cg-preset' => 'Предустановки: <strong>$1</strong>',
+       'fogg-cg-quality' => 'Основные настройки качества и разрешения',
+       'fogg-cg-meta' => 'Метаданные для клипа',
+       'fogg-cg-range' => 'Диапазон кодирования',
+       'fogg-cg-advVideo' => 'Расширенное управление кодированием видео',
+       'fogg-cg-advAudio' => 'Расширенное управление кодированием звука',
+       'fogg-preset-custom' => 'Пользовательские настройки',
+       'fogg-webvideo-desc' => 'Веб-видео Theora, Vorbis 400 кбит/с, максимальная ширина 400 пикс.',
+       'fogg-savebandwidth-desc' => 'Theora для низкоскоростных каналов, Vorbis 164 кбит/с, максимальная ширина 200 пикс.',
+       'fogg-highquality-desc' => 'Theora высокого качества, Vorbis, максимальная ширина 1080 пикс.',
+       'fogg-videoQuality-title' => 'Качество видео',
+       'fogg-videoQuality-help' => 'Используется для установки <i>видимого качества</i> закодированного видео (не используется, если вы установите битрейт в расширенных настройках).',
+       'fogg-starttime-title' => 'Начать с секунды',
+       'fogg-starttime-help' => 'Кодировать только начиная с времени, указанного в секундах',
+       'fogg-endtime-title' => 'Закончить на секунду',
+       'fogg-endtime-help' => 'Кодировать только до указанного времени, в секундах',
+       'fogg-audioQuality-title' => 'Качество звука',
+       'fogg-audioQuality-help' => 'Используется для установки <i>качества звука</i> закодированного аудио (не используется, если вы установите битрейт в расширенных настройках).',
+       'fogg-videoCodec-title' => 'Видеокодек',
+       'fogg-videoCodec-help' => 'Используется для выбора видеокодека клипа. В настоящее время поддерживается только Theora. Подробнее о <a target="_new" href="http://ru.wikipedia.org/wiki/Theora">кодеке Theora</a>.',
+       'fogg-audioCodec-title' => 'Аудиокодек',
+       'fogg-audioCodec-help' => 'Используется для выбора аудиокодека клипа. В настоящее время поддерживается только Vorbis. Подробнее о <a target="_new" href="http://ru.wikipedia.org/wiki/Vorbis">кодеке Vorbis</a>.',
+       'fogg-width-title' => 'Ширина видео',
+       'fogg-width-help' => 'Изменить размер до заданной ширины.',
+       'fogg-height-title' => 'Высота видео',
+       'fogg-height-help' => 'Изменить размер до заданной высоты.',
+       'fogg-videoBitrate-title' => 'Битрейт видео',
+       'fogg-videoBitrate-help' => 'Битрейт видео определяет битрейт кодирования видео в кбит/с',
+       'fogg-twopass-title' => 'Двухпроходное кодирование',
+       'fogg-twopass-help' => 'Двухпроходное кодирование позволяет повысить качество кодирования, посредством проведения двух проходов по видео файлу',
+       'fogg-framerate-title' => 'Частота кадров',
+       'fogg-framerate-help' => 'Частота кадров видео. Подробнее о <a target="_new" href="http://ru.wikipedia.org/wiki/Частота_кадров">частоте кадров</a>.',
+       'fogg-aspect-title' => 'Формат кадра',
+       'fogg-aspect-help' => 'Соотношение ширины и высоты кадра может составлять 4:3 или 16:9. Подробнее о <a target="_new" href="http://ru.wikipedia.org/wiki/Соотношение_сторон_экрана">формате кадра</a>.',
+       'fogg-keyframeInterval-title' => 'Интервал между ключевыми кадрами',
+       'fogg-keyframeInterval-help' => 'Интервал между ключевыми кадрами. Замечание. Большинство кодеков включает ключевые кадры в случае, если разница между кадрами больше размера ключевых кадров кодирования. Подробнее о <a href="http://ru.wikipedia.org/wiki/Типы_кадров">ключевых кадрах</a>.',
+       'fogg-denoise-title' => 'Фильтр удаления шума',
+       'fogg-denoise-help' => 'Входной фильтр удаления шума с видео. Подробнее о <a href="http://en.wikipedia.org/wiki/Video_denoising">об удалении шума</a>.',
+       'fogg-novideo-title' => 'Нет видео',
+       'fogg-novideo-help' => 'отключить видео на выходе',
+       'fogg-audioBitrate-title' => 'Битрейт аудио',
+       'fogg-samplerate-title' => 'Частота дискретизации аудио',
+       'fogg-samplerate-help' => 'установить выходную частоту дискретизации (в Гц).',
+       'fogg-noaudio-title' => 'Без звука',
+       'fogg-noaudio-help' => 'отключить звук на выходе',
+       'fogg-title-title' => 'Название',
+       'fogg-title-help' => 'Название для вашего клипа',
+       'fogg-artist-title' => 'Имя автора',
+       'fogg-artist-help' => 'Автор этого клипа',
+       'fogg-date-title' => 'Дата',
+       'fogg-date-help' => 'Дата создания или выпуска материала',
+       'fogg-location-title' => 'Местонахождение',
+       'fogg-location-help' => 'Местоположение материала',
+       'fogg-organization-title' => 'Организация',
+       'fogg-organization-help' => 'Название организации (студии)',
+       'fogg-copyright-title' => 'Авторские права',
+       'fogg-copyright-help' => 'Авторские права на клип',
+       'fogg-license-title' => 'Лицензия',
+       'fogg-license-help' => 'Лицензия на клип (желательно URL на Creative Commons).',
+       'fogg-contact-title' => 'Контакты',
+       'fogg-contact-help' => 'Контактная информация',
+       'mwe-add_media_wizard' => 'Мастер добавления медиа',
+       'mwe-media_search' => 'Поиск медиа',
+       'rsd_box_layout' => 'Макет коробки',
+       'rsd_list_layout' => 'Макет списка',
+       'rsd_results_desc' => 'Результаты $1 — $2',
+       'rsd_results_desc_total' => 'Результаты с $1 по $2 из $3',
+       'rsd_results_next' => 'следующие',
+       'rsd_results_prev' => 'предыдущие',
+       'rsd_no_results' => 'Нет результатов поиска для <b>$1</b>',
+       'mwe-upload_tab' => 'Загрузка',
+       'rsd_layout' => 'Макет:',
+       'rsd_resource_edit' => 'Править ресурс: $1',
+       'mwe-resource_description_page' => 'Страница описания ресурса',
+       'mwe-link' => 'ссылка',
+       'rsd_local_resource_title' => 'Название локального ресурса',
+       'rsd_do_insert' => 'Выполнить вставку',
+       'mwe-cc_by_title' => 'Указание авторов',
+       'mwe-cc_nc_title' => 'Некоммерческое',
+       'mwe-cc_nd_title' => 'Без производных работ',
+       'mwe-cc_sa_title' => 'С сохранением условий',
+       'mwe-cc_pd_title' => 'Общественное достояние',
+       'mwe-unknown_license' => 'Неизвестная лицензия',
+       'mwe-no_import_by_url' => 'Этот участник или вики <b>не может</b> импортировать объекты с удалённых URL.<p>Возможно, вам следует представиться системе?</p><p>Установлено ли для вас разрешение upload_by_url?<br />Включена ли в данной вики настройка <a href="http://www.mediawiki.org/wiki/Manual:$wgAllowCopyUploads">$wgAllowCopyUploads</a>?</p>',
+       'mwe-results_from' => 'Результаты <a href="$1" target="_new" >$2</a>',
+       'mwe-missing_desc_see_source' => 'Для этого объекта отсутствует описание. Пожалуйста, обратитесь к [$1 исходному источнику] и помогите описать объект.',
+       'rsd_config_error' => 'Ошибка настройки мастера добавления. $1',
+       'mwe-your_recent_uploads' => 'Ваши недавние загрузки в $1',
+       'mwe-upload_a_file' => 'Загрузить новый файл в $1',
+       'mwe-resource_page_desc' => 'Описание страницы ресурса:',
+       'mwe-edit_resource_desc' => 'Править вики-текст описания ресурса:',
+       'mwe-local_resource_title' => 'Название локального ресурса:',
+       'mwe-watch_this_page' => 'Наблюдать за этой страницей',
+       'mwe-do_import_resource' => 'Импортировать ресурс',
+       'mwe-update_preview' => 'Обновить предпросмотр',
+       'mwe-cancel_import' => 'Отменить импорт',
+       'mwe-importing_asset' => 'Импортирование объекта',
+       'mwe-preview_insert_resource' => 'Предпросмотр вставки ресурса: $1',
+       'mwe-checking-resource' => 'Проверка ресурса',
+       'mwe-resource-needs-import' => 'Необходим импорт ресурса $1 в $2',
+       'mwe-ftype-svg' => 'Векторный файл SVG',
+       'mwe-ftype-jpg' => 'Файла изображения JPEG',
+       'mwe-ftype-png' => 'Файла изображения PNG',
+       'mwe-ftype-oga' => 'Аудио-файл OGG',
+       'mwe-ftype-ogg' => 'Видео-файл OGG',
+       'mwe-ftype-unk' => 'Неизвестный формат файла',
+       'rsd-wiki_commons-title' => 'Викисклад',
+       'rsd-wiki_commons' => 'Викисклад (Wikimedia Commons) — архив доступных под свободными лицензиями учебных медиа-материалов (изображениё, аудио и видео)',
+       'rsd-this_wiki-title' => 'Эта вики',
+       'rsd-this_wiki-desc' => 'Локальная вики-система',
+       'rsd-archive_org-desc' => 'Internet Archive — цифровая библиотека культурных артефактов',
+       'rsd-flickr-desc' => 'Flickr.com — сайт фотохостинга',
+       'rsd-metavid-desc' => 'Metavid.org — архив материалов слушаний Палаты представителей и Сената США',
+       'mwe-select_file' => 'Выберите файл',
+       'mwe-more_licence_options' => 'Дополнительные параметры лицензии, доступны на <a href="$1">обычной странице загрузки</a>',
+       'mwe-select_ownwork' => 'Я загружаю полностью свою собственную работу и лицензирую её на условиях:',
+       'mwe-licence_cc-by-sa' => 'Creative Commons Share Alike (3.0)',
+       'mwe-upload' => 'Загрузить файл',
+       'mwe-destfilename' => 'Новое имя файла:',
+       'mwe-summary' => 'Описание изменений',
+       'mwe-error_not_loggedin' => 'Судя по всему, вы не представились системе или не имеете разрешения на загрузку.',
+       'mwe-watch-this-file' => 'Просмотреть этот файл',
+       'mwe-ignore-any-warnings' => 'Игнорировать все предупреждения',
+       'mwe-upload-transcode-in-progress' => 'Перекодирование и загрузка (не закрывайте это окно)',
+       'mwe-upload-in-progress' => 'Идёт загрузка (не закрывайте это окно)',
+       'mwe-upload-transcoded-status' => 'Перекодировано',
+       'mwe-uploaded-status' => 'Загружено',
+       'mwe-upload-stats-fileprogress' => '$1 из $2',
+       'mwe-upload_completed' => 'Ваша загрузка выполнена',
+       'mwe-upload_done' => '<a href="$1">Ваша загрузка <i>должна быть</i> доступной.</a>',
+       'mwe-upload-unknown-size' => 'Неизвестный размер',
+       'mwe-cancel-confim' => 'Вы уверены, что хотите отменить?',
+       'mwe-successfulupload' => 'Загрузка успешно завершена',
+       'mwe-uploaderror' => 'Ошибка загрузки',
+       'mwe-uploadwarning' => 'Предупреждение при загрузке',
+       'mwe-unknown-error' => 'Неизвестная ошибка:',
+       'mwe-return-to-form' => 'Вернуться к форме',
+       'mwe-file-exists-duplicate' => 'Этот файл является дубликатом следующих файлов:',
+       'mwe-fileexists' => 'Файл с этим именем уже существует. Пожалуйста, проверьте <b><tt>$1</tt></b>, если вы не уверены, что хотите заменить его.',
+       'mwe-fileexists-thumb' => '<center><b>Существующий файл</b></center>',
+       'mwe-ignorewarning' => 'Игнорировать предупреждения и всё равно сохранить файл',
+       'mwe-file-thumbnail-no' => 'Название файла начинается с <b><tt>$1</tt></b>',
+       'mwe-go-to-resource' => 'Перейти на страницу ресурсов',
+       'mwe-upload-misc-error' => 'Неизвестная ошибка загрузки',
+       'mwe-wgfogg_warning_bad_extension' => 'Вы выбрали файл с неподдерживаемым расширением (<a href="http://commons.wikimedia.org/wiki/Commons:Firefogg#Supported_File_Types">дополнительная информация</a>).',
+       'mwe-upload-multi' => 'Загрузить {{PLURAL:$1|файл|файлы}}',
+       'mwe-review-upload' => 'Просмотреть {{PLURAL:$1|загрузку файла|загрузки файлов}}',
+       'mwe-credit-title' => 'Название: $1',
+       'mwe-loading_plugin' => 'загрузка плагина ...',
+       'mwe-select_playback' => 'Установить настройки воспроизведения',
+       'mwe-link_back' => 'Обратная ссылка',
+       'mwe-error_swap_vid' => 'Ошибка: mv_embed не может поменять тег видео для интерфейса mv_embed',
+       'mwe-add_to_end_of_sequence' => 'Добавить в конец последовательности',
+       'mwe-missing_video_stream' => 'Видеофайл для этого потока отсутствует',
+       'mwe-play_clip' => 'Воспроизвести клип',
+       'mwe-pause_clip' => 'Приостановить клип',
+       'mwe-volume_control' => 'Регулировка громкости',
+       'mwe-player_options' => 'Настройки проигрывателя',
+       'mwe-closed_captions' => 'Субтитры',
+       'mwe-player_fullscreen' => 'На весь экран',
+       'mwe-next_clip_msg' => 'Воспроизвести следующий клип',
+       'mwe-prev_clip_msg' => 'Воспроизвести предыдущий клип',
+       'mwe-current_clip_msg' => 'Продолжить воспроизведение этого клипа',
+       'mwe-seek_to' => 'Перейти к $1',
+       'mwe-paused' => 'пауза',
+       'mwe-download_segment' => 'Выбор загрузки:',
+       'mwe-download_full' => 'Загрузить полный видео-файл:',
+       'mwe-download_right_click' => 'Чтобы загрузить, нажмите правую кнопку и выберите «Сохранить объект как…»',
+       'mwe-download_clip' => 'Загрузить видео',
+       'mwe-download_text' => 'Загрузить текст (<a style="color:white" title="cmml" href="http://wiki.xiph.org/index.php/CMML">CMML</a> xml):',
+       'mwe-download' => 'Загрузить',
+       'mwe-share' => 'Поделиться',
+       'mwe-credits' => 'Создатели',
+       'mwe-clip_linkback' => 'Исходная страница клипа',
+       'mwe-chose_player' => 'Выбор проигрывателя',
+       'mwe-share_this_video' => 'Поделиться этим видео',
+       'mwe-video_credits' => 'О создателях видео',
+       'mwe-menu_btn' => 'Меню',
+       'mwe-close_btn' => 'Закрыть',
+       'mwe-ogg-player-vlc-player' => 'Проигрыватель VLC',
+       'mwe-ogg-player-videoElement' => 'Встроенное Ogg-видео',
+       'mwe-ogg-player-oggPlugin' => 'Общий плагин Ogg',
+       'mwe-ogg-player-quicktime-mozilla' => 'Плагин QuickTime',
+       'mwe-ogg-player-quicktime-activex' => 'QuickTime ActiveX',
+       'mwe-ogg-player-cortado' => 'Java Cortado',
+       'mwe-ogg-player-flowplayer' => 'Flowplayer',
+       'mwe-ogg-player-kplayer' => 'Проигрыватель Kaltura',
+       'mwe-ogg-player-selected' => '(выбрано)',
+       'mwe-ogg-player-omtkplayer' => 'OMTK Flash Vorbis',
+       'mwe-generic_missing_plugin' => 'Ваш браузер, судя по всему, не поддерживает следующий тип воспроизведения: <b>$1</b><br />Посетите страницу <a href="http://commons.wikimedia.org/wiki/Commons:Медиапомощь">Способы воспроизведения</a>, чтобы загрузить проигрыватель.<br />',
+       'mwe-for_best_experience' => 'Для хорошего воспроизведения видео мы рекомендуем: <br /><b><a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=mwEmbed">Firefox 3.5</a>.</b>',
+       'mwe-do_not_warn_again' => 'Пока отклонить.',
+       'mwe-playerselect' => 'Проигрыватели',
+       'mwe-read_before_embed' => 'Пожалуйста, <a href="http://mediawiki.org/wiki/Security_Notes_on_Remote_Embedding" target="_new">прочтите это</a> перед встраиванием!',
+       'mwe-embed_site_or_blog' => 'Вставить на страницу',
+       'mwe-related_videos' => 'Связанные видео',
+       'mwe-seeking' => 'поиск',
+       'mwe-copy-code' => 'Копировать код',
+       'mwe-video-h264' => 'Видео H.264',
+       'mwe-video-flv' => 'Flash-видео',
+       'mwe-video-ogg' => 'Ogg-видео',
+       'mwe-video-audio' => 'Ogg-аудио',
+);
+
+/** Yakut (Саха тыла)
+ * @author HalanTul
+ */
+$messages['sah'] = array(
+       'mwe-crop' => 'Ойууну быс',
+       'mwe-apply_crop' => 'Ойууга төгүрүччу быһыыны тутун',
+       'mwe-reset_crop' => 'Быспыты төннөр',
+       'mwe-insert_image_page' => 'Сирэйгэ киллэрэн биэр',
+       'mwe-preview_insert' => 'Киллэриини угуох иннинэ көрүү',
+       'mwe-cancel_image_insert' => 'Киллэриини төннөр',
+       'mwe-sc_fileopts' => 'Клип ымпыгын-чымпыгын көннөрүү',
+       'mwe-sc_duration' => 'Уһуна',
+       'mwe-custom_title' => 'Атын аат',
+       'mwe-edit_properties' => 'Туруоруулары көннөрүү',
+       'mwe-other_properties' => 'Атын туруоруулар',
+       'mwe-resource_page' => 'Ресурс сирэйэ:',
+       'mwe-start_time' => 'Саҕаланар кэмэ',
+       'mwe-end_time' => 'Түмүктэнэр кэмэ',
+       'mwe-auto_scroll' => 'автопрокрутка',
+       'mwe-close' => 'сап',
+       'mwe-improve_transcript' => 'Тупсарарга',
+       'mwe-no_text_tracks_found' => 'Тиэкистээх дорожкалар көстүбэтилэр',
+       'mwe-menu_options' => 'Туруоруулар',
+       'mwe-edit_clip' => 'Клибы уларытыы',
+       'mwe-zoom_in' => 'Улаатыннар',
+       'mwe-zoom_out' => 'Кыччат',
+);
+
+/** Slovak (Slovenčina)
+ * @author Helix84
+ * @author Rudko
+ */
+$messages['sk'] = array(
+       'mwe-crop' => 'Orezať obrázok',
+       'mwe-apply_crop' => 'Použiť orezanie na obrázok',
+       'mwe-reset_crop' => 'Vrátiť orezanie',
+       'mwe-insert_image_page' => 'Vložiť na stránku',
+       'mwe-insert_into_sequence' => 'Vložiť do sekvencie',
+       'mwe-preview_insert' => 'Náhľad vloženia',
+       'mwe-cancel_image_insert' => 'Zrušiť vloženie',
+       'mwe-sc_fileopts' => 'Úprava podrobností klipu',
+       'mwe-sc_inoutpoints' => 'Nastaviť body priblíženia/vzdialenia',
+       'mwe-sc_overlays' => 'Vrstvy',
+       'mwe-sc_audio' => 'Ovládanie zvuku',
+       'mwe-sc_duration' => 'Trvanie',
+       'mwe-template_properties' => 'Vlastnosti šablóny',
+       'mwe-custom_title' => 'Vlastný názov',
+       'mwe-edit_properties' => 'Upraviť vlastnosti',
+       'mwe-other_properties' => 'Iné vlastnosti',
+       'mwe-resource_page' => 'Stránka so zdrojmi:',
+       'mwe-set_in_out_points' => 'Nastaviť body priblíženia/vzdialenia',
+       'mwe-start_time' => 'Čas začiatku',
+       'mwe-end_time' => 'Čas konca',
+       'mwe-preview_inout' => 'Náhľad/prehranie bodov priblíženia/vzdialenia',
+       'mwe-select_transcript_set' => 'Vybrať vrstvy',
+       'mwe-auto_scroll' => 'posúvať automaticky',
+       'mwe-close' => 'zatvoriť',
+       'mwe-improve_transcript' => 'Vylepšiť',
+       'mwe-no_text_tracks_found' => 'Neboli nájdené žiadne textové stopy',
+       'mwe-transition_in' => 'Prechod do',
+       'mwe-transition_out' => 'Prechod z',
+       'mwe-effects' => 'Zásobník efektov',
+       'mwe-remove_transition' => 'Odstrániť prechod',
+       'mwe-edit_transin' => 'Upraviť prechod do klipu',
+       'mwe-edit_transout' => 'Upraviť prechod z klipu',
+       'mwe-menu_clipedit' => 'Upraviť multimédiá',
+       'mwe-menu_transition' => 'Prechody a efekty',
+       'mwe-menu_cliplib' => 'Pridať multimédiá',
+       'mwe-menu_resource_overview' => 'Prehľad zdroja',
+       'mwe-menu_options' => 'Možnosti',
+       'mwe-loading_timeline' => 'Načítava sa časová os ...',
+       'mwe-loading_user_rights' => 'Načítavajú sa oprávnenia používateľov ...',
+       'mwe-no_edit_permissions' => 'Nemáte oprávnenie ukladať zmenu tejto sekvencie',
+       'mwe-edit_clip' => 'Upraviť klip',
+       'mwe-edit_save' => 'Uložiť zmeny sekvencie',
+       'mwe-saving_wait' => 'Prebieha ukladanie (prosím, čakajte)',
+       'mwe-save_done' => 'Ukladanie dokončené',
+       'mwe-edit_cancel' => 'Zrušiť úpravu sekvencie',
+       'mwe-edit_cancel_confirm' => 'Ste si istý, že chcete zrušiť svoje úpravy? Zmeny sa stratia.',
+       'mwe-zoom_in' => 'Priblížiť',
+       'mwe-zoom_out' => 'Oddialiť',
+       'mwe-cut_clip' => 'Strih klipov',
+       'mwe-expand_track' => 'Rozšíriť stopu',
+       'mwe-collapse_track' => 'Zmrštiť stopu',
+       'mwe-play_from_position' => 'Prehrať od značky',
+       'mwe-pixle2sec' => 'pixle na sekundy',
+       'mwe-rmclip' => 'Odstrániť klip',
+       'mwe-no_selected_resource' => '<h3>Nebol vybraný žiadny zdroj</h3> Úpravu začnete vybraním klipu.',
+       'mwe-error_edit_multiple' => '<h3>Boli vybrané viaceré zdroje</h3> Úpravu začnete vybraním jediného klipu.',
+       'mwe-editor_options' => 'Možnosti editora',
+       'mwe-editor_mode' => 'Režim editora',
+       'mwe-simple_editor_desc' => 'jednoduchý editor (v štýle iMovie)',
+       'mwe-advanced_editor_desc' => 'pokročilý editor (v štýle Final Cut)',
+       'mwe-other_options' => 'Ďalšie možnosti',
+       'mwe-contextmenu_opt' => 'Zapnúť kontextové menu',
+       'mwe-sequencer_credit_line' => 'Vyvinula <a href="http://kaltura.com">Kaltura, Inc.</a> v spolupráci s <a href="http://wikimediafoundation.org/wiki/Home">Wikimedia Foundation</a> (<a href="#">ďalšie informácie</a>).',
+       'mwe-loading_txt' => 'načítava sa ...',
+       'mwe-error_load_lib' => 'Error: JavaScript $1 nebolo možné získať alebo neobsahuje definíciu $2',
+       'fogg-select_file' => 'Vybrať súbor',
+       'fogg-select_new_file' => 'Vybrať nový súbor',
+       'fogg-select_url' => 'Vybrať URL',
+       'fogg-save_local_file' => 'Uložiť Ogg',
+       'fogg-check_for_firefogg' => 'Kontroluje sa Firefogg ...',
+       'fogg-installed' => 'Firefogg je nainštalovaný',
+       'fogg-for_improved_uploads' => 'Na vylepšenie nahrávania:',
+       'fogg-please_install' => '<a href="$1">si nainštalujte Firefogg</a>. Ďalšie informácie o <a href="http://commons.wikimedia.org/wiki/Commons:Firefogg">Firefogg</a>',
+       'fogg-use_latest_firefox' => 'Najprv si prosím nainštalujte <a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=firefogg">Firefox 3.5</a> (alebo novší). <i>Po opätovnom navštívení tejto stránky si nainštalujte rozšírenie <b>Firefogg</b>.</i>',
+       'fogg-passthrough_mode' => 'Váš vybraný súbor je už Ogg alebo to nie je videosúbor',
+       'fogg-transcoding' => 'Prebieha prekódovanie videosúboru do Ogg',
+       'fogg-encoding-done' => 'Prekódovanie dokončené',
+       'fogg-badtoken' => 'Token nie je platný',
+       'fogg-preview' => 'Náhľad videa',
+       'fogg-hidepreview' => 'Skryť náhľad',
+       'mwe-imported_from' => '$1 je importovaný z [$2 $3]. Ďalšie informácie na pôvodnej [$4 stránke zdrojov].',
+       'mwe-stream_title' => '$1 $2 na $3',
+       'fogg-help-sticky' => 'Pomoc (prilepiť kliknutím)',
+       'fogg-cg-preset' => 'Predvoľba: <strong>$1</strong>',
+       'fogg-cg-quality' => 'Základná kvalita a ovládanie rozlíšenia',
+       'fogg-cg-meta' => 'Metadáta klipu',
+       'fogg-cg-range' => 'Rozsah kódovania',
+       'fogg-cg-advVideo' => 'Pokročilé možnosti kódovania videa',
+       'fogg-cg-advAudio' => 'Pokročilé možnosti kódovania zvuku',
+       'fogg-preset-custom' => 'Vlastné nastavenie',
+       'mwe-add_media_wizard' => 'Sprievodca pridaním multimédia',
+       'mwe-media_search' => 'Hľadanie multimédií',
+       'rsd_box_layout' => 'Rozloženie okna',
+       'rsd_list_layout' => 'Rozloženie zoznamu',
+       'rsd_results_desc' => 'Výsledky $1 až $2',
+       'rsd_results_desc_total' => 'Výsledky $1 až $2 z $3',
+       'rsd_results_next' => 'ďalej',
+       'rsd_results_prev' => 'späť',
+       'rsd_no_results' => 'Žiadne výsledky vyhľadávania <b>$1</b>',
+       'mwe-upload_tab' => 'Nahrať',
+       'rsd_layout' => 'Rozloženie:',
+       'rsd_resource_edit' => 'Upraviť zdroj: $1',
+       'mwe-resource_description_page' => 'Stránka s popisom zdroja',
+       'mwe-link' => 'odkaz',
+       'rsd_local_resource_title' => 'Miestny názov zdroja',
+       'rsd_do_insert' => 'Vložiť',
+       'mwe-cc_by_title' => 'uvedenie autora',
+       'mwe-cc_nc_title' => 'nekomerčné využitie',
+       'mwe-cc_nd_title' => 'žiadne odvodené diela',
+       'mwe-cc_sa_title' => 'zachovať licenciu',
+       'mwe-cc_pd_title' => 'voľné dielo',
+       'mwe-unknown_license' => 'neznáma licencia',
+       'mwe-no_import_by_url' => 'Používateľ alebo wiki <b>nemôže</b> importovať zdroje zo vzdialených URL.</p><p>Musíte sa prihlásiť?</p><p>Ak sú v poriadku oprávnenia, možno treba zapnúť $wgAllowCopyUploads (<a href="http://www.mediawiki.org/wiki/Manual:$wgAllowCopyUploads">ďalšie informácie</a>).</p>',
+       'mwe-results_from' => 'Výsledky z <a href="$1" target="_new" >$2</a>',
+       'mwe-missing_desc_see_source' => 'Prvku chýba popis. Pozrite si prosím [$1 pôvodný zdroj] a pomôžte ho popísať.',
+       'rsd_config_error' => 'Chyba Sprievodcu pridaním multimédia: $1',
+       'mwe-your_recent_uploads' => 'Nedávno ste naharali',
+       'mwe-upload_a_file' => 'Nahrať nový súbor',
+       'mwe-resource_page_desc' => 'Popisná stránka zdroja:',
+       'mwe-edit_resource_desc' => 'Upraviť popis zdroja ako wiki text:',
+       'mwe-local_resource_title' => 'Lokálny názov zdroja:',
+       'mwe-watch_this_page' => 'Sledovať túto stránku',
+       'mwe-do_import_resource' => 'Importovať zdroj',
+       'mwe-update_preview' => 'Aktualizovať náhľad',
+       'mwe-cancel_import' => 'Zrušiť import',
+       'mwe-importing_asset' => 'Importuje sa položka',
+       'mwe-preview_insert_resource' => 'Náhľad vloženia zdroja: $1',
+       'mwe-ftype-svg' => 'vektorový súbor SVG',
+       'mwe-ftype-jpg' => 'obrázkový súbor JPEG',
+       'mwe-ftype-png' => 'obrázkový súbor PNG',
+       'mwe-ftype-oga' => 'zvukový súbor OGG',
+       'mwe-ftype-ogg' => 'videosúbor Ogg',
+       'mwe-ftype-unk' => 'neznámy formát súboru',
+       'mwe-select_file' => 'Vybrať súbor',
+       'mwe-more_licence_options' => 'Ďalšie možnosti licencovania nájdete na <a href="$1">bežnej nahrávacej stránke</a>',
+       'mwe-select_ownwork' => 'Nahrávam dielo, ktoré je kompletne moje vlastné a licencujem ho za podmienok:',
+       'mwe-licence_cc-by-sa' => 'Creative Commons Share Alike (3.0)',
+       'mwe-upload' => 'Nahrať súbor',
+       'mwe-destfilename' => 'Cieľový názov súboru:',
+       'mwe-summary' => 'Zhrnutie',
+       'mwe-error_not_loggedin' => 'Zdá sa, že nie ste prihlásený alebo nemáte oprávnenie nahrávať.',
+       'mwe-upload-transcode-in-progress' => 'Prebieha prekódovanie a nahrávanie (nezatvárajte toto okno)',
+       'mwe-upload-in-progress' => 'Prebieha nahrávanie (nezatvárajte toto okno)',
+       'mwe-upload-transcoded-status' => 'Prekódované',
+       'mwe-uploaded-status' => 'Nahrané',
+       'mwe-upload-stats-fileprogres' => '$1 z $2',
+       'mwe-upload_completed' => 'Vaše nahrávanie bolo dokončené',
+       'mwe-upload_done' => '<a href="$1">Súbor, ktorý ste nahrali <i>by mal byť</i> prístupný</a>.',
+       'mwe-upload-unknown-size' => 'Neznáma veľkosť',
+       'mwe-cancel-confim' => 'Ste si istý, že chcete prerušiť?',
+       'mwe-successfulupload' => 'Nahrávanie úspešné',
+       'mwe-uploaderror' => 'Chyba pri nahrávaní',
+       'mwe-uploadwarning' => 'Upozornenie pri nahrávaní',
+       'mwe-unknown-error' => 'Neznáma chyba:',
+       'mwe-return-to-form' => 'Späť na formulár',
+       'mwe-file-exists-duplicate' => 'Tento súbor je duplikátom nasledujúceho súboru:',
+       'mwe-fileexists' => 'Súbor s týmto názvom už existuje. Prosím, skontrolujte <b><tt>$1</tt></b> ak si nie ste istý, či ho chcete zmeniť.',
+       'mwe-fileexists-thumb' => '<center><b>Existujúci súbor</b></center>',
+       'mwe-ignorewarning' => 'Ignorovať upozornenie a napriek nemu uložiť súbor',
+       'mwe-download' => 'Stiahnuť',
+       'mwe-close_btn' => 'Zavrieť',
+       'mwe-do_not_warn_again' => 'Nateraz nezobrazovať',
+);
+
+/** Swedish (Svenska)
+ * @author GameOn
+ * @author Skalman
+ */
+$messages['sv'] = array(
+       'mwe-crop' => 'Beskär bild',
+       'mwe-apply_crop' => 'Verkställ beskärning',
+       'mwe-reset_crop' => 'Återställ beskärning',
+       'mwe-edit_properties' => 'Redigera egenskaper',
+       'mwe-other_properties' => 'Andra egenskaper',
+       'mwe-start_time' => 'Starttid',
+       'mwe-end_time' => 'Sluttid',
+       'mwe-close' => 'stäng',
+       'mwe-improve_transcript' => 'Förbättra',
+       'mwe-menu_clipedit' => 'Redigera media',
+       'mwe-menu_cliplib' => 'Lägg till media',
+       'mwe-menu_options' => 'Alternativ',
+       'mwe-loading_timeline' => 'Laddar tidslinje...',
+       'mwe-loading_user_rights' => 'Laddar användarrättigheter...',
+       'mwe-zoom_in' => 'Zooma in',
+       'mwe-zoom_out' => 'Zooma ut',
+       'mwe-pixle2sec' => 'Pixlar till sekunder',
+       'mwe-other_options' => 'Andra alternativ',
+       'mwe-ok' => 'OK',
+       'mwe-cancel' => 'Avbryt',
+       'mwe-proxy-not-ready' => 'Proxy är inte konfigurerad',
+       'fogg-select_file' => 'Välj fil',
+       'fogg-select_new_file' => 'Välj ny fil',
+       'fogg-select_url' => 'Välj URL',
+       'fogg-save_local_file' => 'Spara Ogg',
+       'fogg-check_for_firefogg' => 'Kollar om Firefogg är installerat...',
+       'fogg-installed' => 'Firefogg är installerat',
+       'fogg-for_improved_uploads' => 'För förbättrade uppladdningar:',
+       'fogg-please_install' => '<a href="$1">Installera Firefogg</a>. Mer <a href="http://commons.wikimedia.org/wiki/Commons:Firefogg">om Firefogg</a> (på engelska).',
+       'fogg-use_latest_firefox' => 'Vänligen installera först <a href="http://www.mozilla.com/sv-SE/firefox/upgrade.html?from=firefogg">Firefox 3.5</a> (eller senare). <i>Gå sedan tillbaka till den här sidan för att installera tillägget <b>Firefogg</b>.</i>',
+       'fogg-passthrough_mode' => 'Den valda filen är redan i formatet Ogg eller också är den inte en videofil över huvud taget',
+       'fogg-transcoding' => 'Kodar om videon till Ogg...',
+       'fogg-encoding-done' => 'Kodningen har avslutats',
+       'fogg-preview' => 'Förhandsgranska video',
+       'fogg-hidepreview' => 'Göm förhandsgranskning',
+       'fogg-help-sticky' => 'Hjälp (klicka för att fästa)',
+       'fogg-cg-preset' => 'Förinställning: <strong>$1</strong>',
+       'fogg-cg-quality' => 'Grundläggande kvalitets- och bildupplösningsinställning',
+       'fogg-cg-meta' => 'Metadata för klippet',
+       'fogg-videoQuality-title' => 'Videokvalitet',
+       'fogg-starttime-title' => 'Startsekund',
+       'fogg-endtime-title' => 'Slutsekund',
+       'fogg-audioQuality-title' => 'Ljudkvalité',
+       'fogg-videoCodec-title' => 'Bildkvalité',
+       'fogg-width-title' => 'Videobredd',
+       'fogg-height-title' => 'Videohöjd',
+       'fogg-videoBitrate-title' => 'Videobitrate',
+       'fogg-novideo-title' => 'Ingen video',
+       'fogg-title-title' => 'Titel',
+       'fogg-date-title' => 'Datum',
+       'fogg-location-title' => 'Plats',
+       'fogg-organization-title' => 'Organisation',
+       'fogg-copyright-title' => 'Copyright',
+       'rsd_results_next' => 'nästa',
+       'rsd_results_prev' => 'föregående',
+       'mwe-unknown_license' => 'Okänd licens',
+       'mwe-upload_a_file' => 'Ladda upp en ny fil till $1',
+       'mwe-cancel_import' => 'Avbryt import',
+       'mwe-ftype-svg' => 'SVG vektorfil',
+       'mwe-ftype-jpg' => 'JPEG bildfil',
+       'mwe-ftype-png' => 'PNG bildfil',
+       'mwe-ftype-oga' => 'Ogg ljudfil',
+       'mwe-ftype-ogg' => 'Ogg videofil',
+       'mwe-ftype-unk' => 'Okänt filformat',
+       'mwe-select_file' => 'Välj fil',
+       'mwe-upload' => 'Ladda upp fil',
+       'mwe-summary' => 'Sammanfattning',
+       'mwe-upload-stats-fileprogres' => '$1 av $2',
+       'mwe-upload-unknown-size' => 'Okänd storlek',
+       'mwe-cancel-confim' => 'Är det säkert att du vill avbryta?',
+       'mwe-uploaderror' => 'Uppladdningsfel',
+       'mwe-uploadwarning' => 'Uppladdningsvarning',
+       'mwe-unknown-error' => 'Okänt fel',
+       'mwe-ignorewarning' => 'Ignorera varningar och spara filen ändå',
+       'mwe-upload-misc-error' => 'Okänt uppladdningsfel',
+       'mwe-loading_plugin' => 'laddar plugin...',
+       'mwe-volume_control' => 'Volymkontroll',
+       'mwe-player_fullscreen' => 'Fullskärm',
+       'mwe-download' => 'Ladda ner',
+       'mwe-share' => 'Dela',
+       'mwe-chose_player' => 'Välj videouppspelare',
+       'mwe-share_this_video' => 'Dela denna video',
+       'mwe-menu_btn' => 'Meny',
+       'mwe-close_btn' => 'Stäng',
+       'mwe-ogg-player-vlc-mozilla' => 'VLC plugin',
+       'mwe-ogg-player-vlc-activex' => 'VLC ActiveX',
+       'mwe-ogg-player-selected' => '(vald)',
+       'mwe-related_videos' => 'Relaterade videos',
+);
+
+/** Telugu (తెలుగు)
+ * @author Veeven
+ */
+$messages['te'] = array(
+       'mwe-sc_duration' => 'నిడివి',
+       'mwe-template_properties' => 'మూస లక్షణాలు',
+       'mwe-edit_properties' => 'లక్షణాలని మార్చు',
+       'mwe-other_properties' => 'ఇతర లక్షణాలు',
+       'mwe-start_time' => 'ప్రారంభ సమయం',
+       'mwe-end_time' => 'ముగింపు సమయం',
+       'mwe-duration' => 'నిడివి:',
+       'mwe-select-other-language' => 'ఇతర భాషని ఎంచుకోండి',
+       'mwe-close' => 'మూసివేయి',
+       'mwe-menu_options' => 'ఎంపికలు',
+       'mwe-saving_wait' => 'భద్రపరడం జరుగుతూంది (దయచేసి వేచివుండండి)',
+       'mwe-save_done' => 'భద్రపరచడం పూర్తయ్యింది',
+       'mwe-edit_cancel_confirm' => 'మీరు నిజంగానే మీ మార్పుని రద్దుచేయాలనుకుంటున్నారా? మార్పులు పోతాయి.',
+       'mwe-editor_options' => 'కూర్పరి ఎంపికలు',
+       'mwe-other_options' => 'ఇతర ఎంపికలు',
+       'mwe-ok' => 'సరే',
+       'mwe-cancel' => 'రద్దుచేయి',
+       'fogg-videoQuality-title' => 'దృశ్యకపు నాణ్యత',
+       'fogg-width-title' => 'దృశ్యకపు వెడల్పు',
+       'fogg-height-title' => 'దృశ్యకపు ఎత్తు',
+       'fogg-title-title' => 'శీర్షిక',
+       'fogg-date-title' => 'తేదీ',
+       'fogg-location-title' => 'ప్రాంతం',
+       'fogg-organization-title' => 'సంస్థ',
+       'fogg-organization-help' => '(నిర్మాణ) సంస్థ యొక్క పేరు',
+       'fogg-copyright-title' => 'కాపీహక్కులు',
+       'fogg-license-title' => 'లైసెన్సు',
+       'fogg-contact-title' => 'సంప్రదింపులు',
+       'fogg-contact-help' => 'సంప్రదించు లంకె',
+       'rsd_results_desc' => '$1 నుండి $2 వరకు ఫలితాలు',
+       'rsd_results_next' => 'తదుపరి',
+       'rsd_results_prev' => 'గత',
+       'rsd_no_results' => '<b>$1</b>కి ఫలితాలు ఏమీ లేవు',
+       'mwe-upload_tab' => 'ఎక్కింపు',
+       'rsd_layout' => 'అమరిక:',
+       'mwe-link' => 'లంకె',
+       'mwe-results_from' => '<a href="$1" target="_new" >$2</a> నుండి ఫలితాలు',
+       'mwe-your_recent_uploads' => '$1 లోనికి ఇటీవలి మీ ఎక్కింపులు',
+       'mwe-upload_a_file' => 'కొత్త ఫైలుని ఎక్కించండి',
+       'mwe-resource_page_desc' => 'వనరు పేజీ వివరణ:',
+       'rsd-this_wiki-title' => 'ఈ వికీ',
+       'mwe-select_file' => 'ఫైలుని ఎంచుకోండి',
+       'mwe-destfilename' => 'గమ్యస్థాన ఫైలుపేరు:',
+       'mwe-summary' => 'సారాశం',
+       'mwe-upload-in-progress' => 'ఎక్కింపు జరుగుతోంది (ఈ కిటికీని మూసేయకండి)',
+       'mwe-upload_completed' => 'మీ ఎక్కింపు పూర్తయ్యింది',
+       'mwe-cancel-confim' => 'మీరు నిజంగానే రద్దుచేయాలనుకుంటున్నారా?',
+       'mwe-successfulupload' => 'ఎక్కింపు విజయవంతం',
+       'mwe-uploaderror' => 'ఎక్కింపులో పొరపాటు',
+       'mwe-uploadwarning' => 'ఎక్కింపు హెచ్చరిక',
+       'mwe-file-exists-duplicate' => 'ఈ ఫైలు క్రింది ఫైలుకి నకిలీ:',
+       'mwe-player_fullscreen' => 'నిండుతెర',
+       'mwe-menu_btn' => 'మెనూ',
+       'mwe-close_btn' => 'మూసివేయి',
+       'mwe-related_videos' => 'సంబంధిత దృశ్యకాలు',
+);
+
+/** Turkish (Türkçe)
+ * @author Aspar
+ * @author Joseph
+ * @author McDutchie
+ * @author Vito Genovese
+ */
+$messages['tr'] = array(
+       'mwe-crop' => 'Resmi kırp',
+       'mwe-apply_crop' => 'Kırpmayı resme uygula',
+       'mwe-reset_crop' => 'Kırpmayı sıfırla',
+       'mwe-insert_image_page' => 'Sayfaya ekle',
+       'mwe-insert_into_sequence' => 'Sıraya ekle',
+       'mwe-preview_insert' => 'Eklemeyi önizle',
+       'mwe-cancel_image_insert' => 'Eklemeyi iptal et',
+       'mwe-sc_fileopts' => 'Klip ayrıntısını değiştir',
+       'mwe-sc_inoutpoints' => 'Başlangıç-bitiş noktalarını ayarla',
+       'mwe-sc_overlays' => 'Katmanlar',
+       'mwe-sc_audio' => 'Ses denetimi',
+       'mwe-sc_duration' => 'Süre',
+       'mwe-template_properties' => 'Şablon özellikleri',
+       'mwe-custom_title' => 'Özel başlık',
+       'mwe-edit_properties' => 'Değişiklik özellikleri',
+       'mwe-other_properties' => 'Diğer özellikler',
+       'mwe-resource_page' => 'Kaynak sayfası:',
+       'mwe-set_in_out_points' => 'Başlangıç-bitiş noktalarını ayarla',
+       'mwe-start_time' => 'Başlangıç zamanı',
+       'mwe-end_time' => 'Bitiş zamanı',
+       'mwe-preview_inout' => 'Başlangıç-bitiş noktalarını önizle',
+       'mwe-edit-tools' => 'Değişiklik araçları',
+       'mwe-inline-description' => 'Resim yazısı',
+       'mwe-edit-video-tools' => 'Video Düzenleme Araçları:',
+       'mwe-duration' => 'Süre:',
+       'mwe-upload-subs-file' => 'Altyazı yükle',
+       'mwe-add-subs-file-title' => 'Yüklenecek altyazıyı seç',
+       'mwe-error-only-srt' => 'Sadece srt dosyası yükleyebilirsiniz.',
+       'mwe-watch-video' => 'Video izle',
+       'mwe-select-other-language' => 'Başka dil seç',
+       'mwe-saving' => 'kaydediyor...',
+       'mwe-select_transcript_set' => 'Altyazı seç',
+       'mwe-auto_scroll' => 'otomatik kaydır',
+       'mwe-close' => 'kapat',
+       'mwe-improve_transcript' => 'Geliştir',
+       'mwe-no_text_tracks_found' => 'Hiç metin izleri bulunamadı',
+       'mwe-add-edit-subs' => 'Altyazı ekle/düzenle',
+       'mwe-transition_in' => 'İçe geçiş',
+       'mwe-transition_out' => 'Dışa geçiş',
+       'mwe-effects' => 'Efekt yığını',
+       'mwe-remove_transition' => 'Geçişi kaldır',
+       'mwe-edit_transin' => 'Klibe geçişi değiştir',
+       'mwe-edit_transout' => 'Klipten geçişi değiştir',
+       'mwe-add-transition' => 'Geçiş ekle',
+       'mwe-menu_clipedit' => 'Ortamı değiştir',
+       'mwe-menu_transition' => 'Geçişler ve efektler',
+       'mwe-menu_cliplib' => 'Ortam ekle',
+       'mwe-menu_resource_overview' => 'Kaynak genel bakışı',
+       'mwe-menu_options' => 'Seçenekler',
+       'mwe-loading_timeline' => 'Zaman çizelgesi yükleniyor ...',
+       'mwe-loading_user_rights' => 'Kullanıcı hakları yükleniyor ...',
+       'mwe-no_edit_permissions' => 'Bu dizilişe değişiklikleri kaydetme izniniz yok',
+       'mwe-edit_clip' => 'Klibi değiştir',
+       'mwe-edit_save' => 'Diziliş değişikliklerini kaydet',
+       'mwe-saving_wait' => 'Kaydetme sürüyor (lütfen bekleyin)',
+       'mwe-save_done' => 'Kaydetme tamamlandı',
+       'mwe-edit_cancel' => 'Diziliş değişikliğini iptal et',
+       'mwe-edit_cancel_confirm' => 'Değişikliğinizi iptal etmek istediğinize emin misiniz? Değişiklikler kaybolacaktır.',
+       'mwe-zoom_in' => 'Yakınlaştır',
+       'mwe-zoom_out' => 'Uzaklaştır',
+       'mwe-cut_clip' => 'Klipleri kes',
+       'mwe-expand_track' => 'İzi genişlet',
+       'mwe-collapse_track' => 'İzi daralt',
+       'mwe-play_from_position' => 'Oynatma çizgisi konumundan oynat',
+       'mwe-pixle2sec' => 'piksele saniye',
+       'mwe-rmclip' => 'Klibi kaldır',
+       'mwe-clip_in' => 'içe klip',
+       'mwe-clip_out' => 'dışa klip',
+       'mwe-no_selected_resource' => '<h3>Hiç kaynak seçilmedi</h3> Değiştirmeyi etkinleştirmek için bir klip seçin.',
+       'mwe-error_edit_multiple' => '<h3>Birden fazla kaynak seçildi</h3> Değiştirmek için tek klip seçin.',
+       'mwe-editor_options' => 'Düzenleyici seçenekleri',
+       'mwe-editor_mode' => 'Düzenleyici kipi',
+       'mwe-simple_editor_desc' => 'basit düzenleyici (iMovie tarzı)',
+       'mwe-advanced_editor_desc' => 'gelişmiş düzenleyici (Final Cut tarzı)',
+       'mwe-other_options' => 'Diğer seçenekler',
+       'mwe-contextmenu_opt' => 'İçerik menülerini etkinleştir',
+       'mwe-sequencer_credit_line' => '<a href="http://kaltura.com">Kaltura, Inc.</a> tarafından, <a href="http://wikimediafoundation.org/wiki/Home">Wikimedia Foundation</a> (<a href="#">daha fazla bilgi</a>) ortaklığında geliştirilmiştir.',
+       'mwe-loading_txt' => 'yükleniyor ...',
+       'mwe-error_load_lib' => 'Hata: $1 JavaScripti erişilebilir değil ya da $2 tanımlı değil',
+       'mwe-loading-add-media-wiz' => 'Ortam ekle sihirbazı yükleniyor',
+       'mwe-apiproxy-setup' => 'API vekili ayarlanıyor',
+       'mwe-load-drag-item' => 'Sürüklenen öğe yükleniyor',
+       'mwe-ok' => 'Tamam',
+       'mwe-cancel' => 'İptal',
+       'mwe-setting-up-proxy' => 'Vekil ayarlanıyor...',
+       'mwe-re-try' => 'API isteğini tekrar dene',
+       'mwe-re-trying' => 'API isteği tekrar deneniyor...',
+       'mwe-proxy-not-ready' => 'Vekil ayarlanmadı',
+       'mwe-please-login' => '$2 sitesinde <a target="_new" href="$1">oturum açmadınız</a> ya da mwEmbed henüz etkinleştirilmedi.Sorunu çözün, ve sonra isteği tekrar deneyin.',
+       'mwe-remember-loging' => 'Genel güvenlik hatırlatıcısı: Sadece adres çubuğunuz sitenin adresini gösterirse sitlere giriş yapın.',
+       'fogg-select_file' => 'Dosyayı seç',
+       'fogg-select_new_file' => 'Yeni dosyayı seç',
+       'fogg-select_url' => 'URLyi seç',
+       'fogg-save_local_file' => "Ogg'u kaydet",
+       'fogg-check_for_firefogg' => 'Firefogg kontrol ediliyor ...',
+       'fogg-installed' => 'Firefogg yüklendi',
+       'fogg-for_improved_uploads' => 'Gelişmiş yüklemeler için:',
+       'fogg-please_install' => '<a href="$1">Firefogg\'u yükle</a>. <a href="http://commons.wikimedia.org/wiki/Commons:Firefogg">Firefogg hakkında</a> daha fazla',
+       'fogg-use_latest_firefox' => 'Lütfen önce <a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=firefogg">Firefox 3.5</a>\'i (ya da sonrası) yükleyin. <i>Daha sonra <b>Firefogg</b> eklentisini yüklemek için bu sayfayı tekrar ziyaret edin.</i>',
+       'fogg-passthrough_mode' => 'Seçtiğiniz dosya zaten Ogg ya da bir video dosyası değil',
+       'fogg-transcoding' => "Video Ogg'a kodlanıyor",
+       'fogg-encoding-done' => 'Kodlama tamamlandı',
+       'fogg-badtoken' => 'Nişan geçersiz',
+       'fogg-preview' => 'Videoyu önizle',
+       'fogg-hidepreview' => 'Önizlemeyi gizle',
+       'mwe-imported_from' => '$1 [$2 $3] adresinden içe aktardı. Daha fazla bilgi için orijinal [$4 kaynak sayfasına] bakın.',
+       'mwe-stream_title' => '$1 $2 den $3 e',
+       'fogg-help-sticky' => 'Yardım (yapıştırmak için tıklayın)',
+       'fogg-cg-preset' => 'Önayar: <strong>$1</strong>',
+       'fogg-cg-quality' => 'Temel kalite ve çözünürlük denetimi',
+       'fogg-cg-meta' => 'Klip için üstverisi',
+       'fogg-cg-range' => 'Kodlama aralığı',
+       'fogg-cg-advVideo' => 'Gelişmiş video kodlama denetimleri',
+       'fogg-cg-advAudio' => 'Gelişmiş ses kodlama denetimleri',
+       'fogg-preset-custom' => 'Özel ayarlar',
+       'fogg-webvideo-desc' => 'Web videosu Theora, Vorbis 400 kbit/s ve 400px azami genişlik',
+       'fogg-savebandwidth-desc' => 'Düşük bant genişliği Theora, Vorbis 164 kbit/s ve 200px azami genişlik',
+       'fogg-highquality-desc' => 'Yüksek kalite Theora, Vorbis 1080px azami genişlik',
+       'fogg-videoQuality-title' => 'Video kalitesi',
+       'fogg-videoQuality-help' => 'Kodlanan videonun <i>görsel kalitesini</i> ayarlamak için kullanılır (aşağıdaki gelişmiş kontrollerde bit oranını ayarlarsanız kullanılmaz).',
+       'fogg-starttime-title' => 'Başlangıç saniyesi',
+       'fogg-starttime-help' => 'Sadece zamandan itibaren saniye olarak kodla',
+       'fogg-endtime-title' => 'Bitiş saniyesi',
+       'fogg-endtime-help' => 'Sadece zamana kadar saniye olarak kodla',
+       'fogg-audioQuality-title' => 'Ses kalitesi',
+       'fogg-audioQuality-help' => 'Kodlanan videonun <i>akustik kalitesini</i> ayarlamak için kullanılır (aşağıdaki gelişmiş kontrollerde bit oranını ayarlarsanız kullanılmaz).',
+       'fogg-videoCodec-title' => 'Video kodeği',
+       'fogg-videoCodec-help' => 'Klip video kodeğini seçmek için kullanılır. Şu anda sadece Theora destekleniyor. <a target="_new" href="http://en.wikipedia.org/wiki/Theora">Theora kodeği</a> hakkında daha fazla.',
+       'fogg-audioCodec-title' => 'Ses kodeği',
+       'fogg-audioCodec-help' => 'Klip ses kodeğini seçmek için kullanılır. Şu anda sadece Vorbis destekleniyor. <a target="_new" href="http://en.wikipedia.org/wiki/Vorbis">Vorbis kodeği</a> hakkında daha fazla.',
+       'fogg-width-title' => 'Video genişliği',
+       'fogg-width-help' => 'Verilen genişliğe tekrar boyutlandır.',
+       'fogg-height-title' => 'Video yüksekliği',
+       'fogg-height-help' => 'Verilen yüksekliğe tekrar boyutlandır.',
+       'fogg-videoBitrate-title' => 'Video bit oranı',
+       'fogg-videoBitrate-help' => 'Video bit oranı video için kodlama bit oranını (kb/s) olarak ayarlar',
+       'fogg-twopass-title' => 'İkili geçiş kodlaması',
+       'fogg-twopass-help' => 'İkili geçiş kodlaması, video dosyası üzerinden iki geçiş yaparak daha sabit kaliteyi etkinleştirir.',
+       'fogg-framerate-title' => 'Çerçeve oranı',
+       'fogg-framerate-help' => 'Video çerçeve oranı. <a target="_new" href="http://en.wikipedia.org/wiki/Frame_rate">Çerçeve oranı</a> hakkında daha fazla.',
+       'fogg-aspect-title' => 'Görünüş oranı',
+       'fogg-aspect-help' => 'Video görünüş oranı 4:3 ya da 16:9 kesiri olabilir. <a target="_new" href="http://en.wikipedia.org/wiki/Aspect_ratio_%28image%29">Görünüş oranları</a> hakkında daha fazla.',
+       'fogg-keyframeInterval-title' => 'Anahtar çerçeve aralığı',
+       'fogg-keyframeInterval-help' => 'Çerçeve olarak anahtar çerçeve aralığı. Not: Eğer çerçeve aralarındaki fark anahtar çerçeve kodlama boyutundan büyükse; çoğu kodek, anahtar çerçeveleri zorlar. <a href="http://en.wikipedia.org/wiki/I-frame">Anahtar çerçeveler</a> hakkında daha fazla.',
+       'fogg-denoise-title' => 'Gürültü giderici filtre',
+       'fogg-denoise-help' => 'Girdi videosunda gürültü gider. <a href="http://en.wikipedia.org/wiki/Video_denoising">Gürültü giderme</a> hakkında daha fazla.',
+       'fogg-novideo-title' => 'Video yok',
+       'fogg-novideo-help' => 'çıktıda videoyu devre dışı bırak',
+       'fogg-audioBitrate-title' => 'Ses bit oranı',
+       'fogg-samplerate-title' => 'Ses örnekleme oranı',
+       'fogg-samplerate-help' => 'çıktı örnekleme oranını ayarla (Hz olarak).',
+       'fogg-noaudio-title' => 'Ses yok',
+       'fogg-noaudio-help' => 'çıktıda sesi devre dışı bırak',
+       'fogg-title-title' => 'Başlık',
+       'fogg-title-help' => 'Klibiniz için bir başlık',
+       'fogg-artist-title' => 'Oluşturanın ismi',
+       'fogg-artist-help' => 'Bu klibi oluşturan',
+       'fogg-date-title' => 'Tarih',
+       'fogg-date-help' => 'Görüntünün oluşturulduğu ya da yayınlandığı tarih',
+       'fogg-location-title' => 'Yer',
+       'fogg-location-help' => 'Görüntünün konumu',
+       'fogg-organization-title' => 'Organizasyon',
+       'fogg-organization-help' => 'Organizasyon ismi (stüdyo)',
+       'fogg-copyright-title' => 'Telif',
+       'fogg-copyright-help' => 'Klibin telifi',
+       'fogg-license-title' => 'Lisans',
+       'fogg-license-help' => 'Klibin lisansı (tercihen bir Creative Commons URLsi).',
+       'fogg-contact-title' => 'İletişim',
+       'fogg-contact-help' => 'İletişim bağlantısı',
+       'mwe-add_media_wizard' => 'Ortam sihirbazını ekle',
+       'mwe-media_search' => 'Ortam araması',
+       'rsd_box_layout' => 'Kutu yerleşimi',
+       'rsd_list_layout' => 'Liste yerleşimi',
+       'rsd_results_desc' => '$1 $2 arası sonuçlar',
+       'rsd_results_desc_total' => '$3 sonuçtan $1 $2 arası sonuçlar',
+       'rsd_results_next' => 'sonraki',
+       'rsd_results_prev' => 'önceki',
+       'rsd_no_results' => '<b>$1</b> için arama sonucu yok',
+       'mwe-upload_tab' => 'Yükle',
+       'rsd_layout' => 'Yerleşim:',
+       'rsd_resource_edit' => 'Değişiklik kaynağı: $1',
+       'mwe-resource_description_page' => 'Kaynak açıklama sayfası',
+       'mwe-link' => 'bağlantı',
+       'rsd_local_resource_title' => 'Yerel kaynak başlığı',
+       'rsd_do_insert' => 'Ekleme yap',
+       'mwe-cc_by_title' => 'Atıf',
+       'mwe-cc_nc_title' => 'Ticari olmayan',
+       'mwe-cc_nd_title' => 'Türetilemez İşler',
+       'mwe-cc_sa_title' => 'Benzer Paylaşım',
+       'mwe-cc_pd_title' => 'Kamu Malı',
+       'mwe-unknown_license' => 'Bilinmeyen lisans',
+       'mwe-no_import_by_url' => 'Bu kullanıcı ya da viki uzaktan URLlerden kazanç içe <b>aktaramaz</b>.<p>Oturum açmak ister misiniz?</p><p>upload_by_url izni sizin için ayarlanmış mı?<br />Vikide <a href="http://www.mediawiki.org/wiki/Manual:$wgAllowCopyUploads">$wgAllowCopyUploads</a> etkinleştirilmiş mi?</p>',
+       'mwe-results_from' => '<a href="$1" target="_new" >$2</a> için sonuçlar',
+       'mwe-missing_desc_see_source' => 'Bu varlığın tanımı eksik. Lütfen [$1 orijinal kaynağa] bakın ve açıklamaya yardımcı olun.',
+       'rsd_config_error' => 'Ortam ekle sihirbazı yapılandırma hatası: $1',
+       'mwe-your_recent_uploads' => '$1 için son yüklemeleriniz',
+       'mwe-upload_a_file' => '$1 için yeni bir dosya yükle',
+       'mwe-resource_page_desc' => 'Kaynak sayfası açıklaması:',
+       'mwe-edit_resource_desc' => 'Kaynak açıklaması viki metnini değiştir',
+       'mwe-local_resource_title' => 'Yerel kaynak başlığı:',
+       'mwe-watch_this_page' => 'Bu sayfayı izle',
+       'mwe-do_import_resource' => 'Kaynağı içe aktar',
+       'mwe-update_preview' => 'Önizlemeyi güncelle',
+       'mwe-cancel_import' => 'İçe aktarmayı iptal et',
+       'mwe-importing_asset' => 'Varlık içe aktarılıyor',
+       'mwe-preview_insert_resource' => 'Kaynak eklemesini önizle: $1',
+       'mwe-checking-resource' => 'Kaynak kontrol ediliyor',
+       'mwe-resource-needs-import' => '$1 kaynağının $2 için içe aktarılması gerekiyor',
+       'mwe-ftype-svg' => 'SVG yöney dosyası',
+       'mwe-ftype-jpg' => 'JPEG resim dosyası',
+       'mwe-ftype-png' => 'PNG resim dosyası',
+       'mwe-ftype-oga' => 'Ogg ses dosyası',
+       'mwe-ftype-ogg' => 'Ogg video dosyası',
+       'mwe-ftype-unk' => 'Bilinmeyen dosya formatı',
+       'rsd-wiki_commons-title' => 'Wikimedia Commons',
+       'rsd-wiki_commons' => 'Wikimedia Commons, özgür içerikli eğitimsel ortam içeriği arşivi (resim, ses ve video dosyaları)',
+       'rsd-this_wiki-title' => 'Bu viki',
+       'rsd-this_wiki-desc' => 'Yerel viki kurulumu',
+       'rsd-archive_org-desc' => 'The Internet Archive, dijital bir kültürel eser kütüphanesi',
+       'rsd-flickr-desc' => 'Flickr.com, bir çevrimiçi fotoğraf paylaşım sitesi',
+       'rsd-metavid-desc' => 'Metavid.org, ABD Meclis ve Senato görüşmelerinin topluluk arşivi',
+       'mwe-select_file' => 'Dosyayı seçin',
+       'mwe-more_licence_options' => 'Daha fazla lisans seçenekleri için, <a href="$1">normal yükleme sayfası</a>na bakın',
+       'mwe-select_ownwork' => 'Tamamen kendi çalışmamı yüklüyorum, ve lisansı aşağıdaki gibidir:',
+       'mwe-licence_cc-by-sa' => 'Creative Commons Benzer Paylaşım (3.0)',
+       'mwe-upload' => 'Dosyayı yükle',
+       'mwe-destfilename' => 'Hedef dosya adı:',
+       'mwe-summary' => 'Özet',
+       'mwe-error_not_loggedin' => 'Giriş yapmadınız ya da yükleme ayrıcalığınız yok.',
+       'mwe-watch-this-file' => 'Bu dosyayı izle',
+       'mwe-ignore-any-warnings' => 'Herhangi bir uyarıyı önemseme',
+       'mwe-upload-transcode-in-progress' => 'Yeniden kodlama ve yükleme sürüyor (bu pencereyi kapatmayın)',
+       'mwe-upload-in-progress' => 'Yükleme sürüyor (bu pencereyi kapatmayın)',
+       'mwe-upload-transcoded-status' => 'Yeniden kodlandı',
+       'mwe-uploaded-status' => 'Yüklendi',
+       'mwe-upload-stats-fileprogress' => '$2 de $1',
+       'mwe-upload_completed' => 'Yüklemeniz tamamlandı',
+       'mwe-upload_done' => '<a href="$1">Yüklemeniz erişilebilir <i>olmalıdır</i></a>.',
+       'mwe-upload-unknown-size' => 'Bilinmeyen boyut',
+       'mwe-cancel-confim' => 'İptal etmek istediğinize emin misiniz?',
+       'mwe-successfulupload' => 'Yükleme başarılı',
+       'mwe-uploaderror' => 'Yükleme hatası',
+       'mwe-uploadwarning' => 'Yükleme uyarısı',
+       'mwe-unknown-error' => 'Bilinmeyen hata:',
+       'mwe-return-to-form' => 'Forma geri dön',
+       'mwe-file-exists-duplicate' => 'Bu dosya aşağıdaki dosyanın aynısı:',
+       'mwe-fileexists' => 'Bu isimde bir dosya zaten mevcut. Değiştirmek istediğinize emin değilseniz lütfen <b><tt>$1</tt></b> kontrol edin.',
+       'mwe-fileexists-thumb' => '<center><b>Mevcut dosya</b></center>',
+       'mwe-ignorewarning' => 'Uyarıyı önemseme ve dosyayı yinede yükle',
+       'mwe-file-thumbnail-no' => 'Dosya adı <b><tt>$1</tt></b> ile başlıyor',
+       'mwe-go-to-resource' => 'Kaynak sayfasına git',
+       'mwe-upload-misc-error' => 'Bilinmeyen yükleme hatası',
+       'mwe-wgfogg_warning_bad_extension' => 'Desteklenmeyen bir uzantıya sahip bir dosya seçtiniz (<a href="http://commons.wikimedia.org/wiki/Commons:Firefogg#Supported_File_Types">daha fazla bilgi</a>).',
+       'mwe-upload-multi' => '{{PLURAL:$1|Dosya|Dosya}} yükle',
+       'mwe-review-upload' => 'Dosya {{PLURAL:$1|yüklemesini|yüklemelerini}} incele',
+       'mwe-credit-title' => 'Başlık: $1',
+       'mwe-loading_plugin' => 'eklenti yükleniyor ...',
+       'mwe-select_playback' => 'Oynatma tercihini ayarla',
+       'mwe-link_back' => 'Geri bağlantı ver',
+       'mwe-error_swap_vid' => 'Hata: mv_embed, mv_embed arayüzü için video etiketini değiş tokuş yapamıyor',
+       'mwe-add_to_end_of_sequence' => 'Sıranın sonuna ekle',
+       'mwe-missing_video_stream' => 'Bu akış için video dosyası kayıp',
+       'mwe-play_clip' => 'Klibi oynat',
+       'mwe-pause_clip' => 'Klibi durdur',
+       'mwe-volume_control' => 'Ses denetimi',
+       'mwe-player_options' => 'Oynatıcı seçenekleri',
+       'mwe-closed_captions' => 'Kapalı resim yazıları',
+       'mwe-player_fullscreen' => 'Tam ekran',
+       'mwe-next_clip_msg' => 'Sonraki klibi oynat',
+       'mwe-prev_clip_msg' => 'Önceki klibi oynat',
+       'mwe-current_clip_msg' => 'Bu klibi oynatmaya devam et',
+       'mwe-seek_to' => '$1 süresine git',
+       'mwe-paused' => 'durduruldu',
+       'mwe-download_segment' => 'Seçimi indir:',
+       'mwe-download_full' => 'Tam video dosyasını indir:',
+       'mwe-download_right_click' => "İndirmek için, sağ tıklayın ve <i>Bağlantıyı farklı kaydet...</i>'i seçin",
+       'mwe-download_clip' => 'Videoyu indir',
+       'mwe-download_text' => 'Metni indir (<a style="color:white" title="cmml" href="http://wiki.xiph.org/index.php/CMML">CMML</a> xml):',
+       'mwe-download' => 'İndir',
+       'mwe-share' => 'Paylaş',
+       'mwe-credits' => 'Katkıda bulunanlar',
+       'mwe-clip_linkback' => 'Klip kaynak sayfası',
+       'mwe-chose_player' => 'Video oynatıcı seç',
+       'mwe-share_this_video' => 'Bu videoyu paylaş',
+       'mwe-video_credits' => 'Videoya katkıda bulunanlar',
+       'mwe-menu_btn' => 'Menü',
+       'mwe-close_btn' => 'Kapat',
+       'mwe-ogg-player-vlc-player' => 'VLC player',
+       'mwe-ogg-player-videoElement' => 'Yerli Ogg videosu',
+       'mwe-ogg-player-oggPlugin' => 'Jenerik Ogg eklentisi',
+       'mwe-ogg-player-quicktime-mozilla' => 'QuickTime eklentisi',
+       'mwe-ogg-player-quicktime-activex' => 'QuickTime ActiveX',
+       'mwe-ogg-player-cortado' => 'Java Cortado',
+       'mwe-ogg-player-flowplayer' => 'Flowplayer',
+       'mwe-ogg-player-kplayer' => 'Kaltura oynatıcısı',
+       'mwe-ogg-player-selected' => '(seçili)',
+       'mwe-ogg-player-omtkplayer' => 'OMTK Flash Vorbis',
+       'mwe-generic_missing_plugin' => 'Tarayıcınız şu oynatma tiplerini desteklemiyor gibi görünüyor: <b>$1</b><br />Bir oynatıcı indirmek için <a href="http://commons.wikimedia.org/wiki/Commons:Media_help">Oynatma metodları</a> sayfasını ziyaret edin.<br />',
+       'mwe-for_best_experience' => 'Daha iyi bir video oynatma deneyimi için tavsiyemiz:<br /><b><a href="http://www.mozilla.com/en-US/firefox/upgrade.html?from=mwEmbed">Firefox 3.5</a>.</b>',
+       'mwe-do_not_warn_again' => 'Şimdilik bırakın.',
+       'mwe-playerselect' => 'Oynatıcılar',
+       'mwe-read_before_embed' => 'Lütfen gerçekten gömmeden <a href="http://mediawiki.org/wiki/Security_Notes_on_Remote_Embedding" target="_new">uzaktan gömme hakkındaki güvenlik notlarını</a> okuyun!',
+       'mwe-embed_site_or_blog' => 'Bir sayfaya gömün',
+       'mwe-related_videos' => 'İlgili videolar',
+       'mwe-seeking' => 'aranıyor',
+       'mwe-copy-code' => 'Kodu kopyala',
+);
+
+/** Ukrainian (Українська)
+ * @author Prima klasy4na
+ */
+$messages['uk'] = array(
+       'mwe-template_properties' => 'Властивості шаблону',
+       'mwe-start_time' => 'Час початку',
+       'rsd_results_next' => 'наступний',
+       'mwe-ftype-svg' => 'Векторний файл SVG',
+       'mwe-summary' => 'Опис змін',
+       'mwe-closed_captions' => 'Приховані титри',
+);
+
+/** Vèneto (Vèneto)
+ * @author Candalua
+ */
+$messages['vec'] = array(
+       'mwe-crop' => "Taja l'imagine",
+       'mwe-insert_image_page' => 'Inserissi drento la pagina',
+       'mwe-insert_into_sequence' => 'Inserissi drento la sequensa',
+       'mwe-preview_insert' => "Anteprima de l'inserimento",
+       'mwe-sc_audio' => "Controlo de l'audio",
+       'mwe-sc_duration' => 'Durata',
+       'mwe-template_properties' => 'Proprietà del modèl',
+       'mwe-custom_title' => 'Titolo personalizà',
+       'mwe-edit_properties' => 'Canbia proprietà',
+       'mwe-other_properties' => 'Altre proprietà',
+       'mwe-start_time' => 'Tenpo de inissio',
+       'mwe-end_time' => 'Tenpo de fine',
+       'mwe-inline-description' => 'Legenda',
+       'mwe-duration' => 'Durata:',
+       'mwe-upload-subs-file' => 'Carga sototitolo',
+       'mwe-add-subs-file-title' => 'Siegli el sototitolo da cargar',
+       'mwe-error-only-srt' => 'Se pol cargar solo file srt.',
+       'mwe-watch-video' => 'Varda el video',
+       'mwe-select-other-language' => "Siegli n'altra lengua",
+       'mwe-saving' => "so' drio salvar...",
+       'mwe-select_transcript_set' => 'Siegli i sototitoli',
+       'mwe-auto_scroll' => 'scorimento automatico',
+       'mwe-close' => 'sara',
+       'mwe-improve_transcript' => 'Mejorar',
+       'mwe-no_text_tracks_found' => 'Sototitoli testuali mia catà',
+       'mwe-add-edit-subs' => 'Zonta/canbia sototitoli',
+       'mwe-menu_options' => 'Opzioni',
+       'mwe-saving_wait' => "So' drio salvar (speta n'atimo, par piaser)",
+       'mwe-save_done' => 'Salvatajo conpleto',
+       'mwe-zoom_in' => 'Strenzi zoom',
+       'mwe-zoom_out' => 'Slarga zoom',
+       'mwe-loading_txt' => "so' drio cargar ...",
+       'mwe-ok' => 'Va ben',
+       'mwe-cancel' => 'Anula',
+       'mwe-proxy-not-ready' => "El proxy no'l xe mia configurà",
+       'fogg-select_file' => 'Selessiona file',
+       'fogg-select_new_file' => 'Selessiona file novo',
+       'fogg-select_url' => 'Selessiona indirisso (URL)',
+       'fogg-save_local_file' => 'Salva come Ogg',
+       'fogg-check_for_firefogg' => "So' drio sercar el Firefogg...",
+       'fogg-installed' => 'El Firefogg el xe instalà',
+       'fogg-transcoding' => "So' drio codificar el video in formato Ogg",
+       'fogg-encoding-done' => 'Codifica conpletà',
+       'fogg-badtoken' => 'Token mia valido',
+       'fogg-preview' => 'Anteprima del video',
+       'fogg-hidepreview' => 'Scondi anteprima',
+       'mwe-stream_title' => '$1 $2 a $3',
+       'fogg-help-sticky' => 'Ajuto (struca par fissarlo)',
+       'fogg-preset-custom' => 'Inpostassion personalizà',
+       'fogg-videoQuality-title' => 'Qualità video',
+       'fogg-starttime-title' => 'Secondo de scuminsio',
+       'fogg-endtime-title' => 'Secondo de fine',
+       'fogg-audioQuality-title' => 'Qualità audio',
+       'fogg-width-title' => 'Larghessa video',
+       'fogg-width-help' => 'Ridimensiona a la larghessa indicà.',
+       'fogg-height-title' => 'Altessa video',
+       'fogg-height-help' => "Ridimensiona a l'altessa indicà.",
+       'fogg-framerate-title' => 'Frequensa dei fotogrami',
+       'fogg-aspect-title' => 'Proporsion larghessa/altessa',
+       'fogg-novideo-title' => 'No ghe xe el video',
+       'fogg-noaudio-title' => "No ghe xe l'audio",
+       'fogg-title-title' => 'Titolo',
+       'fogg-artist-title' => "Nome de l'autor",
+       'fogg-date-title' => 'Data',
+       'fogg-location-title' => 'Posto',
+       'fogg-organization-title' => 'Dita',
+       'fogg-copyright-title' => "Diriti d'autor",
+       'fogg-license-title' => 'Licensa',
+       'rsd_box_layout' => 'Disposission del riquadro',
+       'rsd_list_layout' => 'Disposission de la lista',
+       'rsd_results_desc' => 'Risultati da $1 a $2',
+       'rsd_results_desc_total' => 'Risultati da $1 a $2 de $3',
+       'rsd_results_next' => 'quel dopo',
+       'rsd_results_prev' => 'quel prima',
+       'rsd_no_results' => 'No gò catà gnente che corisponde a <b>$1</b>',
+       'mwe-upload_tab' => 'Cargar',
+       'rsd_layout' => 'Disposission:',
+       'rsd_resource_edit' => 'Modifica la risorsa: $1',
+       'mwe-resource_description_page' => 'Pagina de descrission de la risorsa',
+       'mwe-link' => 'colegamento',
+       'rsd_local_resource_title' => 'Titolo de la risorsa locale',
+       'rsd_do_insert' => "Fà l'inserimento",
+       'mwe-cc_pd_title' => 'Dominio pùblico',
+       'mwe-unknown_license' => 'Licensa sconossùa',
+       'mwe-your_recent_uploads' => 'I to ultimi caricamenti su $1',
+       'mwe-upload_a_file' => 'Carga un file novo su $1',
+       'mwe-local_resource_title' => 'Titolo local de la risorsa:',
+       'mwe-watch_this_page' => "Tien d'ocio sta pagina",
+       'mwe-do_import_resource' => 'Inporta risorsa',
+       'mwe-update_preview' => 'Ajorna anteprima',
+       'mwe-ftype-svg' => 'File vetorial SVG',
+       'mwe-ftype-jpg' => 'Imagine JPEG',
+       'mwe-ftype-png' => 'Imagine PNG',
+       'mwe-ftype-oga' => 'Audio ogg',
+       'mwe-ftype-ogg' => 'Video Ogg',
+       'mwe-ftype-unk' => 'Formato de file sconossùo',
+       'rsd-wiki_commons-title' => 'Wikimedia Commons',
+       'rsd-wiki_commons' => 'Wikimedia Commons, un archivio de contenuti multimediali pedagogici soto licensa lìbara (imagini, audio e video)',
+       'rsd-this_wiki-title' => 'Sta wiki',
+       'rsd-this_wiki-desc' => 'La wiki locale',
+       'rsd-archive_org-desc' => "L'Internet Archive, na biblioteca digitale de òpare culturali",
+       'rsd-flickr-desc' => 'Flickr.com, un sito de condivision de foto',
+       'rsd-metavid-desc' => "Metavid.org, n'archivio comunitario de ati de la Càmara e del Senado mericani",
+       'mwe-select_file' => 'Selessiona file',
+       'mwe-select_ownwork' => 'Mi son drio cargar solamente el laoro mio, e lo rilassio soto la licensa:',
+       'mwe-licence_cc-by-sa' => "Creative Commons Condividi a l'istesso modo (3.0)",
+       'mwe-upload' => 'Carga file',
+       'mwe-destfilename' => 'Nome del file de destinassion:',
+       'mwe-summary' => 'Riassunto',
+       'mwe-watch-this-file' => "Tien d'ocio sto file",
+       'mwe-ignore-any-warnings' => 'Ignora i avertimenti',
+       'mwe-upload-in-progress' => "So' drio cargar (no stà sarar sta finestra)",
+       'mwe-uploaded-status' => 'Cargà',
+       'mwe-upload-stats-fileprogress' => '$1 de $2',
+       'mwe-upload_completed' => 'El to caricamento el xe stà conpletà',
+       'mwe-upload_done' => '<a href="$1">El to caricamento <i>el dovarìa</i> èssar acessìbile</a>.',
+       'mwe-upload-unknown-size' => 'Dimension sconossùa',
+       'mwe-cancel-confim' => 'Sito sicuro che te vol anular sta operassion?',
+       'mwe-successfulupload' => 'Caricamento riussìo',
+       'mwe-uploaderror' => 'Eror in tel caricamento',
+       'mwe-uploadwarning' => 'Aviso de caricamento',
+       'mwe-unknown-error' => 'Eror sconossùo:',
+       'mwe-return-to-form' => 'Torna indrìo al mòdulo',
+       'mwe-file-exists-duplicate' => "Sto file el xe un dopion de st'altro file:",
+       'mwe-fileexists-thumb' => '<center><b>File esistente</b></center>',
+       'mwe-ignorewarning' => "Ignora l'avertimento e salva istesso el file",
+       'mwe-file-thumbnail-no' => 'El nome del file el taca con <b><tt>$1</tt></b>',
+       'mwe-go-to-resource' => 'Và a la pagina de la risorsa',
+       'mwe-upload-misc-error' => 'Eror de caricamento sconossiùo',
+       'mwe-upload-multi' => 'Carga {{PLURAL:$1|file|file}}',
+       'mwe-review-upload' => 'Contròla el caricamento {{PLURAL:$1|del file|dei file}}',
+       'mwe-credit-title' => 'Titolo: $1',
+       'mwe-loading_plugin' => "so' drio cargar el plugin...",
+       'mwe-link_back' => 'Colèga indrìo',
+       'mwe-add_to_end_of_sequence' => 'Taca in fondo a la sequensa',
+       'mwe-play_clip' => 'Riprodusi',
+       'mwe-pause_clip' => 'Meti in pausa',
+       'mwe-volume_control' => 'Controlo volume',
+       'mwe-player_fullscreen' => 'Schermo intiero',
+       'mwe-seek_to' => 'Serca $1',
+       'mwe-paused' => 'en pausa',
+       'mwe-download_segment' => 'Descarga la selession:',
+       'mwe-download_full' => 'Descarga tuto el file video:',
+       'mwe-download_right_click' => 'Par descargar, struca el boton destro e selessiona <i>Salva colegamento come...</i>',
+       'mwe-download_clip' => 'Descarga el video',
+       'mwe-download' => 'Descarga',
+       'mwe-share' => 'Spartissi',
+       'mwe-credits' => 'Riconossimenti',
+       'mwe-chose_player' => 'Siegli el letor multimedial',
+       'mwe-share_this_video' => 'Condividi sto video',
+       'mwe-video_credits' => 'Riconossimenti del video',
+       'mwe-menu_btn' => 'Menù',
+       'mwe-close_btn' => 'Sara',
+       'mwe-ogg-player-vlc-player' => 'Letor VLC',
+       'mwe-ogg-player-videoElement' => 'Video Ogg nativo',
+       'mwe-ogg-player-oggPlugin' => 'Plugin Ogg generico',
+       'mwe-ogg-player-quicktime-mozilla' => 'Plugin QuickTime',
+       'mwe-ogg-player-quicktime-activex' => 'QuickTime ActiveX',
+       'mwe-ogg-player-cortado' => 'Java Cortado',
+       'mwe-ogg-player-flowplayer' => 'Flowplayer',
+       'mwe-ogg-player-kplayer' => 'Letor Kaltura',
+       'mwe-ogg-player-selected' => '(selessionà)',
+       'mwe-ogg-player-omtkplayer' => 'OMTK Flash Vorbis',
+       'mwe-playerselect' => 'Letori',
+       'mwe-read_before_embed' => '<a href="http://mediawiki.org/wiki/Security_Notes_on_Remote_Embedding" target="_new">Lèzi qua</a> prima de \'ndar vanti.',
+       'mwe-embed_site_or_blog' => 'Inserissi drento na pagina',
+       'mwe-related_videos' => 'Video ligà a sto qua',
+       'mwe-seeking' => "so' drio sercar",
+       'mwe-copy-code' => 'Copia el còdese',
+);
+
+/** Veps (Vepsan kel')
+ * @author Игорь Бродский
+ */
+$messages['vep'] = array(
+       'mwe-sc_audio' => "Audiokontrol'",
+       'mwe-template_properties' => 'Šablonan ičendad',
+       'mwe-edit_properties' => 'Redaktiruida ičendad',
+       'mwe-other_properties' => 'Toižed ičendad',
+       'mwe-resource_page' => "Purtken lehtpol':",
+       'mwe-start_time' => 'Augotišen aig',
+       'mwe-end_time' => 'Lopun aig',
+       'mwe-close' => 'saupta',
+       'mwe-menu_cliplib' => 'Ližata medijad',
+       'mwe-rmclip' => 'Heitta klip poiš',
+       'fogg-select_file' => 'Valiče fail',
+       'fogg-select_new_file' => "Valiče uz' fail",
+       'fogg-select_url' => 'Valiče URL',
+       'rsd_results_desc' => "Rezul'tatad",
+       'rsd_results_next' => "jäl'ghine",
+       'rsd_results_prev' => 'edeline',
+       'mwe-cc_by_title' => 'Attribucii',
+       'mwe-upload' => 'Jügutoitta fail',
+       'mwe-upload-unknown-size' => 'Tundmatoi suruz',
+       'mwe-uploaderror' => 'Jügutoitandan petuz',
+       'mwe-unknown-error' => 'Tundmatoi petuz:',
+       'mwe-link_back' => 'Kosketuz tagaze',
+       'mwe-play_clip' => 'Väta klip',
+       'mwe-credits' => 'Tegijad',
+       'mwe-menu_btn' => 'Menü',
+       'mwe-close_btn' => 'Saubata',
+       'mwe-ogg-player-vlc-mozilla' => 'VLC-plagin',
+       'mwe-ogg-player-quicktime-mozilla' => 'QuickTime-plagin',
+       'mwe-ogg-player-quicktime-activex' => 'QuickTime ActiveX',
+       'mwe-ogg-player-cortado' => 'Java Cortado',
+       'mwe-ogg-player-selected' => '(valitud)',
+       'mwe-playerselect' => 'Plejerad',
+);
+
+/** Vietnamese (Tiếng Việt)
+ * @author Minh Nguyen
+ * @author Vinhtantran
+ */
+$messages['vi'] = array(
+       'mwe-crop' => 'Cắt ảnh',
+       'mwe-apply_crop' => 'Cắt ảnh',
+       'mwe-reset_crop' => 'Tái tạo cắt ảnh',
+       'mwe-insert_image_page' => 'Chèn vào trang',
+       'mwe-insert_into_sequence' => 'Chèn vào dãy',
+       'mwe-preview_insert' => 'Chèn thử',
+       'mwe-cancel_image_insert' => 'Hủy chèn',
+       'mwe-sc_fileopts' => 'Sửa chi tiết clip',
+       'mwe-sc_inoutpoints' => 'Thiết lập điểm vào-ra',
+       'mwe-sc_overlays' => 'Chèn lắp',
+       'mwe-sc_audio' => 'Quản lý âm thanh',
+       'mwe-sc_duration' => 'Thời lượng',
+       'mwe-template_properties' => 'Thuộc tính mẫu',
+       'mwe-custom_title' => 'Tựa đề tùy chỉnh',
+       'mwe-edit_properties' => 'Sửa thuộc tính',
+       'mwe-other_properties' => 'Thuộc tính khác',
+       'mwe-resource_page' => 'Trang tài nguyên:',
+       'mwe-set_in_out_points' => 'Thiết lập điểm vào-ra',
+       'mwe-start_time' => 'Thời điểm bắt đầu',
+       'mwe-end_time' => 'Thời điểm kết thúc',
+       'mwe-preview_inout' => 'Nghe thử điểm vào-ra',
+       'mwe-edit-tools' => 'Công cụ sửa đổi',
+       'mwe-upload-subs-file' => 'Tải lên phụ đề',
+       'mwe-add-subs-file-title' => 'Chọn phụ đề để tải lên',
+       'mwe-error-only-srt' => 'Chỉ có thể tải lên tập tin srt.',
+       'mwe-watch-video' => 'Coi video',
+       'mwe-select-other-language' => 'Chọn ngôn ngữ khác',
+       'mwe-saving' => 'đang lưu…',
+       'mwe-select_transcript_set' => 'Chọn phụ đề',
+       'mwe-auto_scroll' => 'cuộn tự động',
+       'mwe-close' => 'đóng',
+       'mwe-improve_transcript' => 'Cải thiện',
+       'mwe-no_text_tracks_found' => 'Không tìm thấy đoạn dành cho văn bản',
+       'mwe-add-edit-subs' => 'Thêm/sửa phụ đề',
+       'mwe-transition_in' => 'Chuyển tiếp vào',
+       'mwe-transition_out' => 'Chuyển tiếp ra',
+       'mwe-effects' => 'Đống hiệu ứng',
+       'mwe-remove_transition' => 'Xóa chuyển tiếp',
+       'mwe-edit_transin' => 'Sửa chuyển tiếp vào clip',
+       'mwe-edit_transout' => 'Sửa chuyển tiếp ra khỏi clip',
+       'mwe-menu_clipedit' => 'Sửa tập tin nghe nhìn',
+       'mwe-menu_transition' => 'Điểm chuyển và hiệu ứng',
+       'mwe-menu_cliplib' => 'Thêm phương tiện',
+       'mwe-menu_resource_overview' => 'Tổng quát tài nguyên',
+       'mwe-menu_options' => 'Tùy chọn',
+       'mwe-loading_timeline' => 'Đang tải dòng thời gian ...',
+       'mwe-loading_user_rights' => 'Đang tải quyền thành viên ...',
+       'mwe-no_edit_permissions' => 'Bạn không quyền lưu thay đổi vào cảnh này',
+       'mwe-edit_clip' => 'Sửa clip',
+       'mwe-edit_save' => 'Lưu thay đổi trong cảnh',
+       'mwe-saving_wait' => 'Đang lưu (xin chờ)',
+       'mwe-save_done' => 'Đã lưu',
+       'mwe-edit_cancel' => 'Hủy sửa cảnh',
+       'mwe-edit_cancel_confirm' => 'Bạn có chắc là mình muốn hủy sửa đổi không? Các thay đổi sẽ bị mất.',
+       'mwe-zoom_in' => 'Phóng to',
+       'mwe-zoom_out' => 'Thu nhỏ',
+       'mwe-cut_clip' => 'Cắt clip',
+       'mwe-expand_track' => 'Bung track',
+       'mwe-collapse_track' => 'Thu nhỏ track',
+       'mwe-play_from_position' => 'Chơi từ vị trí playline',
+       'mwe-pixle2sec' => 'pixel sang giây',
+       'mwe-rmclip' => 'Xóa clip',
+       'mwe-no_selected_resource' => '<h3>Chưa chọn tài nguyên</h3> Hãy chọn clip để sửa đổi.',
+       'mwe-error_edit_multiple' => '<h3>Đã chọn hơn một tài nguyên</h3> Hãy chỉ chọn một clip để sửa đổi nó.',
+       'mwe-editor_options' => 'Tùy chọn sửa đổi',
+       'mwe-editor_mode' => 'Chế độ sửa đổi',
+       'mwe-simple_editor_desc' => 'bộ sửa đổi đơn giản (kiểu iMovie)',
+       'mwe-advanced_editor_desc' => 'bộ sửa đổi nâng cấp (kiểu Final Cut)',
+       'mwe-other_options' => 'Tùy chọn khác',
+       'mwe-sequencer_credit_line' => 'Do <a href="http://kaltura.com">Kaltura, Inc.</a> phát triển với sự hỗ trợ của <a href="http://wikimediafoundation.org/wiki/Trang_chủ?uselang=vi">Quỹ Wikimedia</a> (<a href="#">chi tiết</a>).',
+       'mwe-loading_txt' => 'đang tải …',
+       'mwe-size-kilobytes' => '$1 kB',
+       'mwe-ok' => 'OK',
+       'mwe-cancel' => 'Hủy bỏ',
+       'fogg-select_file' => 'Chọn tập tin',
+       'fogg-select_new_file' => 'Chọn tập tin mới',
+       'fogg-select_url' => 'Chọn URL',
+       'fogg-save_local_file' => 'Lưu thành Ogg',
+       'fogg-check_for_firefogg' => 'Đang tìm cho Firefogg …',
+       'fogg-installed' => 'Firefogg đã được cài đặt',
+       'fogg-for_improved_uploads' => 'Để tải lên tiện hơn:',
+       'fogg-please_install' => '<a href="$1">Cài Firefogg</a>. Thêm <a href="http://commons.wikimedia.org/wiki/Commons:Firefogg?uselang=vi">chi tiết về Firefogg</a>',
+       'fogg-use_latest_firefox' => 'Xin hãy cài đặt <a href="http://vi.www.mozilla.com/vi/?from=firefogg">Firefox 3.5</a> (trở lên) trước tiên. <i>Sau đó, hãy trở lại trang này để cài đặt phần mở rộng <b>Firefogg</b>.</i>',
+       'fogg-preview' => 'Xem trước video',
+       'fogg-hidepreview' => 'Ẩn phần xem trước',
+       'fogg-help-sticky' => 'Trợ giúp (nhấn chuột để giữ)',
+       'fogg-cg-meta' => 'Siêu dữ liệu của clip',
+       'fogg-preset-custom' => 'Thiết kế tùy biến',
+       'fogg-videoQuality-title' => 'Chất lượng video',
+       'fogg-starttime-title' => 'Giây bắt đầu',
+       'fogg-endtime-title' => 'Giây kết thúc',
+       'fogg-audioQuality-title' => 'Chất lượng âm thanh',
+       'fogg-novideo-title' => 'Không có video',
+       'fogg-noaudio-title' => 'Không có âm thanh',
+       'fogg-title-title' => 'Tên',
+       'fogg-date-title' => 'Ngày tháng',
+       'fogg-location-title' => 'Vị trí',
+       'fogg-organization-title' => 'Tổ chức',
+       'fogg-copyright-title' => 'Bản quyền',
+       'fogg-license-title' => 'Giấy phép',
+       'fogg-contact-title' => 'Liên lạc',
+       'fogg-contact-help' => 'Liên kết để liên lạc',
+       'mwe-media_search' => 'Tìm kiếm phương tiện',
+       'rsd_results_desc' => 'Kết quả từ $1 đến $2',
+       'rsd_results_desc_total' => 'Kết quả từ $1 đến $2 trên tổng số $3',
+       'rsd_results_next' => 'sau',
+       'rsd_results_prev' => 'trước',
+       'rsd_no_results' => 'Không có kết quả tìm kiếm cho <b>$1</b>',
+       'mwe-upload_tab' => 'Tải lên',
+       'mwe-link' => 'liên kết',
+       'mwe-cc_by_title' => 'Ghi công',
+       'mwe-cc_nc_title' => 'Phi thương mại',
+       'mwe-cc_nd_title' => 'Không cho phép tác phẩm phái sinh',
+       'mwe-cc_sa_title' => 'Chia sẻ tương tự',
+       'mwe-cc_pd_title' => 'Phạm vi công cộng',
+       'mwe-unknown_license' => 'Giấy phép không biết',
+       'mwe-results_from' => 'Kết quả từ <a href="$1" target="_new" >$2</a>',
+       'mwe-your_recent_uploads' => 'Tập tin do bạn tải lên $1 gần đây',
+       'mwe-upload_a_file' => 'Tải tập tin mới lên $1',
+       'mwe-resource_page_desc' => 'Miêu tả trang tài nguyên:',
+       'mwe-edit_resource_desc' => 'Sửa đổi văn bản wiki miêu tả tài nguyên:',
+       'mwe-watch_this_page' => 'Theo dõi trang này',
+       'mwe-do_import_resource' => 'Nhập tài nguyên',
+       'mwe-update_preview' => 'Cập nhật xem trước',
+       'mwe-cancel_import' => 'Hủy bỏ việc nhập',
+       'mwe-ftype-svg' => 'Tập tin vectơ SVG',
+       'mwe-ftype-jpg' => 'Tập tin hình JPEG',
+       'mwe-ftype-png' => 'Tập tin hình PNG',
+       'mwe-ftype-oga' => 'Tập tin âm thanh Ogg',
+       'mwe-ftype-ogg' => 'Tập tin video Ogg',
+       'mwe-ftype-unk' => 'Định dạng tập tin không hiểu',
+       'rsd-wiki_commons-title' => 'Wikimedia Commons',
+       'rsd-wiki_commons' => 'Wikimedia Commons, kho tư liệu (hình ảnh, âm thanh, và video) có giấy phép mở',
+       'rsd-this_wiki-title' => 'Wiki này',
+       'rsd-this_wiki-desc' => 'Wiki địa phương',
+       'rsd-flickr-desc' => 'Flickr.com, dịch vụ chia sẻ hình chụp trực tuyến',
+       'mwe-select_file' => 'Chọn tập tin',
+       'mwe-more_licence_options' => 'Xem thêm giấy phép tại <a href="$1">trang tải lên thường</a>',
+       'mwe-licence_cc-by-sa' => 'Creative Commons Chia sẻ tương tự (3.0)',
+       'mwe-upload' => 'Tải lên tập tin',
+       'mwe-summary' => 'Tóm lược',
+       'mwe-watch-this-file' => 'Theo dõi tập tin này',
+       'mwe-ignore-any-warnings' => 'Bỏ qua cảnh báo',
+       'mwe-upload-in-progress' => 'Đang tải lên (đừng đóng cửa sổ này)',
+       'mwe-uploaded-status' => 'Tải lên xong',
+       'mwe-upload-stats-fileprogress' => '$1 của $2',
+       'mwe-upload_completed' => 'Đã tải lên xong.',
+       'mwe-upload-unknown-size' => 'Kích cỡ không biết',
+       'mwe-cancel-confim' => 'Bạn có chắc chắn muốn hủy bỏ?',
+       'mwe-successfulupload' => 'Đã tải lên thành công',
+       'mwe-uploaderror' => 'Lỗi tải lên',
+       'mwe-uploadwarning' => 'Cảnh báo tải lên',
+       'mwe-unknown-error' => 'Lỗi không biết:',
+       'mwe-return-to-form' => 'Trở về biểu mẫu',
+       'mwe-file-exists-duplicate' => 'Tập tin này là bản sao của tập tin sau:',
+       'mwe-fileexists' => 'Một tập tin với tên này đã tồn tại, xin hãy kiểm tra lại <b><tt>$1</tt></b> nếu bạn không chắc bạn có muốn thay đổi nó hay không.',
+       'mwe-fileexists-thumb' => '<center><b>Tập tin đã tồn tại</b></center>',
+       'mwe-ignorewarning' => 'Bỏ qua cảnh báo và lưu tập tin',
+       'mwe-file-thumbnail-no' => 'Tập tin bắt đầu với <b><tt>$1</tt></b>',
+       'mwe-go-to-resource' => 'Vào trang tài nguyên',
+       'mwe-upload-multi' => 'Tải lên {{PLURAL:$1|tập tin|các tập tin}}',
+       'mwe-review-upload' => 'Duyệt {{PLURAL:$1|tập tin|các tập tin}} được tải lên',
+       'mwe-credit-title' => 'Tựa: $1',
+       'mwe-loading_plugin' => 'đang tải phần bổ trợ …',
+       'mwe-play_clip' => 'Chơi clip',
+       'mwe-pause_clip' => 'Tạm ngừng clip',
+       'mwe-player_options' => 'Tùy chọn trình chơi',
+       'mwe-player_fullscreen' => 'Toàn màn hình',
+       'mwe-next_clip_msg' => 'Chơi clip sau',
+       'mwe-prev_clip_msg' => 'Chơi clip trước',
+       'mwe-current_clip_msg' => 'Chơi clip này tiếp',
+       'mwe-seek_to' => 'Nhảy tới $1',
+       'mwe-paused' => 'đang tạm ngừng',
+       'mwe-download_segment' => 'Tải xuống lựa chọn:',
+       'mwe-download_full' => 'Tải xuống cả tập tin video:',
+       'mwe-download_right_click' => 'Để tải xuống, hãy nhấn chuột phải và chọn <i>Lưu Liên Kết dưới dạng…</i> (<i>Save Link As…</i>)',
+       'mwe-download_clip' => 'Tải xuống video',
+       'mwe-download_text' => 'Tải xuống văn bản (<a style="color:white" title="cmml" href="http://wiki.xiph.org/index.php/CMML">CMML</a> xml):',
+       'mwe-download' => 'Tải xuống',
+       'mwe-share' => 'Chia sẻ',
+       'mwe-credits' => 'Ghi công',
+       'mwe-clip_linkback' => 'Trang nguồn clip',
+       'mwe-chose_player' => 'Chọn trình chơi video',
+       'mwe-share_this_video' => 'Chia sẻ video này',
+       'mwe-video_credits' => 'Ghi công về video',
+       'mwe-menu_btn' => 'Trình đơn',
+       'mwe-close_btn' => 'Đóng',
+       'mwe-ogg-player-vlc-player' => 'Trình chơi VLC',
+       'mwe-ogg-player-videoElement' => 'Video Ogg của trình duyệt',
+       'mwe-ogg-player-oggPlugin' => 'Phần bổ trợ Ogg thường',
+       'mwe-ogg-player-quicktime-mozilla' => 'Phần bổ trợ QuickTime',
+       'mwe-ogg-player-quicktime-activex' => 'QuickTime ActiveX',
+       'mwe-ogg-player-cortado' => 'Java Cortado',
+       'mwe-ogg-player-flowplayer' => 'Flowplayer',
+       'mwe-ogg-player-kplayer' => 'Trình chơi Kaltura',
+       'mwe-ogg-player-selected' => '(được chọn)',
+       'mwe-ogg-player-omtkplayer' => 'OMTK Flash Vorbis',
+       'mwe-do_not_warn_again' => 'Tạm kệ.',
+       'mwe-playerselect' => 'Trình chơi',
+       'mwe-read_before_embed' => 'Hãy <a href="http://mediawiki.org/wiki/Security_Notes_on_Remote_Embedding?uselang=vi" target="_new">đọc cảnh báo</a> trước khi nhúng.',
+       'mwe-embed_site_or_blog' => 'Nhúng vào trang',
+       'mwe-related_videos' => 'Video liên quan',
+       'mwe-seeking' => 'đang nhảy',
+       'mwe-copy-code' => 'Chép mã',
+);
+
diff --git a/js2/mwEmbed/php/maintenance/mergeJavascriptMsg.php b/js2/mwEmbed/php/maintenance/mergeJavascriptMsg.php
new file mode 100644 (file)
index 0000000..a9c99f1
--- /dev/null
@@ -0,0 +1,227 @@
+<?php
+/**
+* Merges in JavaScript with mwEmbed.i18n.php
+*
+* @file
+* @ingroup Maintenance
+*/
+
+# Abort if called from a web server
+if ( isset( $_SERVER ) && array_key_exists( 'REQUEST_METHOD', $_SERVER ) ) {
+       print "This script must be run from the command line\n";
+       exit();
+}
+define( 'MEDIAWIKI', true );
+// get the scriptLoader globals:
+require_once( '../../jsScriptLoader.php' );
+
+$mwSTART_MSG_KEY = '$messages[\'en\'] = array(';
+$mwEND_MSG_KEY = ',
+);';
+$mwLangFilePath = '../languages/mwEmbed.i18n.php';
+include_once( $mwLangFilePath );
+
+function print_help(){
+?>
+This script helps merge msgs between javascript and php
+Usage:
+       -j merges javascript msgs into php
+       -p merges php msgs back into javascript
+       -q will disable screen output and wait time
+
+<?php
+die();
+}
+
+// get options (like override JS or override PHP)
+if ( in_array($argv[1], array('--help', '-help', '-h', '-?')) ) {
+       print_help();
+}
+$mergeToPhp = $mergeToJS = false;
+$showInfo = true;
+foreach($argv as $inx => $arg){
+       if($inx == 0)
+               continue;
+       if( $arg == '-j' ){
+               $mergeToPhp = true;
+       }else if( $arg == '-p' ) {
+               $mergeToJS = true;
+       }else if( $arg == '-q'){
+               $showInfo = false;
+       }else{
+               print_help();
+       }
+}
+
+
+if($showInfo){
+       if ( $mergeToPhp )
+       print "Will merge *Javascript to PHP* in 3 seconds ";
+
+       if ( $mergeToJS )
+       print "Will merge *PHP to Javascript* in 3 seconds ";
+
+       for ( $i = 0; $i < 3; $i++ ) {
+               print '.';
+               sleep( 1 );
+       }
+       print "\n";
+}
+
+// read in mwEmbed.i18n.php
+$rawLangFile = file_get_contents( $mwLangFilePath );
+
+$startInx = strpos( $rawLangFile, $mwSTART_MSG_KEY ) + strlen( $mwSTART_MSG_KEY );
+$endInx = strpos( $rawLangFile, $mwEND_MSG_KEY ) + 1;
+if ( $startInx === false || $endInx === false ) {
+       if($showInfo)
+               print "Could not find $mwSTART_MSG_KEY or $mwEND_MSG_KEY in mwEmbed.i18n.php\n";
+       exit();
+}
+
+$preFile = substr( $rawLangFile, 0, $startInx );
+$msgSet = substr( $rawLangFile, $startInx, $endInx - $startInx );
+$postFile = substr( $rawLangFile, $endInx );
+
+// build replacement from all javascript in mwEmbed
+$path = realpath( '../../' );
+
+$curFileName = '';
+// @@todo existing msgSet should be parsed (or we just "include" the file first)
+$msgSet = "";
+
+$objects = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $path ), RecursiveIteratorIterator::SELF_FIRST );
+foreach ( $objects as $fname => $object ) {
+       if ( substr( $fname, - 3 ) == '.js' ) {
+               $jsFileText = file_get_contents( $fname );
+               $mwPos = strpos( $fname, 'mwEmbed' ) + 7;
+               $curFileName = substr( $fname, $mwPos );
+               if ( preg_match( '/loadGM\s*\(\s*{(.*)}\s*\)\s*/siU',   // @@todo fix: will break down if someone does }) in their msg text
+               $jsFileText,
+               $matches ) ) {
+                       $msgSet .= doJsonMerge( $matches[1] );
+               }
+       }
+}
+// rebuild and output to single php file if mergeToPHP is on
+if ( $mergeToPhp ) {
+       if ( file_put_contents( $mwLangFilePath, trim( $preFile ) . "\n\t" . trim( $msgSet ) . "\n" . ltrim( $postFile ) ) ) {
+               if( $showInfo )
+                       print "updated $mwLangFilePath file\n";
+               exit();
+       }
+}
+
+function doJsonMerge( $json_txt ) {
+       global $curFileName, $fname, $messages, $mergeToJS, $jsFileText, $showInfo;
+
+       $outPhp = "\n\t/*\n";
+       $outPhp .= "\t * js file: {$curFileName}\n";
+       $outPhp .= "\t */\n";
+
+       $jsMsgAry = array();
+       $doReplaceFlag = false;
+
+       $jmsg = json_decode( '{' . $json_txt . '}', true );
+       if ( count( $jmsg ) != 0 ) {
+
+               foreach ( $jmsg as $k => $v ) {
+                       // check if the existing value is changed and merge and merge ->right
+                       if ( isset( $messages['en'][$k] ) ) {
+                               if ( $messages['en'][$k] != $v ) {
+                                       $doReplaceFlag = true;
+                                       if( $showInfo )
+                                               print "'$k'does not match:\n" . $messages['en'][$k] . "\n!=\n" . $v . "\n";
+                               }
+                               // add the actual value: (replace new lines (not compatible json)
+                               // $jsMsgAry[$k] = str_replace("\n", '\\n', $messages['en'][$k]);
+                               $jsMsgAry[$k] = $messages['en'][$k];
+                               $doReplaceFlag = true;
+                       } ;
+                       $outPhp .= "\t'{$k}' => '" . str_replace( '\'', '\\\'', $v ) . "',\n";
+               }
+               // merge the jsLanguage array back in and wrap the output
+               if ( $mergeToJS && $doReplaceFlag ) {
+                       $json = json_encode( $jsMsgAry );
+                       $json_txt = jsonReadable( $json );
+                       // escape $1 for preg replace:
+                       $json_txt = str_replace( '$', '\$', $json_txt );
+                       // print "json:\n$json_txt \n";
+                       $str = preg_replace ( '/loadGM\s*\(\s*{(.*)}\s*\)\s*/siU',
+                                               "loadGM(" . $json_txt . ")",
+                                               $jsFileText );
+
+                       // print substr($str, 0, 600);
+
+                       if ( file_put_contents( $fname, $str ) ) {
+                               if( $showInfo )
+                                       print "\nupdated $curFileName from php\n\n";
+                       } else {
+                               die( "Could not write to: " . $fname );
+                       }
+               }
+               // return phpOut for building msgSet in outer function
+               return $outPhp;
+
+       } else {
+               if($showInfo)
+                       print "Could not get any json vars from: $curFileName\n";
+               return '';
+       }
+}
+
+function jsonReadable( $json ) {
+       $tabcount = 0;
+       $result = '';
+       $inquote = false;
+       $ignorenext = false;
+
+       $tab = "\t";
+       $newline = "\n";
+
+       for ( $i = 0; $i < strlen( $json ); $i++ ) {
+               $char = $json[$i];
+
+               if ( $ignorenext ) {
+                       $result .= $char;
+                       $ignorenext = false;
+               } else {
+                       switch( $char ) {
+                               case '{':
+                                       $tabcount++;
+                                       $result .= $char . $newline . str_repeat( $tab, $tabcount );
+                                       break;
+                               case '}':
+                                       $tabcount--;
+                                       $result = trim( $result ) . $newline . str_repeat( $tab, $tabcount ) . $char;
+                                       break;
+                               case ',':
+                                       if ( $inquote ) {
+                                               $result .= $char;
+                                       } else {
+                                               $result .= $char . $newline . str_repeat( $tab, $tabcount );
+                                       }
+                               break;
+                               case ':':
+                                       if ( $inquote ) {
+                                               $result .= $char;
+                                       } else {
+                                               $result .= ' ' . $char . ' ';
+                                       }
+                                       break;
+                               case '"':
+                                       $inquote = !$inquote;
+                                       $result .= $char;
+                                       break;
+                               case '\\':
+                                       if ( $inquote ) $ignorenext = true;
+                                       $result .= $char;
+                                       break;
+                               default:
+                                       $result .= $char;
+                       }
+               }
+       }
+
+       return $result;
+}
diff --git a/js2/mwEmbed/php/minify/JSMin.php b/js2/mwEmbed/php/minify/JSMin.php
new file mode 100644 (file)
index 0000000..f8760e4
--- /dev/null
@@ -0,0 +1,289 @@
+<?php
+
+if ( !defined( 'MEDIAWIKI' ) )  die( 1 );
+/**
+ * jsmin.php - PHP implementation of Douglas Crockford's JSMin.
+ *
+ * This is pretty much a direct port of jsmin.c to PHP with just a few
+ * PHP-specific performance tweaks. Also, whereas jsmin.c reads from stdin and
+ * outputs to stdout, this library accepts a string as input and returns another
+ * string as output.
+ *
+ * PHP 5 or higher is required.
+ *
+ * Permission is hereby granted to use this version of the library under the
+ * same terms as jsmin.c, which has the following license:
+ *
+ * --
+ * Copyright (c) 2002 Douglas Crockford  (www.crockford.com)
+ *
+ * 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 shall be used for Good, not Evil.
+ *
+ * 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.
+ * --
+ *
+ * @package JSMin
+ * @author Ryan Grove <ryan@wonko.com>
+ * @copyright 2002 Douglas Crockford <douglas@crockford.com> (jsmin.c)
+ * @copyright 2008 Ryan Grove <ryan@wonko.com> (PHP port)
+ * @license http://opensource.org/licenses/mit-license.php MIT License
+ * @version 1.1.1 (2008-03-02)
+ * @link http://code.google.com/p/jsmin-php/
+ */
+
+class JSMin {
+       const ORD_LF    = 10;
+       const ORD_SPACE = 32;
+
+       protected $a           = '';
+       protected $b           = '';
+       protected $input       = '';
+       protected $inputIndex  = 0;
+       protected $inputLength = 0;
+       protected $lookAhead   = null;
+       protected $output      = '';
+
+       // -- Public Static Methods --------------------------------------------------
+
+       public static function minify( $js ) {
+               $jsmin = new JSMin( $js );
+               return $jsmin->min();
+       }
+
+       // -- Public Instance Methods ------------------------------------------------
+
+       public function __construct( $input ) {
+               $this->input       = str_replace( "\r\n", "\n", $input );
+               $this->inputLength = strlen( $this->input );
+       }
+
+       // -- Protected Instance Methods ---------------------------------------------
+
+       protected function action( $d ) {
+               switch( $d ) {
+                       case 1:
+                               $this->output .= $this->a;
+
+                       case 2:
+                               $this->a = $this->b;
+
+                               if( $this->a === "'" || $this->a === '"' ) {
+                                       for (;;) {
+                                               $this->output .= $this->a;
+                                               $this->a       = $this->get();
+
+                                               if( $this->a === $this->b ) {
+                                                       break;
+                                               }
+
+                                               if( ord( $this->a ) <= self::ORD_LF ) {
+                                                       throw new JSMinException( 'Unterminated string literal.' );
+                                               }
+
+                                               if( $this->a === '\\' ) {
+                                                       $this->output .= $this->a;
+                                                       $this->a       = $this->get();
+                                               }
+                                       }
+                               }
+
+                       case 3:
+                               $this->b = $this->next();
+
+                               if( $this->b === '/' && (
+                                       $this->a === '(' || $this->a === ',' || $this->a === '=' ||
+                                       $this->a === ':' || $this->a === '[' || $this->a === '!' ||
+                                       $this->a === '&' || $this->a === '|' || $this->a === '?' ) ) {
+
+                                               $this->output .= $this->a . $this->b;
+
+                                               for (;;) {
+                                                       $this->a = $this->get();
+
+                                                       if( $this->a === '/' ) {
+                                                               break;
+                                                       } elseif( $this->a === '\\' ) {
+                                                               $this->output .= $this->a;
+                                                               $this->a       = $this->get();
+                                                       } elseif( ord( $this->a ) <= self::ORD_LF ) {
+                                                               throw new JSMinException( 'Unterminated regular expression literal.' );
+                                                       }
+
+                                                       $this->output .= $this->a;
+                                               }
+
+                                               $this->b = $this->next();
+                               }
+               }
+       }
+
+       protected function get() {
+               $c = $this->lookAhead;
+               $this->lookAhead = null;
+
+               if( $c === null ) {
+                       if( $this->inputIndex < $this->inputLength ) {
+                               $c = $this->input[$this->inputIndex];
+                               $this->inputIndex += 1;
+                       } else {
+                               $c = null;
+                       }
+               }
+
+               if( $c === "\r" ) {
+                       return "\n";
+               }
+
+               if( $c === null || $c === "\n" || ord( $c ) >= self::ORD_SPACE ) {
+                       return $c;
+               }
+
+               return ' ';
+       }
+
+       protected function isAlphaNum( $c ) {
+               return ord( $c ) > 126 || $c === '\\' || preg_match( '/^[\w\$]$/', $c ) === 1;
+       }
+
+       protected function min() {
+               $this->a = "\n";
+               $this->action( 3 );
+
+               while( $this->a !== null ) {
+                       switch( $this->a ) {
+                               case ' ':
+                                       if( $this->isAlphaNum( $this->b ) ) {
+                                               $this->action( 1 );
+                                       } else {
+                                               $this->action( 2 );
+                                       }
+                               break;
+
+                               case "\n":
+                                       switch( $this->b ) {
+                                               case '{':
+                                               case '[':
+                                               case '(':
+                                               case '+':
+                                               case '-':
+                                                       $this->action( 1 );
+                                               break;
+
+                                               case ' ':
+                                                       $this->action( 3 );
+                                               break;
+
+                                               default:
+                                                       if( $this->isAlphaNum( $this->b ) ) {
+                                                               $this->action( 1 );
+                                                       } else {
+                                                               $this->action( 2 );
+                                                       }
+                                       }
+                               break;
+
+                               default:
+                                       switch( $this->b ) {
+                                               case ' ':
+                                                       if( $this->isAlphaNum( $this->a ) ) {
+                                                               $this->action( 1 );
+                                                               break;
+                                                       }
+
+                                                       $this->action( 3 );
+                                               break;
+
+                                               case "\n":
+                                                       switch( $this->a ) {
+                                                               case '}':
+                                                               case ']':
+                                                               case ')':
+                                                               case '+':
+                                                               case '-':
+                                                               case '"':
+                                                               case "'":
+                                                                       $this->action( 1 );
+                                                               break;
+
+                                                       default:
+                                                               if( $this->isAlphaNum( $this->a ) ) {
+                                                                       $this->action( 1 );
+                                                               } else {
+                                                                       $this->action( 3 );
+                                                               }
+                                                       }
+                                               break;
+
+                                               default:
+                                                       $this->action( 1 );
+                                               break;
+                                       }
+                       }
+               }
+
+               return $this->output;
+       }
+
+       protected function next() {
+               $c = $this->get();
+
+               if( $c === '/' ) {
+                       switch( $this->peek() ) {
+                               case '/':
+                                       for (;;) {
+                                               $c = $this->get();
+
+                                               if( ord( $c ) <= self::ORD_LF ) {
+                                                       return $c;
+                                               }
+                                       }
+
+                               case '*':
+                                       $this->get();
+
+                                       for (;;) {
+                                               switch( $this->get() ) {
+                                                       case '*':
+                                                               if( $this->peek() === '/' ) {
+                                                                       $this->get();
+                                                                       return ' ';
+                                                               }
+                                                       break;
+
+                                                       case null:
+                                                               throw new JSMinException( 'Unterminated comment.' );
+                                               }
+                                       }
+
+                               default:
+                                       return $c;
+                       }
+               }
+
+               return $c;
+       }
+
+       protected function peek() {
+               $this->lookAhead = $this->get();
+               return $this->lookAhead;
+       }
+}
+
+// -- Exceptions ---------------------------------------------------------------
+class JSMinException extends Exception {}
\ No newline at end of file
diff --git a/js2/mwEmbed/php/noMediaWikiConfig.php b/js2/mwEmbed/php/noMediaWikiConfig.php
new file mode 100644 (file)
index 0000000..66ec1cc
--- /dev/null
@@ -0,0 +1,100 @@
+<?php
+
+// Give us true for MediaWiki
+define( 'MEDIAWIKI', true );
+
+define( 'MWEMBED_STANDALONE', true );
+
+// Setup the globals:  (for documentation see: DefaultSettings.php )
+
+$wgJSAutoloadLocalClasses = array();
+
+$IP = realpath( dirname( __FILE__ ) . '/../' );
+
+// $wgMwEmbedDirectory becomes the root $IP
+$wgMwEmbedDirectory = '';
+
+$wgUseFileCache = true;
+
+// Init our wg Globals
+$wgJSAutoloadClasses = array();
+$wgJSAutoloadLocalClasses = array();
+
+/*Localization:*/
+$wgEnableScriptLocalization = true;
+
+$mwLanguageCode = 'en';
+
+$wgContLanguageCode = '';
+
+$wgStyleVersion = '218';
+
+$wgEnableScriptMinify = true;
+
+$wgUseGzip = true;
+
+
+/**
+ * Default value for chmoding of new directories.
+ */
+$wgDirectoryMode = 0777;
+
+$wgJsMimeType = 'text/javascript';
+
+// Get the autoload classes
+require_once( realpath( dirname( __FILE__ ) ) . '/jsAutoloadLocalClasses.php' );
+
+// Get the JSmin class:
+require_once( realpath( dirname( __FILE__ ) ) . '/minify/JSMin.php' );
+
+// Get the messages file:
+require_once( realpath( dirname( __FILE__ ) ) . '/languages/mwEmbed.i18n.php' );
+
+function wfDebug() {
+    return false;
+}
+
+/**
+ * Make directory, and make all parent directories if they don't exist
+ *
+ * @param string $dir Full path to directory to create
+ * @param int $mode Chmod value to use, default is $wgDirectoryMode
+ * @param string $caller Optional caller param for debugging.
+ * @return bool
+ */
+function wfMkdirParents( $dir, $mode = null, $caller = null ) {
+       global $wgDirectoryMode;
+
+       if ( !is_null( $caller ) ) {
+               wfDebug( "$caller: called wfMkdirParents($dir)" );
+       }
+
+       if ( strval( $dir ) === '' || file_exists( $dir ) )
+               return true;
+
+       if ( is_null( $mode ) )
+               $mode = $wgDirectoryMode;
+
+       return @mkdir( $dir, $mode, true );  // PHP5 <3
+}
+function wfMsgGetKey( $msgKey, $na, $langKey=false ) {
+    global $messages, $mwLanguageCode;
+    if(!$langKey){
+       $langKey = $mwLanguageCode;
+    }
+    if ( isset( $messages[$mwLanguageCode] ) && isset( $messages[$langKey][$msgKey] ) ) {
+        return $messages[$langKey][$msgKey];
+    } else {
+        return '&lt;' . $msgKey . '&gt;';
+    }
+}
+/* mediaWiki abstracts the json functions with fallbacks
+* here we just map directly to the call */
+class FormatJson{
+       public static function encode($value, $isHtml=false){
+               return json_encode($value);
+       }
+       public static function decode( $value, $assoc=false ){
+               return json_decode( $value, $assoc );
+       }
+}
diff --git a/js2/mwEmbed/php/script-cache/README b/js2/mwEmbed/php/script-cache/README
new file mode 100644 (file)
index 0000000..9704dc4
--- /dev/null
@@ -0,0 +1,6 @@
+This folder holds cached versions of grouped script requests
+
+Be sure to enable write access by your web-server to this directory. 
+
+You can empty this directory at any time and should not be a problem.
+
diff --git a/js2/mwEmbed/skins/common/remote_cp/archive_org_logo_17.png b/js2/mwEmbed/skins/common/remote_cp/archive_org_logo_17.png
new file mode 100644 (file)
index 0000000..148ff15
Binary files /dev/null and b/js2/mwEmbed/skins/common/remote_cp/archive_org_logo_17.png differ
diff --git a/js2/mwEmbed/skins/common/remote_cp/archive_org_logo_80.png b/js2/mwEmbed/skins/common/remote_cp/archive_org_logo_80.png
new file mode 100644 (file)
index 0000000..6d7701c
Binary files /dev/null and b/js2/mwEmbed/skins/common/remote_cp/archive_org_logo_80.png differ
diff --git a/js2/mwEmbed/skins/common/remote_cp/archive_org_tab.png b/js2/mwEmbed/skins/common/remote_cp/archive_org_tab.png
new file mode 100644 (file)
index 0000000..6df1b66
Binary files /dev/null and b/js2/mwEmbed/skins/common/remote_cp/archive_org_tab.png differ
diff --git a/js2/mwEmbed/skins/common/remote_cp/combined_tab.png b/js2/mwEmbed/skins/common/remote_cp/combined_tab.png
new file mode 100644 (file)
index 0000000..d49cc70
Binary files /dev/null and b/js2/mwEmbed/skins/common/remote_cp/combined_tab.png differ
diff --git a/js2/mwEmbed/skins/common/remote_cp/flickr_tab.png b/js2/mwEmbed/skins/common/remote_cp/flickr_tab.png
new file mode 100644 (file)
index 0000000..3b21de4
Binary files /dev/null and b/js2/mwEmbed/skins/common/remote_cp/flickr_tab.png differ
diff --git a/js2/mwEmbed/skins/common/remote_cp/metavid_logo_17.png b/js2/mwEmbed/skins/common/remote_cp/metavid_logo_17.png
new file mode 100644 (file)
index 0000000..556d7eb
Binary files /dev/null and b/js2/mwEmbed/skins/common/remote_cp/metavid_logo_17.png differ
diff --git a/js2/mwEmbed/skins/common/remote_cp/metavid_tab.png b/js2/mwEmbed/skins/common/remote_cp/metavid_tab.png
new file mode 100644 (file)
index 0000000..b3b6f8f
Binary files /dev/null and b/js2/mwEmbed/skins/common/remote_cp/metavid_tab.png differ
diff --git a/js2/mwEmbed/skins/common/remote_cp/this_wiki_logo_17.png b/js2/mwEmbed/skins/common/remote_cp/this_wiki_logo_17.png
new file mode 100644 (file)
index 0000000..f10ab33
Binary files /dev/null and b/js2/mwEmbed/skins/common/remote_cp/this_wiki_logo_17.png differ
diff --git a/js2/mwEmbed/skins/common/remote_cp/this_wiki_tab.png b/js2/mwEmbed/skins/common/remote_cp/this_wiki_tab.png
new file mode 100644 (file)
index 0000000..a01d776
Binary files /dev/null and b/js2/mwEmbed/skins/common/remote_cp/this_wiki_tab.png differ
diff --git a/js2/mwEmbed/skins/common/remote_cp/wiki_commons_logo_17.png b/js2/mwEmbed/skins/common/remote_cp/wiki_commons_logo_17.png
new file mode 100644 (file)
index 0000000..8fdd575
Binary files /dev/null and b/js2/mwEmbed/skins/common/remote_cp/wiki_commons_logo_17.png differ
diff --git a/js2/mwEmbed/skins/common/remote_cp/wiki_commons_logo_80.png b/js2/mwEmbed/skins/common/remote_cp/wiki_commons_logo_80.png
new file mode 100644 (file)
index 0000000..e55aca0
Binary files /dev/null and b/js2/mwEmbed/skins/common/remote_cp/wiki_commons_logo_80.png differ
diff --git a/js2/mwEmbed/skins/common/remote_cp/wiki_commons_tab.png b/js2/mwEmbed/skins/common/remote_cp/wiki_commons_tab.png
new file mode 100644 (file)
index 0000000..200522d
Binary files /dev/null and b/js2/mwEmbed/skins/common/remote_cp/wiki_commons_tab.png differ
diff --git a/js2/mwEmbed/skins/common/transition_images/fade_crossfade.png b/js2/mwEmbed/skins/common/transition_images/fade_crossfade.png
new file mode 100644 (file)
index 0000000..e320e7c
Binary files /dev/null and b/js2/mwEmbed/skins/common/transition_images/fade_crossfade.png differ
diff --git a/js2/mwEmbed/skins/common/transition_images/fade_fadeFromColor.png b/js2/mwEmbed/skins/common/transition_images/fade_fadeFromColor.png
new file mode 100644 (file)
index 0000000..b4851b6
Binary files /dev/null and b/js2/mwEmbed/skins/common/transition_images/fade_fadeFromColor.png differ
diff --git a/js2/mwEmbed/skins/common/transition_images/transition_wipe.png b/js2/mwEmbed/skins/common/transition_images/transition_wipe.png
new file mode 100644 (file)
index 0000000..f4350da
Binary files /dev/null and b/js2/mwEmbed/skins/common/transition_images/transition_wipe.png differ
diff --git a/js2/mwEmbed/skins/ctrlBuilder.js b/js2/mwEmbed/skins/ctrlBuilder.js
new file mode 100644 (file)
index 0000000..f9cb92e
--- /dev/null
@@ -0,0 +1,438 @@
+// set the dismissNativeWarn flag:
+_global['dismissNativeWarn'] = false;
+
+/**
+* Msg text is inherited from embedVideo (we should move it here (although can't load ctrlBuilder without parent EmbedVideo obj)
+/
+
+/**
+* base ctrlBuilder object
+*      @param the embedVideo element we are targeting
+*/
+var ctrlBuilder = function( embedObj ) {
+       return this.init( embedObj );
+};
+
+/*
+ * controlsBuilder prototype:
+ */
+ctrlBuilder.prototype = {
+       init:function( embedObj, opt ) {
+               var _this = this;
+               this.embedObj = embedObj;
+
+               // check for skin overrides for ctrlBuilder
+               if ( _global[ embedObj.skin_name + 'Config'] ) {
+                       // clone as to not override prototype:  
+                       var _this = $j.extend( true, { }, this, _global[ embedObj.skin_name + 'Config'] );
+                       return _this;
+               }
+               return this;
+       },
+       pClass : 'mv-player',
+       long_time_disp: true,
+       body_options : true,
+       // default volume layout is "vertical"
+       volume_layout : 'vertical',
+       height:29,
+       supports: {
+                 'options':true,
+                 'borders':true
+       },
+       getControls:function() {
+               // set up local pointer to the embedObj
+               var embedObj = this.embedObj;
+               // set up loadl ctrlBuilder ref
+               var _this = this;
+
+               js_log( 'f:controlsBuilder:: opt:' + this.options );
+               this.id = ( embedObj.pc ) ? embedObj.pc.pp.id:embedObj.id;
+               this.available_width = embedObj.playerPixelWidth();
+               
+               // Make pointer to the embedObj
+               this.embedObj = embedObj;
+               var _this = this;
+               for ( var i in embedObj.supports ) {
+                       _this.supports[i] = embedObj.supports[i];
+               };
+
+               // Special case vars:
+               if ( ( embedObj.roe ||
+                         embedObj.wikiTitleKey ||
+                               ( embedObj.media_element.timedTextSources &&
+                               embedObj.media_element.timedTextSources() )
+                       )  && embedObj.show_meta_link  )
+                       this.supports['closed_captions'] = true;
+
+
+               // Append options to body (if not already there)
+               if ( _this.body_options && $j( '#mv_vid_options_' + this.id ).length == 0 )
+                       $j( 'body' ).append( this.components['mv_embedded_options'].o( this ) );
+
+               var o = '';
+               for ( var i in this.components ) {
+                       if ( this.supports[i] ) {
+                               if ( this.available_width > this.components[i].w ) {
+                                       // Special case with playhead don't add unless we have 60px
+                                       if ( i == 'play_head' && this.available_width < 60 )
+                                               continue;
+                                       o += this.components[i].o( this  );
+                                       this.available_width -= this.components[i].w;
+                               } else {
+                                       js_log( 'not enough space for control component:' + i );
+                               }
+                       }
+               }
+               return o;
+       },
+        /*
+        * addControlHooks
+        * to be run once controls are attached to the dom
+        */
+       addControlHooks:function( $tp ) {
+               // Set up local pointer to the embedObj
+               var embedObj = this.embedObj;
+               var _this = this;                               
+
+               if ( !$tp )
+                       $tp = $j( '#' + embedObj.id );
+               
+               
+               // Add play hook:
+               $tp.find( '.play-btn,.play-btn-large' ).unbind().btnBind().click( function() {
+                       embedObj.play();
+               } );
+
+               // Add recommend firefox if we have non-native playback:
+               if ( embedObj.doNativeWarningCheck() ) {
+                       $j( '#dc_' + embedObj.id ).hover(
+                               function() {
+                                       if ( $j( '#gnp_' + embedObj.id ).length == 0 ) {
+                                               var toppos = ( embedObj.instanceOf == 'mvPlayList' ) ? 25:10;
+                                               $j( this ).append( '<div id="gnp_' + embedObj.id + '" class="ui-state-highlight ui-corner-all" ' +
+                                                       'style="position:absolute;display:none;background:#FFF;top:' + toppos + 'px;left:10px;right:10px;">' +
+                                                       gM( 'mwe-for_best_experience' ) +
+                                               '<br><input id="ffwarn_' + embedObj.id + '" type=\"checkbox\">' +
+                                                       gM( 'mwe-do_not_warn_again' ) +
+                                               '</div>' );
+                                               $j( '#ffwarn_' + embedObj.id ).click( function() {
+                                                       if ( $j( this ).is( ':checked' ) ) {
+                                                               // set up a cookie for 7 days:
+                                                               $j.cookie( 'dismissNativeWarn', true, { expires: 7 } );
+                                                               // set the current instance
+                                                               _global['dismissNativeWarn'] = true;
+                                                               $j( '#gnp_' + embedObj.id ).fadeOut( 'slow' );
+                                                       } else {
+                                                               _global['adismissNativeWarn'] = false;
+                                                               $j.cookie( 'dismissNativeWarn', false );
+                                                       }
+
+                                               } );
+                                       }
+                                       if ( ( $j.cookie( 'dismissNativeWarn' ) !== true ) &&
+                                               _global['dismissNativeWarn'] === false  ) {
+                                               $j( '#gnp_' + embedObj.id ).fadeIn( 'slow' );
+                                       }
+                               },
+                               function() {
+                                       $j( '#gnp_' + embedObj.id ).fadeOut( 'slow' );
+                               }
+                       );
+               }
+
+               if ( $j.browser.msie  &&  $j.browser.version <= 6 ) {
+                       $j( embedObj.id + ' .play-btn-large' ).pngFix();
+               }
+
+
+               // Captions binding:
+               $tp.find( '.timed-text' ).unbind().btnBind().click( function() {
+                       embedObj.showTextInterface();
+               } );
+
+               // Options binding:
+               $tp.find( '.options-btn' ).unbind().btnBind().click( function() {
+                       embedObj.doOptionsHTML();
+               } );
+
+               // Fullscreen binding:
+               $tp.find( '.fullscreen-btn' ).unbind().btnBind().click( function() {
+                       embedObj.fullscreen();
+               } );
+
+               js_log( " should add slider binding: " + $tp.find( '.play_head' ).length );
+               $tp.find( '.play_head' ).slider( {
+                       range: "min",
+                       value: 0,
+                       min: 0,
+                       max: 1000,
+                       start: function( event, ui ) {
+                               var id = ( embedObj.pc != null ) ? embedObj.pc.pp.id:embedObj.id;
+                               embedObj.userSlide = true;
+                               $j( id + ' .play-btn-large' ).fadeOut( 'fast' );
+                               // If playlist always start at 0
+                               embedObj.start_time_sec = ( embedObj.instanceOf == 'mvPlayList' ) ? 0:
+                                                               npt2seconds( embedObj.getTimeReq().split( '/' )[0] );
+                       },
+                       slide: function( event, ui ) {
+                               var perc = ui.value / 1000;
+                               embedObj.jump_time = seconds2npt( parseFloat( parseFloat( embedObj.getDuration() ) * perc ) + embedObj.start_time_sec );
+                               // js_log('perc:' + perc + ' * ' + embedObj.getDuration() + ' jt:'+  this.jump_time);
+                               if ( _this.long_time_disp ) {
+                                       embedObj.setStatus( gM( 'mwe-seek_to', embedObj.jump_time ) );
+                               } else {
+                                       embedObj.setStatus( embedObj.jump_time );
+                               }
+                               // Update the thumbnail / frame
+                               if ( embedObj.isPlaying == false ) {
+                                       embedObj.updateThumbPerc( perc );
+                               }
+                       },
+                       change:function( event, ui ) {
+                               // only run the onChange event if done by a user slide 
+                               // (otherwise it runs times it should not)
+                               if ( embedObj.userSlide ) {
+                                       embedObj.userSlide = false;
+                                       embedObj.seeking = true;
+                                       // stop the monitor timer (if we can)
+                                       if ( embedObj.stopMonitor )
+                                               embedObj.stopMonitor();
+
+                                       var perc = ui.value / 1000;
+                                       // set seek time (in case we have to do a url seek)
+                                       embedObj.seek_time_sec = npt2seconds( embedObj.jump_time, true );
+                                       js_log( 'do jump to: ' + embedObj.jump_time + ' perc:' + perc + ' sts:' + embedObj.seek_time_sec );
+                                       embedObj.setStatus( gM( 'mwe-seeking' ) );
+                                       embedObj.doSeek( perc );
+                               }
+                       }
+               } );
+               // Up the z-index of the default status indicator:
+               $tp.find( '.play_head .ui-slider-handle' ).css( 'z-index', 4 );
+               $tp.find( '.play_head .ui-slider-range' ).addClass( 'ui-corner-all' ).css( 'z-index', 2 );
+               
+               // Extended class list for jQuery ui themeing 
+               //(we can probably refactor this with custom buffering highlighter)
+               $tp.find( '.play_head' ).append( this.getBufferHtml() );
+                       
+               $opt = $j( '#mv_vid_options_' + embedObj.id );
+               // videoOptions ... @@todo should be merged with something more like kskin.js:
+               $opt.find( '.vo_selection' ).click( function() {
+                       embedObj.displayHTML();
+                       embedObj.showPlayerselect( $tp.find( '.videoOptionsComplete' ) );
+                       $opt.hide();
+                       return false;
+               } );
+               $opt.find( '.vo_download' ).click( function() {
+                       embedObj.displayHTML();
+                       embedObj.showDownload( $tp.find( '.videoOptionsComplete' ) );
+                       $opt.hide();
+                       return false;
+               } )
+               $opt.find( '.vo_showcode' ).click( function() {
+                       embedObj.displayHTML();
+                       embedObj.showShare( $tp.find( '.videoOptionsComplete' ) );
+                       $opt.hide();
+                       return false;
+               } );
+               this.doVolumeBinding();
+               
+               // Check if we have any custom skin Bindings to run
+               if ( this.addSkinControlBindings && typeof( this.addSkinControlBindings ) == 'function' )
+                       this.addSkinControlBindings();
+       },
+       doVolumeBinding:function() {
+               var embedObj = this.embedObj;
+               var _this = this;
+               var $tp = $j( '#' + embedObj.id );
+               $tp.find( '.volume_control' ).unbind().btnBind().click( function() {
+                       js_log( 'clicked volume control' );
+                       $j( '#' + embedObj.id ).get( 0 ).toggleMute();
+               } );
+               
+               // Add vertical volume display hover
+               if ( this.volume_layout == 'vertical' ) {
+                       // default volume binding:
+                       var hoverOverDelay = false;
+                       var $tpvol = $tp.find( '.vol_container' );
+                       $tp.find( '.volume_control' ).hover(
+                               function() {
+                                       $tpvol.addClass( 'vol_container_top' );
+                                       // set to "below" if playing and embedType != native
+                                       if ( embedObj && embedObj.isPlaying && embedObj.isPlaying() && !embedObj.supports['overlays'] ) {
+                                               $tpvol.removeClass( 'vol_container_top' ).addClass( 'vol_container_below' );
+                                       }
+                                       $tpvol.fadeIn( 'fast' );
+                                       hoverOverDelay = true;
+                               },
+                               function() {
+                                       hoverOverDelay = false;
+                                       setTimeout( function doHideVolume() {
+                                               if ( !hoverOverDelay ) {
+                                                       $tpvol.fadeOut( 'fast' );
+                                               }
+                                       }, 500 );
+                               }
+                       );
+               }
+               
+               // Setup play-head slider:
+               var sliderConf = {
+                       range: "min",
+                       value: 80,
+                       min: 0,
+                       max: 100,
+                       slide: function( event, ui ) {
+                               var perc = ui.value / 100;
+                               // js_log('update volume:' + perc);
+                               embedObj.updateVolumen( perc );
+                       },
+                       change:function( event, ui ) {
+                               var perc = ui.value / 100;
+                               if ( perc == 0 ) {
+                                       $tp.find( '.volume_control span' ).removeClass( 'ui-icon-volume-on' ).addClass( 'ui-icon-volume-off' );
+                               } else {
+                                       $tp.find( '.volume_control span' ).removeClass( 'ui-icon-volume-off' ).addClass( 'ui-icon-volume-on' );
+                               }
+                               var perc = ui.value / 100;
+                               embedObj.updateVolumen( perc );
+                       }
+               }
+               
+               if ( this.volume_layout == 'vertical' )
+                       sliderConf['orientation'] = "vertical";
+               
+               $tp.find( '.volume-slider' ).slider( sliderConf );
+       },
+       /*
+       * Gets the Buffer Html that overlays the playhead
+       */
+       getBufferHtml:function() {
+               return '<div class="ui-slider-range ui-slider-range-min ui-widget-header ' +
+                               'ui-state-highlight ui-corner-all ' +
+                               'mv_buffer" style="width:0px;height:100%;z-index:1;top:0px" />';
+       },
+       getComponent:function( component ) {
+               if ( this.components[ component ] ) {
+                       return this.components[ component ].o( this );
+               } else {
+                       return false;
+               }
+       },
+       /*
+       * components take in the embedObj and return some html for the given component.
+       * components can be overwritten by skin javascript
+       */
+       components: {
+               'borders': {
+                       'w':8,
+                       'o':function( ctrlObj ) {
+                               return  '';
+                       }
+               },
+               'play-btn-large': {
+                       'w' : 130,
+                       'h' : 96,
+                       'o':function( ctrlObj ) {
+                               // get dynamic position for big play button (@@todo maybe use margin:auto ? )
+                               return $j( '<div/>' ).attr( {
+                                                               'title' : gM( 'mwe-play_clip' ),
+                                                               'class' : "ui-state-default play-btn-large"
+                                                       } )
+                                                       .css( {
+                                                               'left'  : ( ( ctrlObj.embedObj.playerPixelWidth() - this.w ) / 2 ),
+                                                               'top'   : ( ( ctrlObj.embedObj.playerPixelHeight() - this.h ) / 2 )
+                                                       } )
+                                                       .wrap( '<div/>' ).parent().html();
+                       }
+               },
+               'mv_embedded_options': {
+                       'w':0,
+                       'o':function( ctrlObj ) {
+                               var o = '<div id="mv_vid_options_' + ctrlObj.id + '" class="videoOptions">' +
+                               '<div class="videoOptionsTop"></div>' +
+                               '<div class="videoOptionsBox">' +
+                               '<div class="block">' +
+                                       '<h6>Video Options</h6>' +
+                               '</div>' +
+                                       '<div class="block">' +
+                                               '<p class="short_match vo_selection"><a href="#"><span>' + gM( 'mwe-chose_player' ) + '</span></a></p>' +
+                                               '<p class="short_match vo_download"><a href="#"><span>' + gM( 'mwe-download' ) + '</span></a></p>' +
+                                               '<p class="short_match vo_showcode"><a href="#"><span>' + gM( 'mwe-share' ) + '</span></a></p>';
+
+                                       // link to the stream page if we are not already there:
+                                       if ( ( ctrlObj.embedObj.roe || ctrlObj.embedObj.linkback ) && typeof mv_stream_interface == 'undefined' )
+                                               o += '<p class="short_match"><a href="javascript:$j(\'#' + ctrlObj.id + '\').get(0).doLinkBack()"><span><strong>Source Page</strong></span></a></p>';
+
+                               o += '</div>' +
+                               '</div><!--videoOptionsInner-->' +
+                                       '<div class="videoOptionsBot"></div>' +
+                               '</div><!--videoOptions-->';
+                               return o;
+                       }
+               },
+               'fullscreen': {
+                       'w':20,
+                       'o':function( ctrlObj ) {
+                               return '<div title="' + gM( 'mwe-player_fullscreen' ) + '" class="ui-state-default ui-corner-all ui-icon_link rButton fullscreen-btn">' +
+                                                       '<span class="ui-icon ui-icon-arrow-4-diag"></span>' +
+                                               '</div>'
+                       }
+               },
+               'options': {
+                       'w':26,
+                       'o':function( ctrlObj ) {
+                               return '<div title="' + gM( 'mwe-player_options' ) + '" class="ui-state-default ui-corner-all ui-icon_link rButton options-btn">' +
+                                                       '<span class="ui-icon ui-icon-wrench"></span>' +
+                                               '</div>';
+                       }
+               },
+               'pause': {
+                       'w':24,
+                       'o':function( ctrlObj ) {
+                               return '<div title="' + gM( 'mwe-play_clip' ) + '" class="ui-state-default ui-corner-all ui-icon_link lButton play-btn">' +
+                                                       '<span class="ui-icon ui-icon-play"/>' +
+                                               '</div>';
+                       }
+               },
+               'closed_captions': {
+                       'w':23,
+                       'o':function( ctrlObj ) {
+                               return '<div title="' + gM( 'mwe-closed_captions' ) + '" class="ui-state-default ui-corner-all ui-icon_link rButton timed-text">' +
+                                                       '<span class="ui-icon ui-icon-comment"></span>' +
+                                               '</div>'
+                       }
+               },
+               'volume_control': {
+                       'w':23,
+                       'o':function( ctrlObj ) {
+                               var o = '';
+                               if ( ctrlObj.volume_layout == 'horizontal' )
+                                       o += '<div class="ui-slider ui-slider-horizontal rButton volume-slider"></div>';
+                                       
+                               o += '<div title="' + gM( 'mwe-volume_control' ) + '" class="ui-state-default ui-corner-all ui-icon_link rButton volume_control">' +
+                                               '<span class="ui-icon ui-icon-volume-on"></span>';
+                                               
+                               if ( ctrlObj.volume_layout == 'vertical' ) {
+                                       o += '<div style="position:absolute;display:none;left:0px;" class="vol_container ui-corner-all">' +
+                                                       '<div class="volume-slider" ></div>' +
+                                               '</div>';
+                               }
+                               o += '</div>';
+                               return o;
+                       }
+               },
+               'time_display': {
+                       'w':90,
+                       'o':function( ctrlObj ) {
+                               return '<div class="ui-widget time-disp">' + ctrlObj.embedObj.getTimeReq() + '</div>';
+                       }
+               },
+               'play_head': {
+                       'w':0, // special case (takes up remaining space)
+                       'o':function( ctrlObj ) {
+                               return '<div class="play_head" style="width: ' + ( ctrlObj.available_width - 34 ) + 'px;"></div>';
+                       }
+               }
+       }
+};
diff --git a/js2/mwEmbed/skins/kskin/images/kaltura_open_source_video_platform.gif b/js2/mwEmbed/skins/kskin/images/kaltura_open_source_video_platform.gif
new file mode 100644 (file)
index 0000000..cf05af2
Binary files /dev/null and b/js2/mwEmbed/skins/kskin/images/kaltura_open_source_video_platform.gif differ
diff --git a/js2/mwEmbed/skins/kskin/images/kaltura_open_source_video_platform.png b/js2/mwEmbed/skins/kskin/images/kaltura_open_source_video_platform.png
new file mode 100644 (file)
index 0000000..9d438b5
Binary files /dev/null and b/js2/mwEmbed/skins/kskin/images/kaltura_open_source_video_platform.png differ
diff --git a/js2/mwEmbed/skins/kskin/images/ksprite.png b/js2/mwEmbed/skins/kskin/images/ksprite.png
new file mode 100644 (file)
index 0000000..ed5ec08
Binary files /dev/null and b/js2/mwEmbed/skins/kskin/images/ksprite.png differ
diff --git a/js2/mwEmbed/skins/kskin/images/ui-bg_flat_0_aaaaaa_40x100.png b/js2/mwEmbed/skins/kskin/images/ui-bg_flat_0_aaaaaa_40x100.png
new file mode 100644 (file)
index 0000000..5b5dab2
Binary files /dev/null and b/js2/mwEmbed/skins/kskin/images/ui-bg_flat_0_aaaaaa_40x100.png differ
diff --git a/js2/mwEmbed/skins/kskin/images/ui-bg_flat_75_ffffff_40x100.png b/js2/mwEmbed/skins/kskin/images/ui-bg_flat_75_ffffff_40x100.png
new file mode 100644 (file)
index 0000000..ac8b229
Binary files /dev/null and b/js2/mwEmbed/skins/kskin/images/ui-bg_flat_75_ffffff_40x100.png differ
diff --git a/js2/mwEmbed/skins/kskin/images/ui-bg_glass_55_fbf9ee_1x400.png b/js2/mwEmbed/skins/kskin/images/ui-bg_glass_55_fbf9ee_1x400.png
new file mode 100644 (file)
index 0000000..ad3d634
Binary files /dev/null and b/js2/mwEmbed/skins/kskin/images/ui-bg_glass_55_fbf9ee_1x400.png differ
diff --git a/js2/mwEmbed/skins/kskin/images/ui-bg_glass_65_ffffff_1x400.png b/js2/mwEmbed/skins/kskin/images/ui-bg_glass_65_ffffff_1x400.png
new file mode 100644 (file)
index 0000000..42ccba2
Binary files /dev/null and b/js2/mwEmbed/skins/kskin/images/ui-bg_glass_65_ffffff_1x400.png differ
diff --git a/js2/mwEmbed/skins/kskin/images/ui-bg_glass_75_dadada_1x400.png b/js2/mwEmbed/skins/kskin/images/ui-bg_glass_75_dadada_1x400.png
new file mode 100644 (file)
index 0000000..5a46b47
Binary files /dev/null and b/js2/mwEmbed/skins/kskin/images/ui-bg_glass_75_dadada_1x400.png differ
diff --git a/js2/mwEmbed/skins/kskin/images/ui-bg_glass_75_e6e6e6_1x400.png b/js2/mwEmbed/skins/kskin/images/ui-bg_glass_75_e6e6e6_1x400.png
new file mode 100644 (file)
index 0000000..86c2baa
Binary files /dev/null and b/js2/mwEmbed/skins/kskin/images/ui-bg_glass_75_e6e6e6_1x400.png differ
diff --git a/js2/mwEmbed/skins/kskin/images/ui-bg_glass_95_fef1ec_1x400.png b/js2/mwEmbed/skins/kskin/images/ui-bg_glass_95_fef1ec_1x400.png
new file mode 100644 (file)
index 0000000..4443fdc
Binary files /dev/null and b/js2/mwEmbed/skins/kskin/images/ui-bg_glass_95_fef1ec_1x400.png differ
diff --git a/js2/mwEmbed/skins/kskin/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/js2/mwEmbed/skins/kskin/images/ui-bg_highlight-soft_75_cccccc_1x100.png
new file mode 100644 (file)
index 0000000..7c9fa6c
Binary files /dev/null and b/js2/mwEmbed/skins/kskin/images/ui-bg_highlight-soft_75_cccccc_1x100.png differ
diff --git a/js2/mwEmbed/skins/kskin/images/ui-icons_222222_256x240.png b/js2/mwEmbed/skins/kskin/images/ui-icons_222222_256x240.png
new file mode 100644 (file)
index 0000000..ee039dc
Binary files /dev/null and b/js2/mwEmbed/skins/kskin/images/ui-icons_222222_256x240.png differ
diff --git a/js2/mwEmbed/skins/kskin/images/ui-icons_2e83ff_256x240.png b/js2/mwEmbed/skins/kskin/images/ui-icons_2e83ff_256x240.png
new file mode 100644 (file)
index 0000000..45e8928
Binary files /dev/null and b/js2/mwEmbed/skins/kskin/images/ui-icons_2e83ff_256x240.png differ
diff --git a/js2/mwEmbed/skins/kskin/images/ui-icons_454545_256x240.png b/js2/mwEmbed/skins/kskin/images/ui-icons_454545_256x240.png
new file mode 100644 (file)
index 0000000..7ec70d1
Binary files /dev/null and b/js2/mwEmbed/skins/kskin/images/ui-icons_454545_256x240.png differ
diff --git a/js2/mwEmbed/skins/kskin/images/ui-icons_888888_256x240.png b/js2/mwEmbed/skins/kskin/images/ui-icons_888888_256x240.png
new file mode 100644 (file)
index 0000000..5ba708c
Binary files /dev/null and b/js2/mwEmbed/skins/kskin/images/ui-icons_888888_256x240.png differ
diff --git a/js2/mwEmbed/skins/kskin/images/ui-icons_cd0a0a_256x240.png b/js2/mwEmbed/skins/kskin/images/ui-icons_cd0a0a_256x240.png
new file mode 100644 (file)
index 0000000..7930a55
Binary files /dev/null and b/js2/mwEmbed/skins/kskin/images/ui-icons_cd0a0a_256x240.png differ
diff --git a/js2/mwEmbed/skins/kskin/kskin.js b/js2/mwEmbed/skins/kskin/kskin.js
new file mode 100644 (file)
index 0000000..c7e42a7
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+* skin js allows you to override contrlBuilder html/class output
+*/
+
+loadGM( {
+       "mwe-credit-title" : "Title: $1",
+       "mwe-kaltura-platform-title" : "Kaltura open source video platform"
+} );
+
+var kskinConfig = {
+       pClass: 'k-player',
+       // display time progress
+       long_time_disp: false,
+       body_options: false,
+       volume_layout: 'horizontal',
+       menu_items:[
+               'playerselect',
+               'download',
+               'share',
+               'credits',
+       ],
+       components: {
+               'play-btn-large' : {
+                       'h' : 55
+               },
+               'options': {
+                       'w':50,
+                       'o':function() {
+                               return '<div class="ui-state-default ui-corner-bl rButton k-options" title="' + gM( 'mwe-player_options' ) + '" >' +
+                                                       '<span>' + gM( 'mwe-menu_btn' ) + '</span>' +
+                                               '</div>'
+                       }
+               },
+               'time_display': {
+                       'w':70
+               },
+               'mv_embedded_options': {
+                       'w':0,
+                       'o':function( ctrlObj ) {
+                               var embedObj = ctrlObj.embedObj;
+                               var o = '' +
+                               '<div class="k-menu ui-widget-content" ' +
+                                       'style="width:' + embedObj.playerPixelWidth() + 'px; height:' + embedObj.playerPixelHeight() + 'px;">' +
+                                               '<ul class="k-menu-bar">';
+                                                       // output menu item containers: 
+                                                       for ( i = 0; i < ctrlObj.menu_items.length; i++ ) {
+                                                               var mk = ctrlObj.menu_items[i];
+                                                               o += '<li class="k-' + mk + '-btn" rel="' + mk + '">' +
+                                                                               '<a href="#" title="' + gM( 'mwe-' + mk ) + '">' + gM( 'mwe-' + mk ) + '</a></li>';
+                                                       }
+                                               o += '</ul>' +
+                                               // We have to subtract the width of the k-menu-bar
+                                               '<div class="k-menu-screens" style="width:' + ( embedObj.playerPixelWidth() - 75 ) +
+                                                       'px; height:' + ( embedObj.playerPixelHeight() - ctrlBuilder.height ) + 'px;">';
+                                               
+                                               // Output menu item containers: 
+                                               for ( i = 0; i < ctrlObj.menu_items.length; i++ ) {
+                                                       o += '<div class="menu-screen menu-' + ctrlObj.menu_items[i] + '"></div>';
+                                               }
+                                               '</div>' +
+                                       '</div>';
+                               return o;
+                       }
+               }
+       },
+       /**
+       * Adds the skin Control Bindings
+       */
+       addSkinControlBindings: function() {
+               var embedObj = this.embedObj;
+               var _this = this;
+               var $tp = $j( '#' + embedObj.id );
+               
+               // Adds options and bindings: (we do this onClick )  
+               var addMvOptions = function() {
+                       if ( $j( '#' + embedObj.id + ' .k-menu' ).length != 0 )
+                               return false;
+                               
+                       $j( '#' + embedObj.id + ' .' + _this.pClass ).prepend(
+                               _this.components['mv_embedded_options'].o( $tp.get( 0 ).ctrlBuilder )
+                       );
+                       
+                       // By default its hidden:
+                       $tp.find( '.k-menu' ).hide();
+                       
+                       // Output menu-items: 
+                       for ( i = 0; i < _this.menu_items.length ; i++ ) {
+                       $tp.find( '.k-' +  _this.menu_items[i] + '-btn' ).click( function() {
+                               var mk = $j( this ).attr( 'rel' );
+                               $target = $j( '#' + embedObj.id  + ' .menu-' + mk ).hide();
+                               // Generate the menu html not already done:
+                               if ( $target.children().length == 0 ) {
+                                               // call the function show{Menuitem} with target:
+                                               _this.showMenuItem(     mk );                                                                   
+                               }
+                               // Slide out the others 
+                                $j( '#' + embedObj.id  + ' .menu-screen' ).hide();
+                                $target.fadeIn( "fast" );
+                                       // don't follow the # link                                                              
+                           return false;
+                               } );
+                       }
+               }
+                               
+               // Options menu display:                        
+               $tp.find( '.k-options' ).click( function() {
+                       if ( $j( '#' + embedObj.id + ' .k-menu' ).length == 0 ) {
+                               // Stop the player if it does not support overlays:
+                               if ( !embedObj.supports['overlay'] )
+                                       $tp.get( 0 ).stop();
+                               // Add the options                                      
+                               addMvOptions();
+                       }
+                       // Set up the text and menu:                                                                    
+                       var $ktxt = $j( this );
+                       var $kmenu = $tp.find( '.k-menu' );
+                       if ( $kmenu.is( ':visible' ) ) {
+                               $kmenu.fadeOut( "fast", function() {
+                                       $ktxt.find( 'span' ).html ( gM( 'mwe-menu_btn' ) );
+                               } );
+                               $tp.find( '.play-btn-large' ).fadeIn( 'fast' );
+                       } else {
+                               $kmenu.fadeIn( "fast", function() {
+                                       $ktxt.find( 'span' ).html ( gM( 'mwe-close_btn' ) );
+                               } );
+                               $tp.find( '.play-btn-large' ).fadeOut( 'fast' );
+                       }
+               } );
+       
+       }, 
+       showMenuItem:function( menu_item ) {
+               //handle special k-skin specific display; 
+               if( menu_item == 'credits'){
+                       this.showCredits(); 
+               }else{
+                       //call the base embedObj "show{Item}"
+                       this.embedObj['show' + menu_item.charAt( 0 ).toUpperCase() + menu_item.substring( 1 )](
+                               $j( '#' + this.embedObj.id + ' .menu-' + menu_item )
+                       );
+               }
+       },      
+       // Do the credit screen (presently specific to kaltura skin:)  
+       showCredits:function() {
+               //set up the shortcuts: 
+               embedObj = this.embedObj;
+               var _this = this;       
+               $target = $j( '#' + embedObj.id + ' .menu-credits' );
+
+               $target.html( '<h2>' + gM( 'mwe-credits' ) + '</h2>'  +
+                       '<div class="credits_box ui-corner-all">' +
+                               mv_get_loading_img() + 
+                       '</div>'                                                                
+               );
+
+               if( mw.conf.k_attribution == true ){
+                       $target.append( 
+                               $j('<div/>').addClass( 'k-attribution' )
+                               .attr({
+                                       'title': gM('mwe-kaltura-platform-title')
+                               })
+                               .click( function(){
+                                       window.location = 'http://kaltura.com';
+                               })
+                       );
+               }
+               
+               if( !embedObj.wikiTitleKey ){
+                       $target.find('.credits_box').text(
+                               'Error: no title key to grab credits with' 
+                       );
+                       return ;
+               }               
+               // Do the api request to populate the credits via the wikiTitleKey ( tied to "commons" )
+               var reqObj = {
+                       'action' : 'query',
+                       // Normalize the File NS (ie sometimes its present in wikiTitleKey other times not
+                       'titles' : 'File:' + embedObj.wikiTitleKey.replace(/File:|Image:/, '' ),
+                   'prop' : 'revisions',
+                   'rvprop' : 'content'
+               };
+               var req_categories = new Array();
+           do_api_req( {
+               'url'   : mw.commons_api_url,
+                       'data'  : reqObj                        
+           }, function( data ) {
+                       if( !data || !data.query || !data.query.pages ){
+                               $target.find('.credits_box').text(
+                                       'Error: title key: ' + embedObj.wikiTitleKey + ' not found' 
+                               );
+                               return false;
+                       }
+                       var pages = data.query.pages;                   
+                       for(var i in pages){
+                               page = pages[ i ];
+                               if( page[ 'revisions' ] && page[ 'revisions' ][0]['*'] ){
+                                       $target.find('.credits_box').html(
+                                               _this.doCreditLineFromWikiText( page[ 'revisions' ][0]['*'] )
+                                       );
+                               }
+                       }
+           } );
+       },
+       doCreditLineFromWikiText:function ( wikiText ){
+               var embedObj = this.embedObj;
+               
+               // Get the title str 
+               var titleStr = embedObj.wikiTitleKey.replace(/_/g, ' ');
+               var titleLink = 'http://commons.wikimedia.org/wiki/File:' + embedObj.wikiTitleKey;
+               
+               // @@FIXME Do a quick check for source line:
+               return $j( '<div/>' ).addClass( 'creditline' )
+                       .append(
+                               $j('<a/>').attr({
+                                       'href' : titleLink,
+                                       'title' :  titleStr
+                               }).html( 
+                                       $j('<img/>').attr( {
+                                               'border': 0, 
+                                               'src' : embedObj.thumbnail, 
+                                       } )
+                               )
+                       )
+                       .append(                        
+                               $j('<span>').html( 
+                                       gM( 'mwe-credit-title' ,  
+                                               // We use a div container to easialy get at the built out link
+                                               $j('<div>').html( 
+                                                       $j('<a/>').attr({
+                                                               'href' : titleLink,
+                                                               'title' :  titleStr
+                                                       }).text( titleStr )
+                                               ).html()
+                                       )
+                               )
+                       );
+       }
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/skins/kskin/playerSkin.css b/js2/mwEmbed/skins/kskin/playerSkin.css
new file mode 100644 (file)
index 0000000..3f6bb44
--- /dev/null
@@ -0,0 +1,426 @@
+/*
+* K-skin player
+*/ 
+.k-player {
+       color: white;
+}
+
+/* large play button */
+.k-player .play-btn-large {
+       width: 120px;
+       height: 55px;
+       background: url(images/ksprite.png) no-repeat 28px -433px;
+       position: absolute;
+       cursor: pointer;
+       border: none;
+}  /*.ui-state-default */
+.k-player .play-btn-large.ui-state-hover {
+       background: url(images/ksprite.png) no-repeat 28px -377px;
+}
+
+/* control icons: */
+.k-player .ui-state-default .ui-icon,.k-player .ui-state-hover .ui-icon
+       {
+       background: transparent url(images/ksprite.png) no-repeat scroll 0 -48px
+               ;
+}
+
+.k-player .ui-state-default .ui-icon-arrow-4-diag {
+       background-position: 0 -32px;
+}  /* fullscreen */
+.k-player .ui-state-hover .ui-icon-arrow-4-diag {
+       background-position: -16px -32px;
+}
+
+.k-player .ui-state-hover .ui-icon-volume-on{  
+       background-position: -16px -48px;
+}
+
+/* cc icon */
+.k-player .ui-state-default .ui-icon-comment {
+       background-position: 0px -65px;
+}
+.k-player .ui-state-hover .ui-icon-comment {
+       background-position: -17px -65px;
+}
+
+.k-player .ui-state-default .ui-icon-play {
+       background: url(images/ksprite.png) no-repeat 0 0;
+}
+
+.k-player .ui-state-hover .ui-icon-play {
+       background-position: -16px 0;
+}
+
+.k-player .ui-state-default .ui-icon-pause {
+       background: url(images/ksprite.png) no-repeat 0 -17px;
+}
+
+.k-player .ui-state-hover .ui-icon-pause {
+       background-position: -16px -17px;
+}
+
+.k-player .control-bar {
+       border: 0px;
+       height: 21px;
+       padding: 2px 0 0 6px;
+       margin-top: 0px;
+       background: url(images/ksprite.png) repeat-x 0 -81px;
+       font: normal 11px arial, sans-serif;
+       color: #555;
+}
+
+.k-player .play_head {
+       background: url("images/ksprite.png") repeat-x scroll 0 -350px
+               transparent;
+       display: inline;
+       float: left;
+       margin-left: 10px;
+       border: 1px solid #EEEEEE;
+       height: 8px;
+       margin: 6px 10px 0 7px;
+       position: relative;
+}
+
+.k-player .play_head .ui-slider-handle {
+       background: url("images/ksprite.png") no-repeat scroll -67px -341px
+               transparent;
+       border: 1px solid #888888;
+       display: block;
+       height: 8px;
+       margin: -1px 0 0 -5px;
+       position: absolute;
+       top: 0;
+       width: 8px;
+       cursor: pointer;
+}
+
+.k-player .time-disp {
+       border: medium none;
+       display: inline;
+       color: #555555;
+       font: 11px arial, sans-serif;
+       line-height: 20px;
+       overflow: hidden;
+       width: 39px;
+       float: right;
+}
+
+.k-player .lButton {
+       cursor: pointer;
+       float: left;
+       list-style: none outside none;
+       margin: 2px;
+       padding: 0px 0;
+       width: 24px;
+       height: 16px;
+       position: relative;
+       background: none repeat scroll 0 0 transparent;
+       border: medium none;
+}
+
+.k-player .rButton {
+       cursor: pointer;
+       float: right;
+       list-style: none outside none;
+       margin: 2px;
+       padding: 0px 0;
+       width: 23px;
+       height: 16px;
+       position: relative;
+       background: none repeat scroll 0 0 transparent;
+       border: medium none;
+}
+
+.k-player .k-options {
+       border: 1px solid #AAAAAA !important;
+       color: #555555;
+       float: right;
+       height: 22px;
+       margin-top: -2px;
+       margin-right: 0px;
+       width: 50px;
+       float: right;
+       background: none repeat scroll 0 0 transparent;
+       font-family: Lucida Grande, Lucida Sans, Arial, sans-serif;
+       font-size: 11px;
+       text-transform: uppercase;
+}
+
+.k-player .k-options span {
+       position: relative;
+       top: 4px;
+       left: 7px;
+}
+
+.k-player .k-menu-screens {
+       float: left;
+       font-size: 11px;
+       padding: 13px 10px 15px 15px;
+       width: 320px;
+}
+
+.k-player ul.k-menu-bar {
+       background: url("images/ksprite.png") no-repeat scroll -99px -104px
+               transparent;
+       bottom: 5px;
+       height: 128px;
+       list-style: none outside none;
+       padding: 0 0 5px;
+       position: absolute;
+       right: 0;
+}
+
+.k-player .k-menu {
+       background: none repeat scroll 0 0 #181818;
+       border: medium none;
+       display: none;
+       height: 300px;
+       left: 0;
+       opacity: 0.9;
+       position: absolute;
+       top: 0;
+       width: 400px;
+       z-index: 999;
+}
+
+.k-player .k-menu-bar li a {
+       background: url("images/ksprite.png") no-repeat scroll -51px -110px
+               transparent;
+       display: block;
+       height: 32px;
+       margin-left: 1px;
+       overflow: hidden;
+       text-indent: 99999px;
+       width: 49px;
+}
+
+.k-menu-bar li a:hover {
+       background-position: -1px -110px;
+}
+
+.k-menu-bar li.k-download-btn a {
+       background-position: -51px -203px;
+}
+
+.k-menu-bar li.k-download-btn a:hover {
+       background-position: -1px -203px;
+}
+
+.k-menu-bar li.k-share-btn a {
+       background-position: -51px -172px;
+}
+
+.k-menu-bar li.k-share-btn a:hover {
+       background-position: -1px -172px;
+}
+
+.k-menu-bar li.k-credits-btn a {
+       background-position: -51px -141px;
+}
+
+.k-menu-bar li.k-credits-btn a:hover {
+       background-position: -1px -141px;
+}
+
+.k-menu-screens {
+       width: 320px;
+       padding: 13px 10px 15px 15px;
+       float: left;
+}  /* w & h inline via jq */
+.k-menu-screens h2 {
+       padding: 0 0 5px 1px;
+       clear: both;
+       font-size: 12px;
+       color: #666;
+}
+
+.k-menu-screens p {
+       margin: 6px 0;
+}
+
+.k-menu-screens a {;
+       
+}
+
+.k-menu-screens a img {
+       border: none;
+}
+
+.k-menu-screens ul {
+       padding: 0;
+       margin: 6px 0 0;
+       list-style: none outside none;
+}
+
+.k-edit-screen {
+       width: 370px;
+       height: 223px;
+       padding-top: 77px;
+       text-align: center;
+       background: #181818;
+       color: #fff;
+}
+
+.k-edit-screen div {
+       
+}
+
+.k-edit-screen a {
+       color: #7BB8FC;
+}
+
+.k-edit-screen a img {
+       border: none;
+}
+
+.k-menu-screens {
+       width: 320px;
+       padding: 13px 10px 15px 15px;
+       float: left;
+}  /* w & h inline via jq */
+.k-menu-screens h2 {
+       padding: 0 0 5px 1px;
+       clear: both;
+       font-size: 12px;
+       color: #666;
+}
+
+.k-menu-screens p {
+       margin: 6px 0;
+}
+
+.k-menu-screens a {;
+       
+}
+
+.k-menu-screens a img {
+       border: none;
+}
+
+.k-menu-screens ul {
+       padding: 0;
+       margin: 6px 0 0;
+       list-style: none outside none;
+}
+
+.k-menu-screens li {
+       height: 14px;
+       margin-bottom: 6px;
+}
+
+.k-menu-screens li a {
+       padding-left: 22px;
+       background: url(images/ksprite.png) no-repeat -85px -274px;
+       text-decoration: none;
+}
+
+.k-menu-screens li a.active,.k-menu-screens li a:hover .active {
+       background-position: -85px -247px;
+}
+
+.k-menu-screens li a:hover {
+       background-position: -85px -260px;
+}
+
+.k-menu-screens a {
+       color: #BBBBBB;
+}
+
+.k-menu textarea {
+       background: none repeat scroll 0 0 transparent;
+       border-color: #000000 -moz-use-text-color -moz-use-text-color #000000;
+       border-style: solid none none solid;
+       border-width: 2px medium medium 2px;
+       color: #CCCCCC;
+       font: 11px arial, sans-serif;
+       height: 15px;
+       overflow: hidden;
+       padding-left: 2px;
+       width: 100%;
+}
+
+.menu-screen.menu-share button {
+       background: url("images/ksprite.png") no-repeat scroll 0 -81px #D4D4D4;
+       border: 1px solid #000000;
+       color: #000000;
+       float: right;
+       height: 34px;
+       padding: 0 5px 3px;
+       width: 84px;
+       font-size: 1em;
+}
+
+.k-player .menu-screen.menu-share div.ui-state-highlight {
+       background: none repeat scroll 0 0 transparent;
+       border-color: #554926;
+       color: #FFE96E;
+       float: left;
+       padding: 2px 5px;
+}
+
+.k-player .menu-screen.menu-share div.ui-state-highlight a {
+       color: #FFE96E;
+       font-weight: bold;
+}
+
+.k-player .volume_control {
+       margin-right: 0px;
+       width: 16px;
+}
+
+.k-player .volume_control span {
+       margin-right: 0px;
+}
+
+.k-player .volume-slider {
+       width: 30px;
+}
+
+.k-player .volume-slider .ui-slider-range {
+       -moz-border-radius: 0 0 0 0;
+       background: url("images/ksprite.png") repeat-x scroll -66px -306px
+               transparent;
+       height: 17px;
+       position: absolute;
+}
+
+.k-player .volume-slider a.ui-slider-handle {
+       background: none repeat scroll 0 0 transparent;
+       border: medium none;
+       display: block;
+       height: 18px;
+       margin: -3px 5px 0 -1px;
+       position: absolute;
+       width: 8px;
+}
+
+.k-player .credits_box { 
+       background-attachment:scroll;
+       background-color:white;
+       background-image:none;
+       background-position:0 0;
+       bottom:30px;
+       left:15px;
+       position:absolute;
+       right:61px;
+       top:48px;               
+}
+.k-player .credits_box a{
+       color:#666;
+}
+.k-player .creditline img {
+       float: left;
+       width: 90px;
+       margin: 4px;
+}
+
+.k-player .k-attribution{
+       position:absolute;
+       bottom: 15px;
+       right : 62px;
+       background: url("images/kaltura_open_source_video_platform.png");
+       width : 51px;
+       height : 12px;
+       cursor: pointer;
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/skins/mvpcf/images/Button_add_media.png b/js2/mwEmbed/skins/mvpcf/images/Button_add_media.png
new file mode 100644 (file)
index 0000000..c83582e
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/Button_add_media.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/Jcrop.gif b/js2/mwEmbed/skins/mvpcf/images/Jcrop.gif
new file mode 100644 (file)
index 0000000..72ea7cc
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/Jcrop.gif differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/archive_org_bw.png b/js2/mwEmbed/skins/mvpcf/images/archive_org_bw.png
new file mode 100644 (file)
index 0000000..ab36cb9
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/archive_org_bw.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/archive_org_color.png b/js2/mwEmbed/skins/mvpcf/images/archive_org_color.png
new file mode 100644 (file)
index 0000000..503bf74
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/archive_org_color.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/box_layout_icon.png b/js2/mwEmbed/skins/mvpcf/images/box_layout_icon.png
new file mode 100644 (file)
index 0000000..fff1936
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/box_layout_icon.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/box_layout_icon_dark.png b/js2/mwEmbed/skins/mvpcf/images/box_layout_icon_dark.png
new file mode 100644 (file)
index 0000000..c268e78
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/box_layout_icon_dark.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/button_grey_left.png b/js2/mwEmbed/skins/mvpcf/images/button_grey_left.png
new file mode 100644 (file)
index 0000000..4e0b17f
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/button_grey_left.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/button_grey_right.png b/js2/mwEmbed/skins/mvpcf/images/button_grey_right.png
new file mode 100644 (file)
index 0000000..d32a226
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/button_grey_right.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/button_play.png b/js2/mwEmbed/skins/mvpcf/images/button_play.png
new file mode 100644 (file)
index 0000000..bc327b9
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/button_play.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/button_subscribe.png b/js2/mwEmbed/skins/mvpcf/images/button_subscribe.png
new file mode 100644 (file)
index 0000000..525cf0b
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/button_subscribe.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/button_to_clipboard.png b/js2/mwEmbed/skins/mvpcf/images/button_to_clipboard.png
new file mode 100644 (file)
index 0000000..8b4792f
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/button_to_clipboard.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/carousel_left.png b/js2/mwEmbed/skins/mvpcf/images/carousel_left.png
new file mode 100644 (file)
index 0000000..12a860e
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/carousel_left.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/carousel_right.png b/js2/mwEmbed/skins/mvpcf/images/carousel_right.png
new file mode 100644 (file)
index 0000000..626c16a
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/carousel_right.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/carousel_top_left.png b/js2/mwEmbed/skins/mvpcf/images/carousel_top_left.png
new file mode 100644 (file)
index 0000000..f01c460
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/carousel_top_left.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/carousel_top_right.png b/js2/mwEmbed/skins/mvpcf/images/carousel_top_right.png
new file mode 100644 (file)
index 0000000..e999500
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/carousel_top_right.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/clip_thumb_overlay.png b/js2/mwEmbed/skins/mvpcf/images/clip_thumb_overlay.png
new file mode 100644 (file)
index 0000000..340f167
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/clip_thumb_overlay.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/embed_arrow.png b/js2/mwEmbed/skins/mvpcf/images/embed_arrow.png
new file mode 100644 (file)
index 0000000..ce7044e
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/embed_arrow.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/firefogg_logo.png b/js2/mwEmbed/skins/mvpcf/images/firefogg_logo.png
new file mode 100644 (file)
index 0000000..de50deb
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/firefogg_logo.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/fish_xiph_org_bw.png b/js2/mwEmbed/skins/mvpcf/images/fish_xiph_org_bw.png
new file mode 100644 (file)
index 0000000..08cb5ff
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/fish_xiph_org_bw.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/fish_xiph_org_color.png b/js2/mwEmbed/skins/mvpcf/images/fish_xiph_org_color.png
new file mode 100644 (file)
index 0000000..682f101
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/fish_xiph_org_color.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/flash_carousel.jpg b/js2/mwEmbed/skins/mvpcf/images/flash_carousel.jpg
new file mode 100644 (file)
index 0000000..bf673e4
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/flash_carousel.jpg differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/flash_icon_bw.png b/js2/mwEmbed/skins/mvpcf/images/flash_icon_bw.png
new file mode 100644 (file)
index 0000000..b53c903
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/flash_icon_bw.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/flash_icon_color.png b/js2/mwEmbed/skins/mvpcf/images/flash_icon_color.png
new file mode 100644 (file)
index 0000000..bf25877
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/flash_icon_color.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/flash_player.jpg b/js2/mwEmbed/skins/mvpcf/images/flash_player.jpg
new file mode 100644 (file)
index 0000000..3a05d11
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/flash_player.jpg differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/font_truetype.png b/js2/mwEmbed/skins/mvpcf/images/font_truetype.png
new file mode 100644 (file)
index 0000000..147c5ff
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/font_truetype.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/html_page_icon.png b/js2/mwEmbed/skins/mvpcf/images/html_page_icon.png
new file mode 100644 (file)
index 0000000..28d7141
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/html_page_icon.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/ico_mail.png b/js2/mwEmbed/skins/mvpcf/images/ico_mail.png
new file mode 100644 (file)
index 0000000..955ac43
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/ico_mail.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/ico_rss.png b/js2/mwEmbed/skins/mvpcf/images/ico_rss.png
new file mode 100644 (file)
index 0000000..9bafee2
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/ico_rss.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/image_layout_left.png b/js2/mwEmbed/skins/mvpcf/images/image_layout_left.png
new file mode 100644 (file)
index 0000000..8110531
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/image_layout_left.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/image_layout_right.png b/js2/mwEmbed/skins/mvpcf/images/image_layout_right.png
new file mode 100644 (file)
index 0000000..1ffa9dc
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/image_layout_right.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/image_thumb_overlay.png b/js2/mwEmbed/skins/mvpcf/images/image_thumb_overlay.png
new file mode 100644 (file)
index 0000000..6229f57
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/image_thumb_overlay.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/img1.jpg b/js2/mwEmbed/skins/mvpcf/images/img1.jpg
new file mode 100644 (file)
index 0000000..a3ec451
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/img1.jpg differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/img2.jpg b/js2/mwEmbed/skins/mvpcf/images/img2.jpg
new file mode 100644 (file)
index 0000000..86fd602
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/img2.jpg differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/kaltura_logo_sm.png b/js2/mwEmbed/skins/mvpcf/images/kaltura_logo_sm.png
new file mode 100644 (file)
index 0000000..f9f639a
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/kaltura_logo_sm.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/kaltura_open_source_video_platform.gif b/js2/mwEmbed/skins/mvpcf/images/kaltura_open_source_video_platform.gif
new file mode 100644 (file)
index 0000000..cf05af2
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/kaltura_open_source_video_platform.gif differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/kaltura_open_source_video_platform.png b/js2/mwEmbed/skins/mvpcf/images/kaltura_open_source_video_platform.png
new file mode 100644 (file)
index 0000000..9d438b5
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/kaltura_open_source_video_platform.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/ksprite.png b/js2/mwEmbed/skins/mvpcf/images/ksprite.png
new file mode 100644 (file)
index 0000000..ed5ec08
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/ksprite.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/list_layout_icon.png b/js2/mwEmbed/skins/mvpcf/images/list_layout_icon.png
new file mode 100644 (file)
index 0000000..42d28c1
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/list_layout_icon.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/list_layout_icon_dark.png b/js2/mwEmbed/skins/mvpcf/images/list_layout_icon_dark.png
new file mode 100644 (file)
index 0000000..471a97c
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/list_layout_icon_dark.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/loading_ani.gif b/js2/mwEmbed/skins/mvpcf/images/loading_ani.gif
new file mode 100644 (file)
index 0000000..3288d10
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/loading_ani.gif differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/loading_bar_ani.gif b/js2/mwEmbed/skins/mvpcf/images/loading_bar_ani.gif
new file mode 100644 (file)
index 0000000..47adbf0
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/loading_bar_ani.gif differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/logo.png b/js2/mwEmbed/skins/mvpcf/images/logo.png
new file mode 100644 (file)
index 0000000..76cf5ee
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/logo.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/logo2.png b/js2/mwEmbed/skins/mvpcf/images/logo2.png
new file mode 100644 (file)
index 0000000..a949d83
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/logo2.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/metavid_logo_100.png b/js2/mwEmbed/skins/mvpcf/images/metavid_logo_100.png
new file mode 100644 (file)
index 0000000..08d0cc4
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/metavid_logo_100.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/opened.png b/js2/mwEmbed/skins/mvpcf/images/opened.png
new file mode 100644 (file)
index 0000000..97ed9d1
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/opened.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/other_results_bg.png b/js2/mwEmbed/skins/mvpcf/images/other_results_bg.png
new file mode 100644 (file)
index 0000000..fba1bac
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/other_results_bg.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/other_results_top.png b/js2/mwEmbed/skins/mvpcf/images/other_results_top.png
new file mode 100644 (file)
index 0000000..20b4a22
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/other_results_top.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/other_results_top2.png b/js2/mwEmbed/skins/mvpcf/images/other_results_top2.png
new file mode 100644 (file)
index 0000000..bd34bb7
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/other_results_top2.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/pbar-ani.gif b/js2/mwEmbed/skins/mvpcf/images/pbar-ani.gif
new file mode 100644 (file)
index 0000000..0dfd45b
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/pbar-ani.gif differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/pelosi.jpg b/js2/mwEmbed/skins/mvpcf/images/pelosi.jpg
new file mode 100644 (file)
index 0000000..e345cbc
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/pelosi.jpg differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/person1.jpg b/js2/mwEmbed/skins/mvpcf/images/person1.jpg
new file mode 100644 (file)
index 0000000..1c25555
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/person1.jpg differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/player_big_play_button.png b/js2/mwEmbed/skins/mvpcf/images/player_big_play_button.png
new file mode 100644 (file)
index 0000000..cdbc279
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/player_big_play_button.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/player_bottom_left.png b/js2/mwEmbed/skins/mvpcf/images/player_bottom_left.png
new file mode 100644 (file)
index 0000000..2516405
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/player_bottom_left.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/player_bottom_right.png b/js2/mwEmbed/skins/mvpcf/images/player_bottom_right.png
new file mode 100644 (file)
index 0000000..9322c4a
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/player_bottom_right.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/player_button_cc.png b/js2/mwEmbed/skins/mvpcf/images/player_button_cc.png
new file mode 100644 (file)
index 0000000..6e788d1
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/player_button_cc.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/player_button_fullscreen.png b/js2/mwEmbed/skins/mvpcf/images/player_button_fullscreen.png
new file mode 100644 (file)
index 0000000..540e768
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/player_button_fullscreen.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/player_button_options.png b/js2/mwEmbed/skins/mvpcf/images/player_button_options.png
new file mode 100644 (file)
index 0000000..83cd7a2
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/player_button_options.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/player_button_pause.png b/js2/mwEmbed/skins/mvpcf/images/player_button_pause.png
new file mode 100644 (file)
index 0000000..6f16062
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/player_button_pause.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/player_button_play.png b/js2/mwEmbed/skins/mvpcf/images/player_button_play.png
new file mode 100644 (file)
index 0000000..645e0b7
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/player_button_play.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/player_options_bg.png b/js2/mwEmbed/skins/mvpcf/images/player_options_bg.png
new file mode 100644 (file)
index 0000000..e115c99
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/player_options_bg.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/player_options_bottom.png b/js2/mwEmbed/skins/mvpcf/images/player_options_bottom.png
new file mode 100644 (file)
index 0000000..f935baf
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/player_options_bottom.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/player_options_top.png b/js2/mwEmbed/skins/mvpcf/images/player_options_top.png
new file mode 100644 (file)
index 0000000..6c35193
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/player_options_top.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/player_seek_bg_loaded.png b/js2/mwEmbed/skins/mvpcf/images/player_seek_bg_loaded.png
new file mode 100644 (file)
index 0000000..87ac7d7
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/player_seek_bg_loaded.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/player_seek_bg_normal.png b/js2/mwEmbed/skins/mvpcf/images/player_seek_bg_normal.png
new file mode 100644 (file)
index 0000000..5458193
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/player_seek_bg_normal.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/player_seek_left.png b/js2/mwEmbed/skins/mvpcf/images/player_seek_left.png
new file mode 100644 (file)
index 0000000..b710b59
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/player_seek_left.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/player_seek_right.png b/js2/mwEmbed/skins/mvpcf/images/player_seek_right.png
new file mode 100644 (file)
index 0000000..1067cd8
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/player_seek_right.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/player_slider.png b/js2/mwEmbed/skins/mvpcf/images/player_slider.png
new file mode 100644 (file)
index 0000000..bef3f55
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/player_slider.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/player_video.jpg b/js2/mwEmbed/skins/mvpcf/images/player_video.jpg
new file mode 100644 (file)
index 0000000..9b3b7be
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/player_video.jpg differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/player_video_options_bg.png b/js2/mwEmbed/skins/mvpcf/images/player_video_options_bg.png
new file mode 100644 (file)
index 0000000..17ca498
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/player_video_options_bg.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/player_volume_seek.png b/js2/mwEmbed/skins/mvpcf/images/player_volume_seek.png
new file mode 100644 (file)
index 0000000..2611fd9
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/player_volume_seek.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/player_volume_tag.png b/js2/mwEmbed/skins/mvpcf/images/player_volume_tag.png
new file mode 100644 (file)
index 0000000..1198765
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/player_volume_tag.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/player_volume_tag_off.png b/js2/mwEmbed/skins/mvpcf/images/player_volume_tag_off.png
new file mode 100644 (file)
index 0000000..3b2d699
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/player_volume_tag_off.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/plugin.png b/js2/mwEmbed/skins/mvpcf/images/plugin.png
new file mode 100644 (file)
index 0000000..6187b15
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/plugin.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/plugin_disabled.png b/js2/mwEmbed/skins/mvpcf/images/plugin_disabled.png
new file mode 100644 (file)
index 0000000..f4f6be5
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/plugin_disabled.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/plugin_edit.png b/js2/mwEmbed/skins/mvpcf/images/plugin_edit.png
new file mode 100644 (file)
index 0000000..b6cb0ec
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/plugin_edit.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/search_suggest_bg.png b/js2/mwEmbed/skins/mvpcf/images/search_suggest_bg.png
new file mode 100644 (file)
index 0000000..e69748b
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/search_suggest_bg.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/search_suggest_bottom.png b/js2/mwEmbed/skins/mvpcf/images/search_suggest_bottom.png
new file mode 100644 (file)
index 0000000..7231cff
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/search_suggest_bottom.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/search_suggest_top.png b/js2/mwEmbed/skins/mvpcf/images/search_suggest_top.png
new file mode 100644 (file)
index 0000000..60ee2f0
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/search_suggest_top.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/selector.png b/js2/mwEmbed/skins/mvpcf/images/selector.png
new file mode 100644 (file)
index 0000000..8b2e0ad
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/selector.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/slider_handle.gif b/js2/mwEmbed/skins/mvpcf/images/slider_handle.gif
new file mode 100644 (file)
index 0000000..c91a332
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/slider_handle.gif differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/slider_handle_green.gif b/js2/mwEmbed/skins/mvpcf/images/slider_handle_green.gif
new file mode 100644 (file)
index 0000000..84e9449
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/slider_handle_green.gif differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/slider_handle_red.gif b/js2/mwEmbed/skins/mvpcf/images/slider_handle_red.gif
new file mode 100644 (file)
index 0000000..0d5777c
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/slider_handle_red.gif differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/sound_music_icon-60.png b/js2/mwEmbed/skins/mvpcf/images/sound_music_icon-60.png
new file mode 100644 (file)
index 0000000..eec6797
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/sound_music_icon-60.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/sound_music_icon-80.png b/js2/mwEmbed/skins/mvpcf/images/sound_music_icon-80.png
new file mode 100644 (file)
index 0000000..883fac6
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/sound_music_icon-80.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/sound_music_icon.png b/js2/mwEmbed/skins/mvpcf/images/sound_music_icon.png
new file mode 100644 (file)
index 0000000..7291987
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/sound_music_icon.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/stock-text-layer-24.png b/js2/mwEmbed/skins/mvpcf/images/stock-text-layer-24.png
new file mode 100644 (file)
index 0000000..6df91e6
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/stock-text-layer-24.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/stock-text-layer-24_over.png b/js2/mwEmbed/skins/mvpcf/images/stock-text-layer-24_over.png
new file mode 100644 (file)
index 0000000..25d165d
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/stock-text-layer-24_over.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/stock-tool-button-crop.png b/js2/mwEmbed/skins/mvpcf/images/stock-tool-button-crop.png
new file mode 100644 (file)
index 0000000..cf23381
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/stock-tool-button-crop.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/stock-tool-button-crop_over.png b/js2/mwEmbed/skins/mvpcf/images/stock-tool-button-crop_over.png
new file mode 100644 (file)
index 0000000..d749f0f
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/stock-tool-button-crop_over.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/stock-tool-button-scale.png b/js2/mwEmbed/skins/mvpcf/images/stock-tool-button-scale.png
new file mode 100644 (file)
index 0000000..773603f
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/stock-tool-button-scale.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/stock-tool-button-scale_over.png b/js2/mwEmbed/skins/mvpcf/images/stock-tool-button-scale_over.png
new file mode 100644 (file)
index 0000000..557874b
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/stock-tool-button-scale_over.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/stock_icon_over.xcf b/js2/mwEmbed/skins/mvpcf/images/stock_icon_over.xcf
new file mode 100644 (file)
index 0000000..27e958e
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/stock_icon_over.xcf differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/tab-bg.png b/js2/mwEmbed/skins/mvpcf/images/tab-bg.png
new file mode 100644 (file)
index 0000000..a0caaed
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/tab-bg.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/thumb1.jpg b/js2/mwEmbed/skins/mvpcf/images/thumb1.jpg
new file mode 100644 (file)
index 0000000..4341d10
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/thumb1.jpg differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/thumb2.jpg b/js2/mwEmbed/skins/mvpcf/images/thumb2.jpg
new file mode 100644 (file)
index 0000000..3004859
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/thumb2.jpg differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/thumb3.jpg b/js2/mwEmbed/skins/mvpcf/images/thumb3.jpg
new file mode 100644 (file)
index 0000000..1d6b137
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/thumb3.jpg differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/thumb4.jpg b/js2/mwEmbed/skins/mvpcf/images/thumb4.jpg
new file mode 100644 (file)
index 0000000..091a188
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/thumb4.jpg differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/tracker.png b/js2/mwEmbed/skins/mvpcf/images/tracker.png
new file mode 100644 (file)
index 0000000..2ba1f54
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/tracker.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/transition_icon.png b/js2/mwEmbed/skins/mvpcf/images/transition_icon.png
new file mode 100644 (file)
index 0000000..e6a8506
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/transition_icon.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/transparent_bg.png b/js2/mwEmbed/skins/mvpcf/images/transparent_bg.png
new file mode 100644 (file)
index 0000000..1bd5357
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/transparent_bg.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/ui-bg_diagonals-thick_20_666666_40x40.png b/js2/mwEmbed/skins/mvpcf/images/ui-bg_diagonals-thick_20_666666_40x40.png
new file mode 100644 (file)
index 0000000..64ece57
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/ui-bg_diagonals-thick_20_666666_40x40.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/ui-bg_flat_0_aaaaaa_40x100.png b/js2/mwEmbed/skins/mvpcf/images/ui-bg_flat_0_aaaaaa_40x100.png
new file mode 100644 (file)
index 0000000..5b5dab2
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/ui-bg_flat_0_aaaaaa_40x100.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/ui-bg_flat_75_ffffff_40x100.png b/js2/mwEmbed/skins/mvpcf/images/ui-bg_flat_75_ffffff_40x100.png
new file mode 100644 (file)
index 0000000..ac8b229
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/ui-bg_flat_75_ffffff_40x100.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/ui-bg_glass_55_fbf9ee_1x400.png b/js2/mwEmbed/skins/mvpcf/images/ui-bg_glass_55_fbf9ee_1x400.png
new file mode 100644 (file)
index 0000000..ad3d634
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/ui-bg_glass_55_fbf9ee_1x400.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/ui-bg_glass_65_ffffff_1x400.png b/js2/mwEmbed/skins/mvpcf/images/ui-bg_glass_65_ffffff_1x400.png
new file mode 100644 (file)
index 0000000..42ccba2
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/ui-bg_glass_65_ffffff_1x400.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/ui-bg_glass_75_dadada_1x400.png b/js2/mwEmbed/skins/mvpcf/images/ui-bg_glass_75_dadada_1x400.png
new file mode 100644 (file)
index 0000000..5a46b47
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/ui-bg_glass_75_dadada_1x400.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/ui-bg_glass_75_e6e6e6_1x400.png b/js2/mwEmbed/skins/mvpcf/images/ui-bg_glass_75_e6e6e6_1x400.png
new file mode 100644 (file)
index 0000000..86c2baa
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/ui-bg_glass_75_e6e6e6_1x400.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/ui-bg_glass_95_fef1ec_1x400.png b/js2/mwEmbed/skins/mvpcf/images/ui-bg_glass_95_fef1ec_1x400.png
new file mode 100644 (file)
index 0000000..4443fdc
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/ui-bg_glass_95_fef1ec_1x400.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/js2/mwEmbed/skins/mvpcf/images/ui-bg_highlight-soft_75_cccccc_1x100.png
new file mode 100644 (file)
index 0000000..7c9fa6c
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/ui-bg_highlight-soft_75_cccccc_1x100.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/ui-icons_222222_256x240.png b/js2/mwEmbed/skins/mvpcf/images/ui-icons_222222_256x240.png
new file mode 100644 (file)
index 0000000..ee039dc
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/ui-icons_222222_256x240.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/ui-icons_2e83ff_256x240.png b/js2/mwEmbed/skins/mvpcf/images/ui-icons_2e83ff_256x240.png
new file mode 100644 (file)
index 0000000..45e8928
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/ui-icons_2e83ff_256x240.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/ui-icons_454545_256x240.png b/js2/mwEmbed/skins/mvpcf/images/ui-icons_454545_256x240.png
new file mode 100644 (file)
index 0000000..7ec70d1
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/ui-icons_454545_256x240.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/ui-icons_888888_256x240.png b/js2/mwEmbed/skins/mvpcf/images/ui-icons_888888_256x240.png
new file mode 100644 (file)
index 0000000..5ba708c
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/ui-icons_888888_256x240.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/ui-icons_cd0a0a_256x240.png b/js2/mwEmbed/skins/mvpcf/images/ui-icons_cd0a0a_256x240.png
new file mode 100644 (file)
index 0000000..7930a55
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/ui-icons_cd0a0a_256x240.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/uni_edit_bw.png b/js2/mwEmbed/skins/mvpcf/images/uni_edit_bw.png
new file mode 100644 (file)
index 0000000..8ac8487
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/uni_edit_bw.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/uni_edit_color.png b/js2/mwEmbed/skins/mvpcf/images/uni_edit_color.png
new file mode 100644 (file)
index 0000000..875c980
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/uni_edit_color.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/vid_default_thumb.jpg b/js2/mwEmbed/skins/mvpcf/images/vid_default_thumb.jpg
new file mode 100644 (file)
index 0000000..fae4054
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/vid_default_thumb.jpg differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/vid_next_sm.png b/js2/mwEmbed/skins/mvpcf/images/vid_next_sm.png
new file mode 100644 (file)
index 0000000..2eb5f9b
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/vid_next_sm.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/vid_prev_sm.png b/js2/mwEmbed/skins/mvpcf/images/vid_prev_sm.png
new file mode 100644 (file)
index 0000000..6856148
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/vid_prev_sm.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/images/wiki_commons_logo_80.png b/js2/mwEmbed/skins/mvpcf/images/wiki_commons_logo_80.png
new file mode 100644 (file)
index 0000000..e55aca0
Binary files /dev/null and b/js2/mwEmbed/skins/mvpcf/images/wiki_commons_logo_80.png differ
diff --git a/js2/mwEmbed/skins/mvpcf/mv_sequence.css b/js2/mwEmbed/skins/mvpcf/mv_sequence.css
new file mode 100644 (file)
index 0000000..a170695
--- /dev/null
@@ -0,0 +1,206 @@
+/* the css file for sequence styles */
+.mv_head_jump{
+       font-family:"verdana","helvetica","arial",sans-serif;
+       font-size:11px;
+       background:#CCCCCC;
+       z-index:1;
+}
+.mv_playline{
+       position:absolute;
+       background:gray;
+       top:20px;
+       left:0px;
+       width:2px;
+       bottom:0px;
+       z-index:10;
+       overflow:visible; 
+}
+.mv_playline_top{
+       position:absolute;
+       top:-5px;
+       left:-7px;
+       width:16px;
+       height:16px;    
+       background:url("images/opened.png");
+}
+.mv_story_playline{
+       position:absolute;
+       background:blue;
+       top:0px;
+       left:0px;
+       width:2px;
+       height:100%;
+       bottom:0px;
+       z-index:10;
+       overflow:visible; 
+}
+.mv_seq_tracks{
+       position:absolute;left:90px;top:0px;right:12px;bottom:0px;overflow:auto;
+}
+.mv_tl_left_cnt{
+       position:absolute;
+       top:0px;
+       left:0px;
+       bottom:0px;
+       width:85px;
+}
+.track_name{
+       font-family:"verdana","helvetica","arial",sans-serif;
+       font-size:12px;
+       width:85px;
+       position:absolute;
+       background:#CCCCCC;
+}
+.container_track{
+       position:absolute;
+       border:solid thin gray;
+
+}
+/**************************/
+.clip_img{
+       }
+.clip_edit_button{     
+       width:16px;
+       height:16px;
+       position:absolute;
+       top:0px;
+       right:50px;
+       cursor:pointer;
+}
+.clip_trans_box{
+       border:solid thin black;
+       width:32px;
+       height:32px;
+       position:absolute;
+       top:27px;
+       right:15px;
+}
+
+.clip_edit_base{
+       background: url("images/uni_edit_bw.png");
+}
+.clip_edit_over{
+       background: url('images/uni_edit_color.png');
+}
+.mv_time_clip_text{
+       font-family:"verdana","helvetica","arial",sans-serif;
+       font-size:12px;
+}
+.mv_clip_cnt{
+       position:absolute;
+       width:16px;
+       height:16px;
+}
+
+.ui-drag-e{ cursor: e-resize;}
+.ui-drag-w{ cursor: w-resize;}
+
+.mv_clip_stats{
+       font-family:"verdana","helvetica","arial",sans-serif;
+       font-size:11px;
+       position:absolute;
+       background:#CCCCCC;
+       bottom:0px;
+       right:0px;
+}
+.mv_droppable{
+       position:absolute;
+       top:0px;
+       z-index:-1;
+}
+.mv_storyboard_container{
+       position:absolute;
+       z-index:0;
+       overflow:hidden;
+}
+.mv_clip_thumb{
+       position:absolute;
+       top:7px;        
+       border:solid #CCC;
+       display:block;
+       overflow:hidden;        
+}
+.mv_tl_clip{
+       position:absolute;
+       z-index:0;
+       overflow:hidden;
+       border:solid thin white;
+       white-space: nowrap;    
+}
+.mv_tl_thumb{
+       display:inline; 
+}
+.mv_selected_clip{
+       border:solid #9F9;      
+}
+.mv_selected_transition{
+       border:solid #9F9;
+}
+.mv_adj_text{
+       font-weight: strong;
+       font-size:small;
+       color:#6F6;
+       display:none; /* hide by default */
+       position:absolute;
+       left:20px;
+}
+.mv_adjust_click{
+       cursor:pointer;
+}
+/*
+#seq_menu{
+       list-style-type:none;
+       list-style-position:outside;
+       display:block;
+       padding-left:10px;
+}
+#seq_menu li{
+       display:inline;
+       padding:5px;
+       margin:0px;
+       border: solid thin gray;
+       cursor:pointer; 
+}
+#seq_menu li a{
+       color:#fff;
+}
+*/
+.seq_control_container{
+       position:absolute;
+       top:40px;       
+       overflow:auto; 
+       bottom:0px;
+       left:10px;
+       right:0px;
+}
+.submenu_container{
+/*     top:25px;
+       left:10px;
+       right:0px;
+       overflow:auto;
+       position:absolute;
+       broder: solid thin gray;
+*/
+}
+.mv_submenu{   
+       /*position:absolute;*/
+       /*left:0px;
+       top:0px;
+       margin:2px;
+       list-style-type:none; 
+       bottom:0px;     
+       border:none;
+       padding:0px;*/
+}
+.mv_submenu li{
+       border:solid thin gray;
+       cursor:pointer;
+       display:inline;
+       padding:5px;
+}
+.mv_submenu .mv_sub_selected{
+       border-bottom: none;
+}
+#seq_menu .mv_selected_item{
+       border-bottom:none;
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/skins/mvpcf/mvpcf.js b/js2/mwEmbed/skins/mvpcf/mvpcf.js
new file mode 100644 (file)
index 0000000..4bac486
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+mvpcf skin config
+*/
+
+var mvpcfConfig = {
+       pClass : 'mv-player'
+};
\ No newline at end of file
diff --git a/js2/mwEmbed/skins/mvpcf/playerSkin.css b/js2/mwEmbed/skins/mvpcf/playerSkin.css
new file mode 100644 (file)
index 0000000..dcba3cb
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * reference player skin 
+ */
+/* large play button: */
+.mv-player .play-btn-large { 
+       width:130px; 
+       height:96px; 
+       background: url(images/player_big_play_button.png) !important; 
+       position:absolute; 
+       cursor:pointer; 
+       border:none !important;
+       z-index:1; 
+}/*.ui-state-default */
+
+
+.mv-player
+{
+       color: #474747; 
+}
+
+.mv-player a:link {color: #2060c1; text-decoration: underline;}
+.mv-player a:visited {color: #2060c1; text-decoration: underline;}
+/*a:visited {color: #75a5e4; text-decoration: underline;}*/ /*Not sure if you want this*/
+.mv-player a:hover {color: #75a5e4; text-decoration: underline;}
+.mv-player img, .mv-player img a, .mv-player img a:hover {border: 0;}
+
+.mv-player h1, .mv-player h2, .mv-player h3, .mv-player h4, .mv-player h5, .mv-player h6 {color: #242424; margin: 5px 0; padding: 0;}
+.mv-player h1 {font-size: 24px;}
+.mv-player h2 {font-size: 18px;}
+.mv-player h3 {font-size: 16px;}
+.mv-player h4 {font-size: 14px;}
+.mv-player h5 {font-size: 13px; text-align: center;}
+.mv-player h6 {font-size: 13px; color: #6c6c6c; padding: 10px 20px 0px 20px; text-transform: uppercase;}
+
+
+/*Video player*/
+.mv-player {
+       color: white;
+}
+.mv-player .video {
+       display: block;
+       position: relative;
+       font-size: 1px;
+       height: 305px;
+}
+.mv-player .control-bar {
+       height: 29px;           
+}
+.mv-player .controlInnerSmall {
+/*     width: 430px;*/
+       height: 29px;
+       float: left;
+       display: inline;
+}
+
+.mv-player .lButton {
+       cursor:pointer;
+       float:left;
+       list-style:none outside none;
+       margin:2px;
+       padding:4px 0;
+       width: 24px;
+       height:16px;
+       position:relative;
+}
+.mv-player .rButton {
+       cursor:pointer;
+       float:right;
+       list-style:none outside none;
+       margin:2px;
+       padding:4px 0;
+       width: 23px;
+       height:16px;
+       position:relative;
+}
+
+.controls a{
+       display: block;
+       height: 100%;
+       width: 100%;
+}
+.mv-player .volume_icon {
+       float: right;
+       display: inline;
+       width: 22px;
+       height: 29px;
+       padding: 0 0 0 0;
+       
+}
+
+.mv-player .volume_on {        
+       background: url(images/player_volume_tag.png) 0 8px no-repeat;
+}
+.mv-player .volume_off{
+       background: url(images/player_volume_tag_off.png) 0 8px no-repeat;
+}
+
+.mv-player .volume_knob {
+       background: url(images/player_slider.png) 0 0 no-repeat;
+       width: 14px;
+       height: 14px;
+       position: absolute;
+       z-index: 2;
+       margin: -1px 0 0 3px;
+       cursor: pointer;
+}
+.mv-player .vol_container{
+       z-index:99;
+       width:23px;
+       height:75px;
+       width:23px;
+       background: #CCC;
+}
+.mv-player .vol_container_below{
+       top:30px;
+}
+.mv-player .vol_container_top{
+       top:-77px;
+}
+.mv-player .vol_container .volume-slider{
+       margin-top:5px; 
+       height:65px;
+       width:10px;
+       margin-left: auto ;
+       margin-right: auto ;    
+}
+.mv-player .vol_container .ui-slider-handle{
+       cursor : pointer;
+       width:10px;
+       height:10px;    
+       position:absolute;
+       left:-1px;              
+}
+
+.mv-player .time-disp {
+       line-height: 32px;
+       height: 29px;
+       overflow: visible;
+       font-size: 10.2px;
+       width: 85px;
+       float: right;
+       display: inline;
+       border:none;
+}
+
+.mv-player .play_head{
+       float: left;
+       display: inline;        
+       height: 10px;
+       margin-left:8px;
+       margin-top:10px;
+       position:relative;      
+}
+
+.mv-player .play_head .ui-slider-handle{
+       width:10px;
+       height:15px;
+       margin-left:-5px;
+       margin-top:1px;
+}
+
+.mv-player .inOutSlider .ui-slider-handle{
+       width:8px;      
+       cusror: move;
+}
+
+
+.mv-player .videoOptionsComplete textarea {
+       background:none repeat scroll 0 0 transparent;
+       border-color:#333 -moz-use-text-color -moz-use-text-color #333;
+       border-style:solid none none solid;
+       border-width:2px medium medium 2px;
+       color:#CCCCCC;
+       font:11px arial,sans-serif;
+       height:15px;
+       overflow:hidden;
+       padding-left:2px;
+       width:100%;
+}
+.mv-player .videoOptionsComplete .copycode {
+       background:url("images/ksprite.png") no-repeat scroll 0 -81px #D4D4D4;
+       border:1px solid #000000;
+       color:#000000;
+       float:right;
+       height:24px;
+       padding:0 5px 3px;
+       width:84px;
+       font-size:1em;
+}
+.mv-player .videoOptionsComplete div.ui-state-highlight {
+       background:none repeat scroll 0 0 transparent;
+       border-color:#554926;
+       color:#FFE96E;
+       float:left;
+       padding:2px 5px;
+}
+.mv-player .videoOptionsComplete div.ui-state-highlight a {
+       color:#FFE96E;
+       font-weight:bold;
+}
+
+.videoComplete{
+       position: absolute;
+       top:0px;
+       left:0px;
+       z-index: 10;
+       font-size:16px;
+       overflow: hidden;
+       background:transparent url(images/transparent_bg.png) repeat scroll 0 0;
+}
+.videoComplete .videoOptionsComplete {
+       background:transparent url('images/player_video_options_bg.png') no-repeat scroll 0pt;
+       color:#7A7A7A;
+       font-size:10pt;
+       height:158px;
+       left:10%;
+       overflow:auto;
+       padding:19px;
+       position:relative;
+       top:16%;
+       width:283px;
+}
+.videoComplete .videoOptionsComplete p { text-align: center; margin: 3px 0; padding: 0; }
+.videoComplete .videoOptionsComplete a {
+       color: white;
+/*     font-size: 22px;*/
+       font-size:12px;
+       text-decoration: underline;
+}
+.videoComplete .videoOptionsComplete a.active{
+       color: #bbf;
+}
+.videoComplete .videoOptionsComplete a.email {
+       font-size:16px;
+       background: url(images/ico_mail.png) right 0px no-repeat; 
+       padding: 0 50px 0 0;
+}
+
+.videoComplete div.embed_code textarea {
+       margin: 8px 0 8px 0;
+       padding: 3px;
+       width: 258px;
+       height: 54px;
+       border: 1px solid #dadada;
+       font-family: Arial;
+       color: #777;
+       font-size: 11px;
+}
+.videoComplete div.embed_code button.copy_to_clipboard {
+       background: #dddddd url(images/button_to_clipboard.png) 0 0 repeat-x;
+       border: 1px solid #3b4552;
+       text-align: center;
+       padding: 2px 4px;
+       margin: 0 0 6px 0;
+       float: right;
+       display: inline;
+}
+
+
+
diff --git a/js2/mwEmbed/skins/mvpcf/styles.css b/js2/mwEmbed/skins/mvpcf/styles.css
new file mode 100644 (file)
index 0000000..499fd71
--- /dev/null
@@ -0,0 +1,549 @@
+#mv_overlay {
+       background:transparent url(images/transparent_bg.png) repeat scroll 0 0;
+       cursor:wait;
+       height:100%;
+       left:0;
+       position:fixed;
+       top:0;
+       width:100%;
+       z-index:99;
+}
+
+.modal_editor {
+       /*background:#AAA none repeat scroll 0 0;
+       border:3px solid #666666;*/
+       left:10px;
+       top:10px;
+       right:10px;
+       bottom:10px;
+       position:fixed;         
+       z-index:100;
+}
+.mv_track {
+       margin-bottom:20px;
+       position:relative;
+} 
+.player_select_list {
+       color:white;
+       font-size:10pt;
+/*     display:none;*/
+}
+
+.player_select_list a:visited {
+       color:white;
+}
+.displayHTML a:visited {
+       color:white;
+}
+.mv_playhead {
+       position:absolute;
+       top:0;
+       left:0;
+       width:17px;
+       height:21px;
+       /*http://art.gnome.org/themes/gtk2*/
+}
+.mv_status {
+       font-family:"Times New Roman", Times, serif;
+       font-size:14px;
+       float:left;
+}
+.set_ogg_player_pref{
+       text-align:left;
+}
+
+.inputTrackerInput {
+               height:20;
+               width:30;
+               font-family : Arial, Helvetica, sans-serif;
+       font-size : 12px;
+}
+.mv_loading_icon {
+       position:absolute;
+       top:0px;
+       right:0px;
+       width:16px;
+       height:16px;
+}
+div.floatleft, table.floatleft {
+       border:0pt none;
+       clear:left;
+       float:left;
+       margin:0pt 0.5em 0.5em 0pt;
+       position:relative;
+}
+
+
+
+
+
+
+/*
+.videoPlayer .seeker {
+       float: right;
+       display: inline;
+       width: 55%;
+       margin: 0 5px 0 5px;
+       height: 29px;
+}
+
+.videoPlayer .seeker .seeker_bar {
+       float: left;
+       display: inline;
+       width : 100%;
+       height: 12px;
+       background: url(images/player_seek_bg_loaded.png) 0 1px repeat-x;
+       margin: 9px 0px 0 0px;
+       position:relative;
+}
+
+.videoPlayer .seeker .seeker_bar_outer {
+       width: 100%;
+       height: 12px;
+       position: relative;
+       z-index: 4;
+       background: url(images/player_seek_left.png) 0 0 no-repeat;
+}
+.videoPlayer .seeker .seeker_bar_close {
+       width: 5px;
+       height: 12px;
+       position: relative;
+       z-index: 4;
+       float: right;
+       display: inline;
+       margin: -12px 0 0 0;
+       background: url(images/player_seek_right.png) 0 0 no-repeat;
+}
+
+.videoPlayer .seeker .mv_progress{
+       width: 0%;
+       height: 12px;
+       left:0px;
+       top:0px;
+       position: absolute;
+}
+.videoPlayer .seeker .mv_playback {
+       z-index: 3;
+       background: #CCC;
+}
+.videoPlayer .seeker .mv_buffer {
+       z-index: 2;
+       background: #99C;
+}
+.videoPlayer .seeker .mv_highlight {
+       z-index: 3;
+       background: #558;
+}
+.videoPlayer .seeker .seeker_slider {
+       background: url(images/player_slider.png) 0 0 no-repeat;
+       width: 14px;
+       height: 14px;
+       position: relative;
+       z-index: 6;
+       margin: -13px 0 0 0px;
+       float: left;
+       cursor: pointer;
+}
+*/
+.tt_highlight{
+       border: solid thin blue;
+       background: #CCC;
+}
+.tt_scroll_highlight{
+       border: solid thin red;
+       background: #CCF;
+}
+.mvttseek{
+       cursor:pointer;
+}
+.mvtt{
+       border:solid thin black; 
+}
+.large_play_button {   
+       display:block;
+       width: 130px;
+       height: 96px;
+       margin: auto;
+/*     margin: -202px 0 0 154px;*/
+       position: absolute;
+       z-index: 3;
+       cursor: pointer;
+}
+
+/*Video options*/
+.videoOptions {
+       display: none;
+       width: 183px;
+       overflow: hidden;
+       position: absolute;
+       z-index: 9999;
+/*     margin: 0 0 0 230px;*/
+}
+*:first-child+html .videoOptions {margin-top: -20px;}
+.videoOptionsTop {
+       width: 183px;
+       height: 32px;
+       position: relative;
+       z-index: 3;
+       background: url(images/player_options_top.png) 0 0 no-repeat;
+}
+.videoOptionsBox {
+       width: 170px;
+       padding: 0px 11px 0 4px;
+       position: relative;
+       overflow: hidden;
+       color:#6C6C6C;
+       z-index: 3;
+       background: url(images/player_options_bg.png) 0 0 repeat-y;
+}
+.videoOptionsBot {
+       width: 183px;
+       height: 18px;
+       position: relative;
+       z-index: 3;
+       background: url(images/player_options_bottom.png) 0 0 no-repeat;
+}
+
+.videoOptionsBox div.block {
+       border-top: 1px solid #dadada;
+}
+.videoOptionsBox div.block h6 {
+       padding: 0;
+       margin: 5px 0;
+       text-align: center;
+}
+.videoOptionsBox div.wide_block {
+       padding: 15px 0;
+}
+.videoOptionsBox div.first_block {
+       border: 0;
+}
+.videoOptionsBox div.block p {padding: 10px 20px;margin: 0;}
+.videoOptionsBox div.block p.short_match, .videoOptionsBox div.block p.normal_match {padding: 0; margin: 0;}
+.videoOptionsBox div.block p a {text-decoration: none;}
+.videoOptionsBox div.block p.short_match a {
+       padding: 0;
+       display: block;
+       width: 100%;
+       border-bottom: 1px solid #dadada;
+}
+.videoOptionsBox div.block p.short_match a span {display: block; padding: 5px 20px;}
+.videoOptionsBox div.block p.short_match a:hover {background: #0b68c9 url(images/selector.png) 0 0 repeat-x; color: white;}
+.videoOptionsBox div.block p.short_match a.last_match {border: 0;}
+
+.videoOptionsBox div.block p.normal_match a {
+       padding: 0;
+       margin: 0;
+       display: block;
+       width: 100%;
+       border: 0;
+}
+.videoOptionsBox div.block p.normal_match a span {display: block; padding: 3px 20px;}
+.videoOptionsBox div.block p.normal_match a:hover {background: #0b68c9 url(images/selector.png) 0 0 repeat-x; color: white;}
+.videoOptionsBox div.block p.normal_match a.last_match {border: 0;}
+
+.videoOptionsBox div.block p.bill_match {border-bottom: 1px solid #dadada;}
+
+.videoOptionsBox div.block p.last_match {border-bottom: 0;}
+
+.videoOptionsBox div.block ul {
+       list-style: none;
+       margin: 10px 0;
+       padding: 0 20px;
+}
+.videoOptionsBox div.block ul a { text-decoration: none;}
+.videoOptionsBox div.block ul li { margin: 7px 0;}
+.videoOptionsBox div.block ul li ul {margin: 0;}
+.videoOptionsBox div.block ul li ul li a {color: #df5c01;}
+.videoOptionsBox div.block ul li ul li a:hover {color: #ffa02f;}
+
+.videoOptionsBox div.block ul li span.clips {display: block; text-align: right; margin: 6px 0 18px 0;}
+
+.videoOptionsBox div.advanced a.advanced_options {color: #aaa; text-align: center; display: block; margin: 3px 0; text-decoration: none;}
+
+.videoOptionsBox div.embed_code {text-align: center; border-bottom: 1px solid #dadada; }
+.videoOptionsBox div.embed_code textarea {
+       margin: 10px 0 10px 0;
+       padding: 3px;
+       width: 142px;
+       height: 54px;
+       border: 1px solid #dadada;
+       font-family: Arial;
+       color: #777;
+       font-size: 11px;
+}
+.videoOptionsBox div.embed_code button.copy_to_clipboard {
+       background: #dddddd url(images/button_to_clipboard.png) 0 0 repeat-x;
+       border: 1px solid #a1badf;
+       text-align: center;
+       padding: 2px 4px;
+       margin: 0 0 6px 0;
+}
+
+
+
+.cl_status{
+       position:absolute; 
+       bottom:0px;
+       top:0px;
+       z-index:3;
+}
+
+.rsd_control_container{        
+       margin:10px;
+}
+
+.rsd_cp_tab img{
+       border:0px;     
+}
+.rsd_cp_tab a{
+       height:16px;
+}
+.rsd_results_container{
+       left:2px;
+       right:2px;
+       top:2px;
+       bottom:2px;             
+}
+#rsd_resource_edit{
+       z-index:2;
+}
+.rsd_file_type{
+       position : absolute;
+       bottom : 0px;
+       left : 3px;
+       font-size: x-small;     
+}
+.rsd_linkback{
+       position: absolute;
+       top: 0px;
+       right: 0px;
+       font-size: x-small;     
+}
+.rsd_license{
+       position : absolute;
+       bottom : 0px;
+       right : 0px;
+}
+.rsd_license img{
+       float:left;
+}
+.rsd_license span{
+       float:left;
+       background:#FFF;
+       color:#200;
+       font-size:x-small;
+       filter:alpha(opacity=70);
+       -moz-opacity:0.7;
+       opacity:0.7;
+}
+.mv_clip_box_result{
+       padding:10px;
+       float:left;
+       border: thin solid #BBB;
+       overflow:hidden;
+}
+.mv_clip_box_result_over{
+       border: thin solid #F99;        
+}
+.mv_clip_list_result{
+       padding:10px;
+       border: thin solid #BBB;
+       clear:both;
+       position:relative;
+}
+.mv_clip_list_result_over{
+       padding:10px;
+       border: thin solid #F99;
+       clear:both;
+}
+.rsd_res_item{
+       cursor:pointer;
+       display:block;
+}
+#rds_results_bar{
+       margin:4px;
+       background:#DEF;
+       height:22px;
+}
+
+/* edit buttons: */
+.mv_edit_button{       
+       width:22px;
+       height:22px;
+       float:left;
+}
+#mv_layout_left_img{
+       width:50px;
+       height:33px;
+       background-image: url('images/image_layout_left.png');
+       float:left;
+}
+#mv_layout_right_img{
+       width:50px;
+       height:33px;
+       background-image: url('images/image_layout_right.png');
+       float:left;
+}
+
+.mv_crop_button_base{
+       background-image: url('images/stock-tool-button-crop.png');
+}
+.mv_crop_button_selected{
+       background-image: url('images/stock-tool-button-crop_over.png');        
+}
+.mv_scale_button_base{
+       background-image: url('images/stock-tool-button-scale.png');
+}
+.mv_scale_button_selected{
+       background-image: url('images/stock-tool-button-scale_over.png');
+}
+.mv_loading_img{
+       width:32px;
+       height:32px;
+       display:inline;
+       padding:0px;
+       position:absolute;
+       background-image: url('images/loading_ani.gif');
+}
+.mv_loading_bar_img{
+       width:220px;
+       height:19px;
+       display:inline;
+       position:absolute;
+       background-image: url('images/loading_bar_ani.gif');
+}
+
+/* jquery.ui overides */
+
+.ui-icon_link {
+       padding: .4em 1em .4em 20px;
+       text-decoration: none;
+       position: relative;     
+}
+.ui-icon_link span.ui-icon {
+       margin: 0 5px 0 0;
+       position: absolute;
+       left: 0.2em;
+       right: auto;
+       top: 50%;
+       margin-top: -8px;
+       zoom: 1;
+}
+.ui-icon_link span.ui-text {   
+       position: absolute;
+       left: 0.2em;
+       right: auto;    
+       margin-top: -3px;
+       zoom: 1;
+}
+
+.ui-progressbar-value{
+       background-image: url('images/pbar-ani.gif');
+}
+
+ui-widget-overlay{
+       background: url("images/ui-bg_diagonals-thick_20_666666_40x40.png") repeat scroll 50% 50% #666666;
+       opacity:0.5;
+}
+
+/* Vertical Tabs
+----------------------------------*/
+.ui-dialog-buttonpane { padding:10px !important; }
+.ui-tabs-vertical { width: 100%; }
+.ui-tabs-vertical .ui-tabs-nav { padding: .2em .1em .2em .2em; float: left; width: 25%; }
+.ui-tabs-vertical .ui-tabs-nav li { clear: left; width: 100%; border-bottom-width: 1px !important; border-right-width: 0 !important; margin: 0 -1px .2em 0; }
+.ui-tabs-vertical .ui-tabs-nav li a { display:block; }
+.ui-tabs-vertical .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 0; padding-right: .1em; border-right-width: 1px; border-right-width: 1px; }
+.ui-tabs-vertical .ui-tabs-panel { padding: 1em; float: right; width: 68%;}
+
+.ui-dialog .ui-dialog-buttonpane button { float: left !important; }
+
+.ui-widget-content a { text-decoration: underline; }
+
+
+.vol_container{
+       z-index:99;
+       width:23px;
+       height:75px;
+       width:23px;
+       background: #CCC;
+}
+.vol_container_below{
+       top:30px;
+}
+.vol_container_top{
+       top:-77px;
+}
+.vol_container .volume_bar{
+       margin-top:5px; 
+       height:65px;
+       width:10px;
+       margin-left: auto ;
+       margin-right: auto ;    
+}
+.vol_container .ui-slider-handle{
+       cursor : pointer;
+       width:10px;
+       height:10px;    
+       position:absolute;
+       left:-1px;              
+}
+
+/* related videos Video */
+.related_vids {                        
+       top:10px;
+       left:5px;
+       right:5px;
+       bottom:5px;
+       position:absolute;
+       overflow-y:auto;        
+}
+.related_vids h1 {
+       border:medium none;
+       font-size:20px;
+       margin:4px 0px 4px 11px;
+       padding:0;
+       color:#FFF;
+       font-family:arial,sans-serif;
+}
+
+.related_vids ul {
+       margin:0;
+       padding:0;
+       
+       list-style-image:none;
+       list-style-position:inside;
+       list-style-type:none;
+       margin:0;
+       padding:0;
+}
+
+
+.related_vids li{
+       -x-system-font:none;
+       color:#FAFAFA;
+       display:table;
+       font-family:arial,sans-serif;
+       font-size:11px;
+       line-height:normal;
+       margin:0 0 6px 35px;
+       padding:0;
+}
+
+.related_vids li div {
+       float:right;
+       margin:5px 0 0 10px;
+       width:200px;
+}
+
+.related_vids img {
+       width:80px;     
+       z-index:2;
+       border-bottom:3px solid #36393D;
+       border-top:3px solid #36393D;
+}
+
+.mw-imported-resource{
+       border: thin solid black;
+}
\ No newline at end of file
diff --git a/js2/mwEmbed/tests/README b/js2/mwEmbed/tests/README
new file mode 100644 (file)
index 0000000..7481623
--- /dev/null
@@ -0,0 +1,2 @@
+This folder contains stand alone tests of js2/mwEmbed components. 
+The tests folder does not need to be included or exposed in a production environment. 
\ No newline at end of file
diff --git a/js2/mwEmbed/tests/testApiProxy.html b/js2/mwEmbed/tests/testApiProxy.html
new file mode 100644 (file)
index 0000000..2e146c1
--- /dev/null
@@ -0,0 +1,104 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Api Proxy Test</title>
+<script type="text/javascript" src="../mv_embed.js"></script>
+
+<script type="text/javascript" >
+//HARD coded local test: 
+var remote_wiki_host = 'http://test.wikipedia.org';
+var remote_script_path = '/w';
+
+js2AddOnloadHook( function(){
+       $j('#hostName').text( remote_wiki_host );
+       //run the api-proxy setup:
+       $j.apiProxy(
+               'client', 
+               {
+                       'server_frame': remote_wiki_host +  remote_script_path + '/index.php/MediaWiki:ApiProxy',
+                       'client_frame_path'     : '/wiki_trunk/js2/mwEmbed/libMwApi/NestedCallbackIframe.html',
+               },
+               function(){
+                       //callback function here: 
+                       $j('#setupDone').show('slow');
+                       $j('#doHello').click( doHello );        
+                       $j('#doAppend').click(doAppend);        
+               }
+       );                              
+});
+function doHello(){
+       js_log('to a hello user');
+       $j('#helloTarget').html( mv_get_loading_img() );
+       //first get the user name:
+       getUserName(function( user_name ){      
+               $j('#helloTarget').hide().text( user_name  ).fadeIn('slow');
+       });
+       return false;
+}
+function getUserName( callback ){
+       var rObj = {
+               'action':'query',
+               'meta':'userinfo'
+       }
+       //we use normal do_api_req with keywork 'proxy' for the url 
+       $mw.proxy.doRequest( rObj,
+               function( data ){               
+                       //now we get the data back for that domain
+                       if( !data.query || !data.query.userinfo ){
+                               js_log("Error no query.userinfo ");
+                               return false;
+                       }
+                       callback( data.query.userinfo.name );                                                                   
+               }
+       );
+} 
+
+//simple "hello from api proxy" append on talk page
+function doAppend(){
+       $j('#appendTarget').html( mv_get_loading_img() );
+       //get user name
+       getUserName(function(userName){
+               var eTitle = 'User_talk:' + userName;
+               //get a edit token
+               get_mw_token(eTitle, 'proxy', function( token ){
+                       js_log("got token: " + token) ;
+                       var aReq = {
+                               'action':'edit',
+                               'title': eTitle,
+                               'summary': "Api proxy test edit",
+                               'appendtext': "\n\n==== Hello from Api proxy At: " + Date() + " ====",
+                               'token': token
+                       }
+                       do_api_req({
+                               'data': aReq,
+                               'url': 'proxy'
+                       },function(result){
+                               if(result.edit && result.edit.newrevid){                                
+                                       $j('#appendTarget').html( "success: " + JSON.stringify ( result) );
+                                       url = remote_wiki_host +  remote_script_path + '/index.php/';
+                                       url+= result.edit.title.replace(' ', '_');
+                                       $j('#appendTarget').append( '<br><a target="_new" href="' + url + '">visit page</a>' );
+                               }else{
+                                       $j('#appendTarget').html( "falied: " + JSON.stringify ( result) );
+                               }
+                       });
+                       
+               });
+       });
+}
+</script>
+</head>
+<body>
+<h3> Simple API proxy testing system </h3>
+
+<div id="setupProxy">Proxy for:  <span id="hostName"></span> <br><span style="font-size:small">( be sure to enable the mwEmbed gadget or add importScriptURI( 'path_to_local_mw_install' + /js2/remoteMwEmbed.js ) to your User skin .js page </span></div>
+<div id="setupDone" style="display:none;">
+       <br> <a href="#" id="doHello" >Hello User:</a> <span id="helloTarget"></span>
+       <br><br><br> <a href="#" id="doAppend">Append Msg to Talk page:</a>
+       <div id="appendTarget"></div>
+</div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/js2/mwEmbed/tests/testLang.html b/js2/mwEmbed/tests/testLang.html
new file mode 100644 (file)
index 0000000..95d8edd
--- /dev/null
@@ -0,0 +1,305 @@
+<html>
+<head>
+<title>Test Plural Conversions (should match php) </title>
+<script type="text/javascript" src="../mv_embed.js"></script>
+<style>
+td{
+       border:solid thin black;
+}
+</style>
+<script type="text/javascript" >
+var scriptLoaderURID = 't15';
+//for just setting one or two to test at a time for debug
+//var langKeyDebug = ['sl']; //pl
+var langKeyDebug = [ 'az', 'da', 'pt', 'fr', 'lv', 'en'];
+//var langKeyDebug = ['en','az', 'da', 'pt', 'fr', 'lv', 'ga','hr','cy','mk','mt','pl','sl'];
+
+//longlangKey is every language we have a much more verbose test
+var langKeyAll = [
+               //no plurals, there are no rules
+               'az','fa','hu','ja','ko','my to','tr','vi','yo','zh',
+               'bo','dz','id','jv ka','km','kn','ms','th',
+               
+               /*
+               'zero'  => 0,
+               'one'   => 1,
+               'two'   => 2,
+               //n mod 100 in 3..10    
+               'few'   => array( 'mod' => 100, 'is'=>'3-10' ),
+               //n mod 100 in 11..99
+               'many'  => array( 'mod' => 100, 'is'=>'11-99')
+               */
+               'ar',
+               
+               /*
+               'one' => 1
+               */              
+               'da','de','el','en','eo','es','et','fi','fo','gl',
+               'he','iw','it','nb','nl','nn','no','pt_PT','sv',
+               'af','bg','bn','ca','eu','fur','fy','gu','ha',
+               'is','ku','lb','ml','mr','nah','ne','om','or',
+               'pa','pap','ps','so','sq','sw','ta','te','tk',
+               'ur','zu','mn','gsw',
+               
+               /*
+               'one'=> '0-1'
+               */
+               'pt','am','bh','fil','tl','guw','hi','ln','mg','nso','ti','wa',
+               
+               /*
+               'one' => array( 'is'=>'0-2', 'not' => 2)
+               */
+               'fr',
+                
+               /*
+               'zero' => 0,
+               //n mod 10 is 1 and n mod 100 is not 11
+               'one'=>array(
+                               array( 'mod' => 10, 'is' => 1 ),
+                               //AND
+                               array( 'mod' => 100, 'not' => 11)
+                       )
+               */
+               'lv',
+               
+               /*
+               'one' => 1,
+               'two' => 2
+               */
+               'ga','se','sma','smi','smj','smn','sms',
+               
+               
+               /*
+               'one' => 1,
+               //n is 0 OR n is not 1 AND n mod 100 in 1..19
+               'few' => array(
+                                       'or'=> array(
+                                               array( 'is' => 0),                                                              
+                                               array(
+                                                       array( 'not' => 1),
+                                                       //and
+                                                       array( 'mod' => 100, 'is'=>'1-19')
+                                               )
+                                       )
+                               )
+                       */
+               'ro','mo',
+               
+               
+               /*
+               //n mod 10 is 1 and n mod 100 not in 11..19
+               'one' => array(
+                                       array( 'mod'=>10, 'is'=> 1 ),
+                                       array( 'mod'=> 100, 'not'=> '11-19')
+                               ),
+               //n mod 10 in 2..9 and n mod 100 not in 11..19
+               'few' => array(
+                                       array( 'mod'=> 10, 'is'=> '2-9' ),
+                                       array( 'mod'=> 100, 'not' => '11-19')
+                               ),
+               */
+               'lt',
+               
+               
+               /*
+               //n mod 10 is 1 and n mod 100 is not 11
+               'one' => array(
+                       array( 'mod' => 10, 'is' => 1),
+                       array( 'mod' => 100, 'not' => 11)
+               ),
+               //n mod 10 in 2..4 and n mod 100 not in 12..14
+               'few' => array(
+                       array( 'mod' => 10, 'is' => '2-4'),
+                       array( 'mod' => 100, 'not' => '12-14')
+               ),
+               //n mod 10 is 0 or n mod 10 in 5..9 or n mod 100 in 11..14
+               'many' => array(
+                       'or'=>array(
+                               array( 'mod'=> 10, 'is' => 0),
+                               array( 'mod'=> 10, 'is' => '5-9'),
+                               array( 'mod'=> 100, 'is' => '11-14')
+                       )
+               ),
+               */
+               'hr','ru','sr','uk','be','bs','sh',
+               
+               
+               /*
+               'one' => 1,
+               'few' => array(
+                       //n mod 10 in 2..4
+                       array( 'mod' => 10, 'is' => '2-4'),
+                       //and n mod 100 not in 12..14
+                       array( 'mod' => 100, 'not'=> '12-14'),
+                       //and n mod 100 not in 22..24
+                       array( 'mod' => 100, 'in' => '22-24')
+               )
+               */
+               'pl', 
+               
+               /*
+               'one' => array( 'mod'=>100, 'is' => 1 ),
+               'two' => array( 'mod'=>100, 'is' => 2 ),
+               'few' => array( 'mod'=>100, 'is' => '3-4')
+               */
+               'sl', 
+
+       
+               /*
+               'one' => 1,
+               //n is 0 or n mod 100 in 2..10
+               'few' => array(
+                       array( 'is' => 0 ),
+                       'or',
+                       array( 'mod' => 100, 'is' => '2-10')
+               ),
+               //n mod 100 in 11..19
+               'many' => array( 'mod'=>100, 'is' => '11-19')
+               */      
+               'mt',
+               
+               /*
+               'one' => array('mod' => 10, 'is' => '1')
+               */
+               'mk', 
+               
+               /*
+               'one' => 1,
+               'two' => 2,
+               //n is 8 or n is 11
+               'many' => array(
+                       array( 'is' => 8 ),
+                       array( 'is' => 11 )
+               )*/
+               'cy'
+];
+
+js2AddOnloadHook( function(){
+       //do mauall script loaders calls to test multiple languages:
+       function doLangTable( langSet ){                
+               //build table output: 
+               var msgTestSet = {                                                                                              
+                       'undelete_short' : [ 0, 1, 2, 5, 21, 30 ],                      
+                       //category-subcat-count' has two params:
+                       'category-subcat-count' : [ 
+                               [0,10], 
+                               [1,2], 
+                               [3,30] 
+                       ]                       
+               };
+                                       
+               var passTest=0;
+               var failTest=0;
+               var testCount=0;        
+               
+                                       
+               //do a manual call to the script-lodaer:
+               function doProcLangKey(langKey){                        
+                       $j.getScript('../../../mwScriptLoader.php?class=mw.testLang&urid='+ scriptLoaderURID +'&uselang='+langKey, function(){                  
+                               var o='';
+                               o+='<tr><td colspan="6" height="20" style="font-size:large"><b>Lang:' + langKey + '</b></td></tr>';             
+                               //now for each langage msg: 
+                               $j.each(msgTestSet, function(mKey, mTestSet){
+                                       //output table names:
+                                       o+='<tr>'+
+                                                       '<td>$1[,$2]</td>'+
+                                                       '<td width="14%">Msg key</td>'+
+                                                       '<td width="34%">Msg text</td>'+
+                                                       '<td width="24%">Msg Transform JS</td>'+
+                                                       '<td width="24%">Msg Transform Mw</td>'+
+                                               '</tr>';
+                               
+                                       //for each number value
+                                       for(var i in mTestSet){
+                                               var numVal = mTestSet[i];                                               
+                                               var numKey = (typeof numVal== 'object')? numVal.join( '_' ).replace('/ /', '_') : numVal;
+                                               var tkey = mKey + '_' + numKey + '_' + langKey;                                                                                         
+                                               o+='<tr>'+
+                                                               '<td>' + numVal + '</td>' + 
+                                                               '<td>' + mKey + '</td>' + 
+                                                               '<td>' + mw.lang.gMsgNoTrans( mKey ) + '</td>' + 
+                                                               '<td id="' + tkey + '_js">' + mw.lang.gM( mKey, numVal ) + '</td>';
+                                               //show mw col:                                          
+                                               if( mKey.substr(0, 5) == 'test_' ){
+                                                       o+='<td> (test msg) </td>';
+                                               }else{  
+                                                       o+='<td id="' + tkey + '">loading...</td>';                                     
+                                                       
+                                                       //get transform from mw (& compare and highlight)
+                                                       function doPopWmMsg(mKey, numVal, numKey){ 
+                                                               //set the local tkey:
+                                                               var tkey = mKey + '_' + numKey + '_' + langKey;
+                                                               testCount++;
+                                                               $j('#score_card').html('Running Tests <span id="perc_done">0</sapn>% done');    
+                                                               var msgparam = (typeof numVal== 'object')? numVal.join( '|' ) : numVal;         
+                                                               do_api_req({
+                                                                       'data': {
+                                                                               'action' : 'parse',
+                                                                               'uselang' : langKey,
+                                                                               'text' : '{{int:' + mKey + '|' + msgparam + '}}'
+                                                                       },
+                                                                       'url' : '../../../api.php'                                      
+                                                               }, function( data ) {                                                   
+                                                                       var t = '#'+ tkey ;                                                             
+                                                                       if(data.parse && data.parse.text && data.parse.text['*']){
+                                                                               $j(t).html( data.parse.text['*'] );                                                                             
+                                                                               var js_txt = $j.trim( $j(t + '_js').text().replace('\n', '') );
+                                                                               var php_txt = $j.trim( $j(t + ' p').text())
+                                                                               //just get the part in the <p> to compare with js version
+                                                                               if( js_txt != php_txt ){
+                                                                               var cat = $j.trim( $j(t + ' p').text() );
+                                                                               var dog =  $j.trim( $j(t + '_js').text() );                                                                                     
+                                                                                       if( cat == dog)
+                                                                                               alert('wtf');
+                                                                                       //debugger;                                                                     
+                                                                                       $j(t).css('color', 'red');
+                                                                                       failTest++;
+                                                                               }else{
+                                                                                       $j(t).css('color', 'green');
+                                                                                       passTest++;
+                                                                               }
+                                                                               var perc = ( failTest + passTest ) / testCount
+                                                                               if( perc != 1){
+                                                                                       $j('#perc_done').html( Math.round(perc*1000)/1000 + '%');
+                                                                               }else{
+                                                                                       var failHtlm = (failTest == 0)?failTest: '<span style="color:red">'+ failTest+'</span>';
+                                                                                       $j('#score_card').html( 
+                                                                                               'Passed: <span style="color:green">' + passTest + '</span> Failed:' + failHtlm );
+                                                                                               
+                                                                                       //done with this lang... call outer function if we have lang keys left to proccess:
+                                                                                       if(langSet.length!=0)
+                                                                                               doProcLangKey( langSet.pop() );         
+                                                                               }                       
+                                                                       }else{
+                                                                               $t.html(' error ');
+                                                                       }
+                                                               });
+                                                       };
+                                                       //pop off an anonymous function call
+                                                       doPopWmMsg(mKey, numVal, numKey);
+                                               } 
+                                               o+='</tr>';                                                                             
+                                       }
+                                       //output a spacer:
+                                       o+='<tr><td colspan="6" height="20"> </td></tr>';                       
+                               });
+                               //put the output into the page: 
+                               $j('#table_out').append( o );                                                           
+                       });                     
+               }//procc lang key:
+               doProcLangKey( langSet.pop() );
+       }
+       //by default run the "debug" set:
+       doLangTable( langKeyDebug );
+});
+
+</script>
+</head>
+<body>
+<h3>Test Javascript plural msg transformations</h3>
+<div id="score_card" style="font-size:large"></div>
+<table id="table_out"></table>
+
+
+</body>
+</html>
diff --git a/js2/mwEmbed/tests/testLang.js b/js2/mwEmbed/tests/testLang.js
new file mode 100644 (file)
index 0000000..17c61ec
--- /dev/null
@@ -0,0 +1,15 @@
+/* a simple language tester replacements
+ */
+
+loadGM( {
+       "undelete_short"  : "Undelete {{PLURAL:$1|one edit|$1 edits}}",
+       "category-subcat-count" : "{{PLURAL:$2|This category has only the following subcategory.|This category has the following {{PLURAL:$1|subcategory|$1 subcategories}}, out of $2 total.}}",
+       "mwe-upload-multi" : "Upload {{PLURAL:$1|file|files}}"
+} );
+
+mw.lang.loadRS( {
+       'PLURAL' : { "one" : 1 }
+} );
+
+// define a class by the name of this file:  
+mw.testLang = { };
\ No newline at end of file
diff --git a/js2/remoteMwEmbed.js b/js2/remoteMwEmbed.js
new file mode 100644 (file)
index 0000000..6f91a68
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ * This file exposes some of the functionality of mwEmbed to wikis
+ * that do not yet have js2 enabled
+ */
+var urlparts = getRemoteEmbedPath();
+var mwEmbedHostPath = urlparts[0];
+var mwRemoteVersion = '1.10';
+var mwUseScriptLoader = true;
+
+// setup up request Params: 
+var reqParts = urlparts[1].substring( 1 ).split( '&' );
+var mwReqParam = { };
+for ( var i = 0; i < reqParts.length; i++ ) {
+       var p = reqParts[i].split( '=' );
+       if ( p.length == 2 )
+               mwReqParam[ p[0] ] = p[1];
+}
+
+addOnloadHook( function() {
+       // Only do rewrites if MV_EMBED / js2 is "off"
+       if ( typeof MV_EMBED_VERSION == 'undefined' ) {
+               doPageSpecificRewrite();
+       }
+} );
+
+function doPageSpecificRewrite() {             
+       // Add media wizard
+       if ( wgAction == 'edit' || wgAction == 'submit' ) {     
+               var jsSetEdit = [ 'remoteSearchDriver', '$j.fn.textSelection', '$j.ui', '$j.ui.sortable' ]
+               mwr_load_mv_embed( jsSetEdit, function() {
+                       loadExternalJs( mwEmbedHostPath + '/editPage.js?' + mwGetReqArgs() );
+               } );
+       }
+       
+       // Timed text display:
+       if ( wgPageName.indexOf( "TimedText" ) === 0 ) {
+               mwr_load_mv_embed( function() {
+                       // Load with mw loader to get localized interface:
+                       mw.load( ['mvTimeTextEdit'], function() {
+                               // could run init here (but mvTimeTextEdit already included onLoad actions)
+                       } );
+               } );
+       }
+       
+       // Firefogg integration
+       if ( wgPageName == "Special:Upload" ) { 
+               var jsSetUpload = [ 'mvBaseUploadInterface', 'mvFirefogg' , '$j.ui',
+                                                       '$j.ui.progressbar', '$j.ui.dialog', '$j.ui.draggable' ]; 
+               mwr_load_mv_embed( jsSetUpload, function() {
+                       loadExternalJs( mwEmbedHostPath + '/uploadPage.js?' + mwGetReqArgs() );
+               } );
+       }
+       
+       // Special api proxy page
+       if ( wgPageName == 'MediaWiki:ApiProxy' ) {
+               var wgEnableIframeApiProxy = true;
+               mwr_load_mv_embed( [ 'mw.proxy' ], function() {                 
+                       loadExternalJs( mwEmbedHostPath + '/apiProxyPage.js?' + mwGetReqArgs() );
+               } );
+       }
+       
+       // OggHandler rewrite for view pages:
+       var vidIdList = [];
+       var divs = document.getElementsByTagName( 'div' );
+       for ( var i = 0; i < divs.length; i++ ) {
+               if ( divs[i].id && divs[i].id.substring( 0, 11 ) == 'ogg_player_' ) {
+                       vidIdList.push( divs[i].getAttribute( "id" ) );
+               }
+       }
+       if ( vidIdList.length > 0 ) {   
+               var jsSetVideo = [ 'embedVideo', '$j.ui', 'ctrlBuilder', '$j.cookie', '$j.ui.slider', 'kskinConfig' ];          
+               // Quick sniff use java if IE and native if firefox 
+               // ( other browsers will run detect and get on-demand )         
+               if (navigator.userAgent.indexOf("MSIE") != -1)
+                       jsSetVideo.push( 'javaEmbed' );
+                       
+               if ( navigator.userAgent &&  navigator.userAgent.indexOf("Firefox") != -1 )
+                       jsSetVideo.push( 'nativeEmbed' );
+       
+               mwr_load_mv_embed( jsSetVideo, function() {
+                       mvJsLoader.embedVideoCheck( function() {
+                               // Do utility rewrite of OggHandler content:
+                               rewrite_for_OggHandler( vidIdList );
+                       } );
+               } );
+       }
+}
+// This will be depreciated in favour of updates to OggHandler
+function rewrite_for_OggHandler( vidIdList ) {
+       function procVidId( vidId ) {
+               // don't process empty vids
+               if ( !vidId )
+                       return ;
+               js_log( 'vidIdList on: ' + vidId + ' length: ' + vidIdList.length + ' left in the set: ' + vidIdList );
+               
+               tag_type = 'video';
+               // Check type:
+               var pwidth = $j( '#' + vidId ).width();
+               var $pimg = $j( '#' + vidId + ' img:first' );           
+               if( $pimg.attr('src').split('/').pop() == 'play.png'){
+                       tag_type = 'audio';
+                       poster_attr = '';               
+                       pheight = 0;
+               }else{
+                       var poster_attr = 'poster = "' + $pimg.attr( 'src' ) + '" ';                    
+                       var pheight = $pimg.attr( 'height' );                           
+               }
+
+
+               // Parsed values:
+               var src = '';
+               var duration_attr = '';
+               var wikiTitleKey = $j( '#' + vidId + ' img' ).filter( ':first' ).attr( 'src' ).split( '/' );
+               wikiTitleKey = unescape( wikiTitleKey[ wikiTitleKey.length - 2 ] );
+               var re = new RegExp( /videoUrl(&quot;:?\s*)*([^&]*)/ );
+               src = re.exec( $j( '#' + vidId ).html() )[2];
+
+               var re = new RegExp( /length(&quot;:?\s*)*([^,]*)/ );
+               var dv = re.exec( $j( '#' + vidId ).html() )[2];
+               if ( dv ) {
+                       duration_attr = 'durationHint="' + dv + '" ';
+               }
+
+               var re = new RegExp( /offset(&quot;:?\s*)*([^&]*)/ );
+               offset = re.exec( $j( '#' + vidId ).html() )[2];
+               var offset_attr = offset ? 'startOffset="' + offset + '"' : '';
+
+               if ( src ) {
+                       var html_out = '';
+                       
+                       var common_attr = ' id="mwe_' + vidId + '" ' +
+                                       'wikiTitleKey="' + wikiTitleKey + '" ' +
+                                       'src="' + src + '" ' +
+                                       duration_attr +
+                                       offset_attr + ' ' +
+                                       'class="kskin" ';
+                                                               
+                       if ( tag_type == 'audio' ) {
+                               html_out = '<audio' + common_attr + ' style="width:' + pwidth + 'px;"></audio>';
+                       } else {
+                               html_out = '<video' + common_attr +
+                               poster_attr + ' ' +
+                               'style="width:' + pwidth + 'px;height:' + pheight + 'px;">' +
+                               '</video>';
+                       }
+                       // Set the video tag inner html and update the height
+                       $j( '#' + vidId ).html( html_out )
+                               .css( 'height', pheight + 30 );
+
+                       // Do the actual rewrite                                
+                       rewrite_by_id( 'mwe_' + vidId, function() {
+                               if ( vidIdList.length != 0 ) {
+                                       setTimeout( function() {
+                                               procVidId( vidIdList.pop() )
+                                       }, 10 );
+                               }
+                       } );
+
+               }               
+       };
+       // process each item in the vidIdList (with setTimeout to avoid locking)
+       procVidId( vidIdList.pop() );
+}
+function getRemoteEmbedPath() {
+       for ( var i = 0; i < document.getElementsByTagName( 'script' ).length; i++ ) {
+               var s = document.getElementsByTagName( 'script' )[i];
+               if ( s.src.indexOf( '/remoteMwEmbed.js' ) != - 1 ) {
+                       var reqStr = '';
+                       var scriptPath = '';
+                       if ( s.src.indexOf( '?' ) != - 1 ) {
+                               reqStr = s.src.substr( s.src.indexOf( '?' ) );
+                               scriptPath = s.src.substr( 0,  s.src.indexOf( '?' ) ).replace( '/remoteMwEmbed.js', '' );
+                       } else {
+                               scriptPath = s.src.replace( '/remoteMwEmbed.js', '' )
+                       }
+                       // Use the external_media_wizard path:
+                       return [scriptPath, reqStr];
+               }
+       }
+}
+function mwGetReqArgs() {
+       var rurl = '';
+       if ( mwReqParam['debug'] )
+               rurl += 'debug=true&';
+
+       if ( mwReqParam['uselang'] )
+               rurl += 'uselang=' + mwReqParam['uselang'] + '&';
+
+       if ( mwReqParam['urid'] ) {
+               rurl += 'urid=' + mwReqParam['urid'];
+       } else {
+               // Make sure to use an urid 
+               // This way remoteMwEmbed can control version of code being requested
+               rurl += 'urid=' + mwRemoteVersion;
+       }
+       return rurl;
+}
+/**
+* @param {mixed} function or classSet to preload
+* classSet saves round trips to the server by grabbing things we will likely need in the first request. 
+* ( this is essentially a shortcut to mv_jqueryBindings in mv_embed.js )   
+* @param {callback} function callback to be called once mv_embed is ready
+*/
+function mwr_load_mv_embed( classSet, callback ) {
+       if( typeof classSet == 'function')
+               callback = classSet;
+       // Inject mv_embed if needed
+       if ( typeof mw == 'undefined' ) {
+               if ( ( mwReqParam['uselang'] || mwReqParam['useloader'] ) && mwUseScriptLoader ) {
+                       var rurl = mwEmbedHostPath + '/mwEmbed/jsScriptLoader.php?class=mv_embed';
+                       
+                       // Add jQuery too if we need it: 
+                       if ( typeof window.jQuery == 'undefined' ) {
+                               rurl += ',window.jQuery';
+                       }       
+                                                               
+                       // Add requested classSet
+                       for( var i=0; i < classSet.length; i++ ){
+                               var cName =  classSet[i];
+                               if( !mwr_check_obj_path( cName ) ){
+                                       rurl +=  ',' + cName;
+                               }
+                       }
+                       
+                       // Add the remaining arguments
+                       rurl += '&' + mwGetReqArgs();
+                                                       
+                       importScriptURI( rurl );
+               } else { 
+                       // Ingore classSet (will be loaded onDemand )
+                       importScriptURI( mwEmbedHostPath + '/mwEmbed/mv_embed.js?' + mwGetReqArgs() );
+               }
+       }
+       mwr_check_for_mv_embed( callback );
+}
+
+function mwr_check_for_mv_embed( callback ) {
+       if ( typeof mw == 'undefined' ) {
+               setTimeout( function() {
+                       mwr_check_for_mv_embed( callback );
+               }, 25 );
+       } else {
+               callback();
+       }
+}
+
+function mwr_check_obj_path ( libVar ) {
+       if ( !libVar )
+               return false;
+       var objPath = libVar.split( '.' )
+       var cur_path = '';
+       for ( var p = 0; p < objPath.length; p++ ) {
+               cur_path = ( cur_path == '' ) ? cur_path + objPath[p] : cur_path + '.' + objPath[p];
+               eval( 'var ptest = typeof ( ' + cur_path + ' ); ' );
+               if ( ptest == 'undefined' ) {
+                       this.missing_path = cur_path;
+                       return false;
+               }
+       }
+       this.cur_path = cur_path;
+       return true;
+};
diff --git a/js2/uploadPage.js b/js2/uploadPage.js
new file mode 100644 (file)
index 0000000..dbe8e04
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * This script is run on [[Special:Upload]].
+ * It controls the invocation of the mvUploader class based on local config.
+ */
+
+var mwUploadFormSelector = '#mw-upload-form';
+// Set up the upload form bindings once all DOM manipulation is done
+var mwUploadHelper = {
+       init: function() {
+               var _this = this;
+               // If wgEnableFirefogg is not boolean false, set to true
+               if ( typeof wgEnableFirefogg == 'undefined' )
+                       wgEnableFirefogg = true;
+
+               if ( wgEnableFirefogg ) {
+                       // Set up the upload handler to Firefogg. Should work with the HTTP uploads too.
+                       $j( '#wpUploadFile' ).firefogg( {
+                               // An API URL (we won't submit directly to action of the form)
+                               'api_url': wgServer + wgScriptPath + '/api.php',
+                               'form_rewrite': true,
+                               // MediaWiki API supports chunk uploads: 
+                               'enable_chunks' : true, 
+                               'edit_form_selector': mwUploadFormSelector,
+                               'new_source_cb': function( orgFilename, oggName ) {
+                                       $j( '#wpDestFile' ).val( oggName );
+                                       $j( '#wpDestFile' ).doDestCheck( {
+                                               'warn_target': '#wpDestFile-warning'
+                                       } );
+                               }
+                       } );
+               } else {
+                       // Add basic upload profile support ( http status monitoring, progress box for
+                       // browsers that support it, etc.)
+                       if ( $j( '#wpUploadFileURL' ).length != 0 ) {
+                               $j( '#wpUploadFileURL' ).baseUploadInterface( {
+                                       'api_url': wgServer + wgScriptPath + '/api.php',
+                                       'edit_form_selector': mwUploadFormSelector
+                               } );
+                       }
+               }
+
+               if ( wgAjaxUploadDestCheck ) {
+                       // Do destination check
+                       $j( '#wpDestFile' ).change( function() {
+                               $j( '#wpDestFile' ).doDestCheck( {
+                                       'warn_target':'#wpDestFile-warning'
+                               } );
+                       } );
+               }
+
+               // Check if we have HTTP enabled & setup enable/disable toggle:
+               if ( $j( '#wpUploadFileURL' ).length != 0 ) {
+                       // Set the initial toggleUpType
+                       _this.toggleUpType( true );
+
+                       $j( "input[name='wpSourceType']" ).click( function() {
+                               _this.toggleUpType( this.id == 'wpSourceTypeFile' );
+                       } );
+               }
+               $j( '#wpUploadFile,#wpUploadFileURL' )
+               .focus( function() {
+                       _this.toggleUpType( this.id == 'wpUploadFile' );
+               } )
+               // Also setup the onChange event binding:
+               .change( function() {
+                       if ( wgUploadAutoFill ) {
+                               mwUploadHelper.doDestinationFill( this );
+                       }
+               } );
+       },
+       /**
+       * Set the upload radio buttons
+       *
+       * @boolean set
+       */
+       toggleUpType: function( set ) {
+               $j( '#wpSourceTypeFile' ).attr( 'checked', set );
+               $j( '#wpUploadFile' ).attr( 'disabled', !set );
+
+               $j( '#wpSourceTypeURL' ).attr( 'checked', !set );
+               $j( '#wpUploadFileURL' ).attr( 'disabled', set );
+
+               // If Firefogg is enabled, toggle action according to wpSourceTypeFile selection
+               if ( wgEnableFirefogg ) {
+                       $j( '#wpUploadFile' ).firefogg( {
+                               'firefogg_form_action': $j( '#wpSourceTypeFile' ).attr( 'checked' )
+                       } );
+               }
+       },
+       /**
+       * Fill in a destination file-name based on a source asset name.
+       */
+       doDestinationFill: function( targetElm ) {
+               js_log( "doDestinationFill" )
+               // Remove any previously flagged errors
+               $j( '#mw-upload-permitted,#mw-upload-prohibited' ).hide();
+
+               var path = $j( targetElm ).val();
+               // Find trailing part
+               var slash = path.lastIndexOf( '/' );
+               var backslash = path.lastIndexOf( '\\' );
+               var fname;
+               if ( slash == -1 && backslash == -1 ) {
+                       fname = path;
+               } else if ( slash > backslash ) {
+                       fname = path.substring( slash + 1, 10000 );
+               } else {
+                       fname = path.substring( backslash + 1, 10000 );
+               }
+               // URLs are less likely to have a useful extension. Don't include them in the extension check.
+               if ( wgFileExtensions && $j( targetElm ).attr( 'id' ) != 'wpUploadFileURL' ) {
+                       var found = false;
+                       if ( fname.lastIndexOf( '.' ) != -1 ) {
+                               var ext = fname.substr( fname.lastIndexOf( '.' ) + 1 );
+                               for ( var i = 0; i < wgFileExtensions.length; i++ ) {
+                                       if ( wgFileExtensions[i].toLowerCase() == ext.toLowerCase() )
+                                       found = true;
+                               }
+                       }
+                       if ( !found ) {
+                               // Clear the upload. Set mw-upload-permitted to error.
+                               $j( targetElm ).val( '' );
+                               $j( '#mw-upload-permitted,#mw-upload-prohibited' ).show().addClass( 'error' );
+                               $j( '#wpDestFile' ).val( '' );
+                               return false;
+                       }
+               }
+               // Capitalise first letter and replace spaces by underscores
+               fname = fname.charAt( 0 ).toUpperCase().concat( fname.substring( 1, 10000 ) ).replace(/ /g, '_' );
+               // Output result
+               $j( '#wpDestFile' ).val( fname );
+
+               // Do a destination check
+               $j( '#wpDestFile' ).doDestCheck( {
+                       'warn_target': '#wpDestFile-warning'
+               } );
+       }
+}
+
+
+js2AddOnloadHook( function() {
+       mwUploadHelper.init();
+} );
\ No newline at end of file