From 70bcfb5b861894ecfc5df386921586e3b2ff2555 Mon Sep 17 00:00:00 2001 From: plegall Date: Tue, 27 May 2014 14:11:23 +0000 Subject: feature 2616: HTML5 upload (with plupload 2.1.2). First basic implementation. Needs customization. Chunked upload + Drag & drop (no more Flash) use a new specific API method pwg.images.upload git-svn-id: http://piwigo.org/svn/trunk@28545 68402e56-0260-453c-a942-63ccdbb3a9ee --- themes/default/js/plugins/plupload/Moxie.swf | Bin 0 -> 29349 bytes themes/default/js/plugins/plupload/Moxie.xap | Bin 0 -> 62643 bytes themes/default/js/plugins/plupload/i18n/ar.js | 2 + themes/default/js/plugins/plupload/i18n/az.js | 2 + themes/default/js/plugins/plupload/i18n/bs.js | 2 + themes/default/js/plugins/plupload/i18n/cs.js | 2 + themes/default/js/plugins/plupload/i18n/cy.js | 2 + themes/default/js/plugins/plupload/i18n/da.js | 2 + themes/default/js/plugins/plupload/i18n/de.js | 2 + themes/default/js/plugins/plupload/i18n/el.js | 2 + themes/default/js/plugins/plupload/i18n/en.js | 2 + themes/default/js/plugins/plupload/i18n/es.js | 2 + themes/default/js/plugins/plupload/i18n/et.js | 2 + themes/default/js/plugins/plupload/i18n/fa.js | 2 + themes/default/js/plugins/plupload/i18n/fi.js | 2 + themes/default/js/plugins/plupload/i18n/fr.js | 2 + themes/default/js/plugins/plupload/i18n/he.js | 2 + themes/default/js/plugins/plupload/i18n/hr.js | 2 + themes/default/js/plugins/plupload/i18n/hu.js | 2 + themes/default/js/plugins/plupload/i18n/hy.js | 2 + themes/default/js/plugins/plupload/i18n/id.js | 2 + themes/default/js/plugins/plupload/i18n/it.js | 2 + themes/default/js/plugins/plupload/i18n/ja.js | 2 + themes/default/js/plugins/plupload/i18n/ka.js | 2 + themes/default/js/plugins/plupload/i18n/kk.js | 2 + themes/default/js/plugins/plupload/i18n/km.js | 2 + themes/default/js/plugins/plupload/i18n/ko.js | 2 + themes/default/js/plugins/plupload/i18n/lt.js | 2 + themes/default/js/plugins/plupload/i18n/lv.js | 2 + themes/default/js/plugins/plupload/i18n/mn.js | 2 + themes/default/js/plugins/plupload/i18n/ms.js | 2 + themes/default/js/plugins/plupload/i18n/nl.js | 2 + themes/default/js/plugins/plupload/i18n/pl.js | 2 + themes/default/js/plugins/plupload/i18n/pt_BR.js | 2 + themes/default/js/plugins/plupload/i18n/ro.js | 2 + themes/default/js/plugins/plupload/i18n/ru.js | 2 + themes/default/js/plugins/plupload/i18n/sk.js | 2 + themes/default/js/plugins/plupload/i18n/sq.js | 2 + themes/default/js/plugins/plupload/i18n/sr.js | 2 + themes/default/js/plugins/plupload/i18n/sr_RS.js | 2 + themes/default/js/plugins/plupload/i18n/sv.js | 2 + themes/default/js/plugins/plupload/i18n/th_TH.js | 2 + themes/default/js/plugins/plupload/i18n/tr.js | 2 + themes/default/js/plugins/plupload/i18n/uk_UA.js | 2 + themes/default/js/plugins/plupload/i18n/zh_CN.js | 2 + themes/default/js/plugins/plupload/i18n/zh_TW.js | 2 + .../css/jquery.plupload.queue.css | 185 + .../jquery.plupload.queue/img/backgrounds.gif | Bin 0 -> 2977 bytes .../jquery.plupload.queue/img/buttons-disabled.png | Bin 0 -> 1292 bytes .../plupload/jquery.plupload.queue/img/buttons.png | Bin 0 -> 1439 bytes .../plupload/jquery.plupload.queue/img/delete.gif | Bin 0 -> 180 bytes .../plupload/jquery.plupload.queue/img/done.gif | Bin 0 -> 1024 bytes .../plupload/jquery.plupload.queue/img/error.gif | Bin 0 -> 994 bytes .../jquery.plupload.queue/img/throbber.gif | Bin 0 -> 1922 bytes .../jquery.plupload.queue/img/transp50.png | Bin 0 -> 399 bytes .../jquery.plupload.queue/jquery.plupload.queue.js | 428 + .../jquery.plupload.queue.min.js | 1 + .../jquery.ui.plupload/css/jquery.ui.plupload.css | 371 + .../css/jquery.ui.plupload.css.orig | 370 + .../plupload/jquery.ui.plupload/img/loading.gif | Bin 0 -> 4023 bytes .../plupload/jquery.ui.plupload/img/plupload.png | Bin 0 -> 6597 bytes .../jquery.ui.plupload/jquery.ui.plupload.js | 1323 +++ .../jquery.ui.plupload/jquery.ui.plupload.min.js | 1 + themes/default/js/plugins/plupload/moxie.js | 10726 +++++++++++++++++++ themes/default/js/plugins/plupload/moxie.min.js | 15 + themes/default/js/plugins/plupload/plupload.dev.js | 2315 ++++ .../js/plugins/plupload/plupload.full.min.js | 28 + themes/default/js/plugins/plupload/plupload.min.js | 13 + 68 files changed, 15864 insertions(+) create mode 100644 themes/default/js/plugins/plupload/Moxie.swf create mode 100644 themes/default/js/plugins/plupload/Moxie.xap create mode 100644 themes/default/js/plugins/plupload/i18n/ar.js create mode 100644 themes/default/js/plugins/plupload/i18n/az.js create mode 100644 themes/default/js/plugins/plupload/i18n/bs.js create mode 100644 themes/default/js/plugins/plupload/i18n/cs.js create mode 100644 themes/default/js/plugins/plupload/i18n/cy.js create mode 100644 themes/default/js/plugins/plupload/i18n/da.js create mode 100644 themes/default/js/plugins/plupload/i18n/de.js create mode 100644 themes/default/js/plugins/plupload/i18n/el.js create mode 100644 themes/default/js/plugins/plupload/i18n/en.js create mode 100644 themes/default/js/plugins/plupload/i18n/es.js create mode 100644 themes/default/js/plugins/plupload/i18n/et.js create mode 100644 themes/default/js/plugins/plupload/i18n/fa.js create mode 100644 themes/default/js/plugins/plupload/i18n/fi.js create mode 100644 themes/default/js/plugins/plupload/i18n/fr.js create mode 100644 themes/default/js/plugins/plupload/i18n/he.js create mode 100644 themes/default/js/plugins/plupload/i18n/hr.js create mode 100644 themes/default/js/plugins/plupload/i18n/hu.js create mode 100644 themes/default/js/plugins/plupload/i18n/hy.js create mode 100644 themes/default/js/plugins/plupload/i18n/id.js create mode 100644 themes/default/js/plugins/plupload/i18n/it.js create mode 100644 themes/default/js/plugins/plupload/i18n/ja.js create mode 100644 themes/default/js/plugins/plupload/i18n/ka.js create mode 100644 themes/default/js/plugins/plupload/i18n/kk.js create mode 100644 themes/default/js/plugins/plupload/i18n/km.js create mode 100644 themes/default/js/plugins/plupload/i18n/ko.js create mode 100644 themes/default/js/plugins/plupload/i18n/lt.js create mode 100644 themes/default/js/plugins/plupload/i18n/lv.js create mode 100644 themes/default/js/plugins/plupload/i18n/mn.js create mode 100644 themes/default/js/plugins/plupload/i18n/ms.js create mode 100644 themes/default/js/plugins/plupload/i18n/nl.js create mode 100644 themes/default/js/plugins/plupload/i18n/pl.js create mode 100644 themes/default/js/plugins/plupload/i18n/pt_BR.js create mode 100644 themes/default/js/plugins/plupload/i18n/ro.js create mode 100644 themes/default/js/plugins/plupload/i18n/ru.js create mode 100644 themes/default/js/plugins/plupload/i18n/sk.js create mode 100644 themes/default/js/plugins/plupload/i18n/sq.js create mode 100644 themes/default/js/plugins/plupload/i18n/sr.js create mode 100644 themes/default/js/plugins/plupload/i18n/sr_RS.js create mode 100644 themes/default/js/plugins/plupload/i18n/sv.js create mode 100644 themes/default/js/plugins/plupload/i18n/th_TH.js create mode 100644 themes/default/js/plugins/plupload/i18n/tr.js create mode 100644 themes/default/js/plugins/plupload/i18n/uk_UA.js create mode 100644 themes/default/js/plugins/plupload/i18n/zh_CN.js create mode 100644 themes/default/js/plugins/plupload/i18n/zh_TW.js create mode 100644 themes/default/js/plugins/plupload/jquery.plupload.queue/css/jquery.plupload.queue.css create mode 100644 themes/default/js/plugins/plupload/jquery.plupload.queue/img/backgrounds.gif create mode 100644 themes/default/js/plugins/plupload/jquery.plupload.queue/img/buttons-disabled.png create mode 100644 themes/default/js/plugins/plupload/jquery.plupload.queue/img/buttons.png create mode 100644 themes/default/js/plugins/plupload/jquery.plupload.queue/img/delete.gif create mode 100644 themes/default/js/plugins/plupload/jquery.plupload.queue/img/done.gif create mode 100644 themes/default/js/plugins/plupload/jquery.plupload.queue/img/error.gif create mode 100644 themes/default/js/plugins/plupload/jquery.plupload.queue/img/throbber.gif create mode 100644 themes/default/js/plugins/plupload/jquery.plupload.queue/img/transp50.png create mode 100644 themes/default/js/plugins/plupload/jquery.plupload.queue/jquery.plupload.queue.js create mode 100644 themes/default/js/plugins/plupload/jquery.plupload.queue/jquery.plupload.queue.min.js create mode 100644 themes/default/js/plugins/plupload/jquery.ui.plupload/css/jquery.ui.plupload.css create mode 100644 themes/default/js/plugins/plupload/jquery.ui.plupload/css/jquery.ui.plupload.css.orig create mode 100644 themes/default/js/plugins/plupload/jquery.ui.plupload/img/loading.gif create mode 100644 themes/default/js/plugins/plupload/jquery.ui.plupload/img/plupload.png create mode 100644 themes/default/js/plugins/plupload/jquery.ui.plupload/jquery.ui.plupload.js create mode 100644 themes/default/js/plugins/plupload/jquery.ui.plupload/jquery.ui.plupload.min.js create mode 100644 themes/default/js/plugins/plupload/moxie.js create mode 100644 themes/default/js/plugins/plupload/moxie.min.js create mode 100644 themes/default/js/plugins/plupload/plupload.dev.js create mode 100644 themes/default/js/plugins/plupload/plupload.full.min.js create mode 100644 themes/default/js/plugins/plupload/plupload.min.js (limited to 'themes/default/js/plugins/plupload') diff --git a/themes/default/js/plugins/plupload/Moxie.swf b/themes/default/js/plugins/plupload/Moxie.swf new file mode 100644 index 000000000..da9914bb8 Binary files /dev/null and b/themes/default/js/plugins/plupload/Moxie.swf differ diff --git a/themes/default/js/plugins/plupload/Moxie.xap b/themes/default/js/plugins/plupload/Moxie.xap new file mode 100644 index 000000000..aabc9f7c8 Binary files /dev/null and b/themes/default/js/plugins/plupload/Moxie.xap differ diff --git a/themes/default/js/plugins/plupload/i18n/ar.js b/themes/default/js/plugins/plupload/i18n/ar.js new file mode 100644 index 000000000..dc348395d --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/ar.js @@ -0,0 +1,2 @@ +// Arabic (ar) +plupload.addI18n({"Stop Upload":"أيقاف التحميل","Upload URL might be wrong or doesn't exist.":"عنوان التحميل ربما يكون خاطئ أو غير متوفر","tb":"تيرابايت","Size":"الحجم","Close":"أغلاق","Init error.":"خطأ في تهيئة","Add files to the upload queue and click the start button.":"أضف ملفات إلى القائمة إنتظار التحميل ثم أضغط على زر البداية","Filename":"أسم الملف","Image format either wrong or not supported.":"صيغة الصورة أما خطاء أو غير مدعومه","Status":"الحالة","HTTP Error.":"خطأ في برتوكول نقل الملفات","Start Upload":"أبدا التحميل","mb":"ميجابايت","kb":"كيلوبايت","Duplicate file error.":"خطاء في تكرار الملف","File size error.":"خطأ في حجم الملف","N/A":"لا شي","gb":"جيجابايت","Error: Invalid file extension:":"خطاء : أمتداد الملف غير صالح :","Select files":"أختر الملفات","%s already present in the queue.":"%s الملف موجود بالفعل في قائمة الانتظار","File: %s":"ملف: %s","b":"بايت","Uploaded %d/%d files":"تحميل %d/%d ملف","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"العناصر المقبوله لتحميل هي %d ملف في هذا الوقت. الملفات الاضافية أزيلة.","%d files queued":"%d الملفات في قائمة الانتظار","File: %s, size: %d, max file size: %d":"ملف: %s, أقصى حجم للملف: %d, حجم: %d","Drag files here.":"سحب الملف هنا","Runtime ran out of available memory.":"الذاكرة المتوفره أنتهت لمدة التشغيل","File count error.":"خطاء في عد الملفات","File extension error.":"خطأ في أمتداد الملف","Error: File too large:":" خطاء : حجم الملف كبير :","Add Files":"أضف ملفات"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/az.js b/themes/default/js/plugins/plupload/i18n/az.js new file mode 100644 index 000000000..5930cbb2f --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/az.js @@ -0,0 +1,2 @@ +// Azerbaijani (az) +plupload.addI18n({"Stop Upload":"Yükləməni saxla","Upload URL might be wrong or doesn't exist.":"Yükləmə ünvanı səhvdir və ya mövcud deyil","tb":"tb","Size":"Həcm","Close":"Bağla","Init error.":"Init error.","Add files to the upload queue and click the start button.":"Faylları əlavə edin və yüklə düyməsinə klikləyin.","Filename":"Faylın adı","Image format either wrong or not supported.":"Şəklin formatı uyğun deyil və ya dəstəklənmir.","Status":"Status","HTTP Error.":"HTTP xətası.","Start Upload":"Yüklə","mb":"mb","kb":"kb","Duplicate file error.":"Bu fayl artıq növbədə var.","File size error.":"Fayl həcmi xətası.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Xəta: Yanlış fayl uzantısı:","Select files":"Faylları seçin","%s already present in the queue.":"%s artıq növbədə var.","File: %s":"Fayl: %s","b":"b","Uploaded %d/%d files":"%d/%d fayl yüklənib","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"Növbədə %d fayl var","File: %s, size: %d, max file size: %d":"Fayl: %s, həcm: %d, max fayl həcmi: %d","Drag files here.":"Faylları bura çəkin.","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"Fayl sayı çox böyükdür.","File extension error.":"Fayl uzantısı xətası.","Error: File too large:":"Xəta:Fayl həcmi çox böyükdür.","Add Files":"Fayl əlavə et"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/bs.js b/themes/default/js/plugins/plupload/i18n/bs.js new file mode 100644 index 000000000..27fe00933 --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/bs.js @@ -0,0 +1,2 @@ +// Bosnian (bs) +plupload.addI18n({"Stop Upload":"Prekini dodavanje","Upload URL might be wrong or doesn't exist.":"URL za dodavanje je neispravan ili ne postoji.","tb":"tb","Size":"Veličina","Close":"Zatvori","Init error.":"Inicijalizacijska greška.","Add files to the upload queue and click the start button.":"Dodajte datoteke u red i kliknite na dugme za pokretanje.","Filename":"Naziv datoteke","Image format either wrong or not supported.":"Format slike je neispravan ili nije podržan.","Status":"Status","HTTP Error.":"HTTP greška.","Start Upload":"Započni dodavanje","mb":"mb","kb":"kb","Duplicate file error.":"Dupla datoteka.","File size error.":"Greška u veličini datoteke.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Greška! Neispravan ekstenzija datoteke:","Select files":"Odaberite datoteke","%s already present in the queue.":"%s se već nalazi u redu.","File: %s":"Datoteka: %s","b":"b","Uploaded %d/%d files":"Dodano %d/%d datoteka","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Dodavanje trenutno dozvoljava samo %d datoteka istovremeno. Dodatne datoteke su uklonjene.","%d files queued":"%d datoteka čeka","File: %s, size: %d, max file size: %d":"Datoteka: %s, veličina: %d, maksimalna veličina: %d","Drag files here.":"Dovucite datoteke ovdje.","Runtime ran out of available memory.":"Nema više dostupne memorije.","File count error.":"Greška u brojanju datoeka.","File extension error.":"Greška u ekstenziji datoteke.","Error: File too large:":"Greška! Datoteka je prevelika:","Add Files":"Dodaj datoteke"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/cs.js b/themes/default/js/plugins/plupload/i18n/cs.js new file mode 100644 index 000000000..82c21ed09 --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/cs.js @@ -0,0 +1,2 @@ +// Czech (cs) +plupload.addI18n({"Stop Upload":"Zastavit nahrávání","Upload URL might be wrong or doesn't exist.":"URL uploadu je možná špatně, nebo neexistuje.","tb":"tb","Size":"Velikost","Close":"Zavřít","Init error.":"Chyba inicializace.","Add files to the upload queue and click the start button.":"Přidejte soubory do fronty a pak spusťte nahrávání.","Filename":"Název souboru","Image format either wrong or not supported.":"Špatný, nebo nepodporovaný formát obrázku.","Status":"Stav","HTTP Error.":"Chyba HTTP.","Start Upload":"Spustit nahrávání","mb":"mb","kb":"kb","Duplicate file error.":"Chyba - duplikovaný soubor.","File size error.":"Chyba velikosti souboru.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Chyba: Neplatná koncovka souboru:","Select files":"Vyberte soubory","%s already present in the queue.":"%s je již zařazen ve frontě.","File: %s":"Soubor: %s","b":"b","Uploaded %d/%d files":"Nahráno %d/%d souborů","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload akceptuje pouze %d soubor(ů) najednou. Další soubory byly odstraněny.","%d files queued":"%d souborů ve frontě","File: %s, size: %d, max file size: %d":"Soubor: %s, velikost: %d, maximální velikost souboru: %d","Drag files here.":"Sem přetáhněte soubory.","Runtime ran out of available memory.":"Běh skriptu přesáhl dostupnou paměť.","File count error.":"Chyba v počtu souborů.","File extension error.":"Chyba přípony souboru.","Error: File too large:":"Chyba: Soubor je příliš veliký:","Add Files":"Přidat soubory"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/cy.js b/themes/default/js/plugins/plupload/i18n/cy.js new file mode 100644 index 000000000..54a60c026 --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/cy.js @@ -0,0 +1,2 @@ +// Welsh (cy) +plupload.addI18n({"Stop Upload":"Atal Lanlwytho","Upload URL might be wrong or doesn't exist.":"URL y lanlwythiad ynb anghywir neu ddim yn bodoli.","tb":"tb","Size":"Maint","Close":"Cau","Init error.":"Gwall cych.","Add files to the upload queue and click the start button.":"Ychwanegwch ffeiliau i'r ciw lanlwytho a chlicio'r botwm dechrau.","Filename":"Enw'r ffeil","Image format either wrong or not supported.":"Fformat delwedd yn anghywir neu heb ei gynnal.","Status":"Statws","HTTP Error.":"Gwall HTTP.","Start Upload":"Dechrau Lanlwytho","mb":"mb","kb":"kb","Duplicate file error.":"Gwall ffeil ddyblyg.","File size error.":"Gwall maint ffeil.","N/A":"Dd/A","gb":"gb","Error: Invalid file extension:":"Gwall: estyniad ffeil annilys:","Select files":"Dewis ffeiliau","%s already present in the queue.":"%s yn y ciw yn barod.","File: %s":"Ffeil: %s","b":"b","Uploaded %d/%d files":"Lanlwythwyd %d/%d ffeil","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Mae'r elfen lanlwytho yn derbyn %d ffeil ar y tro. Caiff ffeiliau ychwanegol eu tynnu.","%d files queued":"%d ffeil mewn ciw","File: %s, size: %d, max file size: %d":"Ffeil: %s, maint: %d, maint mwyaf ffeil: %d","Drag files here.":"Llusgwch ffeiliau yma.","Runtime ran out of available memory.":"Allan o gof.","File count error.":"Gwall cyfri ffeiliau.","File extension error.":"Gwall estyniad ffeil.","Error: File too large:":"Gwall: Ffeil yn rhy fawr:","Add Files":"Ychwanegu Ffeiliau"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/da.js b/themes/default/js/plugins/plupload/i18n/da.js new file mode 100644 index 000000000..9a4f62fea --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/da.js @@ -0,0 +1,2 @@ +// Danish (da) +plupload.addI18n({"Stop Upload":"Stop upload","Upload URL might be wrong or doesn't exist.":"Upload URL kan være forkert eller ikke eksisterende.","tb":"tb","Size":"Størrelse","Close":"Luk","Init error.":"Opstarts fejl.","Add files to the upload queue and click the start button.":"Tilføj filer til køen og klik Start upload knappen.","Filename":"Filnavn","Image format either wrong or not supported.":"Billede format er enten forkert eller ikke understøttet.","Status":"Status","HTTP Error.":"HTTP fejl.","Start Upload":"Start upload","mb":"mb","kb":"kb","Duplicate file error.":"Filen findes allerede.","File size error.":"Filstørrelse fejl.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Fejl: Ugyldigt fil format:","Select files":"Vælg filer","%s already present in the queue.":"%s findes allerede i køen.","File: %s":"Fil: %s","b":"b","Uploaded %d/%d files":"Uploaded %d/%d filer","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload accepterer kun %d fil(er) af gangen. Ekstra filer blev skippet.","%d files queued":"%d filer i kø","File: %s, size: %d, max file size: %d":"Fil: %s, størrelse: %d, maks. filstørrelse: %d","Drag files here.":"Træk filer her.","Runtime ran out of available memory.":"Runtime mangler tilgængelige hukommelse.","File count error.":"Fil antal fejl.","File extension error.":"Fil format fejl.","Error: File too large:":"Fejl: Filen er for stor:","Add Files":"Tilføj filer"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/de.js b/themes/default/js/plugins/plupload/i18n/de.js new file mode 100644 index 000000000..c738343de --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/de.js @@ -0,0 +1,2 @@ +// German (de) +plupload.addI18n({"Stop Upload":"Hochladen stoppen","Upload URL might be wrong or doesn't exist.":"Upload-URL ist falsch oder existiert nicht.","tb":"TB","Size":"Größe","Close":"Schließen","Init error.":"Initialisierungsfehler","Add files to the upload queue and click the start button.":"Dateien hinzufügen und auf 'Hochladen' klicken.","Filename":"Dateiname","Image format either wrong or not supported.":"Bildformat falsch oder nicht unterstützt.","Status":"Status","HTTP Error.":"HTTP-Fehler","Start Upload":"Hochladen beginnen","mb":"MB","kb":"KB","Duplicate file error.":"Datei bereits hochgeladen","File size error.":"Fehler bei Dateigröße","N/A":"Nicht verfügbar","gb":"GB","Error: Invalid file extension:":"Fehler: Ungültige Dateiendung:","Select files":"Dateien auswählen","%s already present in the queue.":"%s ist bereits in der Warteschlange","File: %s":"Datei: %s","b":"B","Uploaded %d/%d files":"%d/%d Dateien wurden hochgeladen","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Pro Durchgang können nur %d Datei(en) akzeptiert werden. Überzählige Dateien wurden ignoriert.","%d files queued":"%d Dateien in der Warteschlange","File: %s, size: %d, max file size: %d":"Datei: %s, Größe: %d, maximale Dateigröße: %d","Drag files here.":"Dateien hier hin ziehen.","Runtime ran out of available memory.":"Nicht genügend Speicher verfügbar.","File count error.":"Fehlerhafte Dateianzahl.","File extension error.":"Fehler bei Dateiendung","Error: File too large:":"Fehler: Datei zu groß:","Add Files":"Dateien hinzufügen"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/el.js b/themes/default/js/plugins/plupload/i18n/el.js new file mode 100644 index 000000000..1cabee897 --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/el.js @@ -0,0 +1,2 @@ +// Greek (el) +plupload.addI18n({"Stop Upload":"Ακύρωση Μεταφόρτωσης","Upload URL might be wrong or doesn't exist.":"Το URL μεταφόρτωσης είναι λάθος ή δεν υπάρχει.","tb":"tb","Size":"Μέγεθος","Close":"Κλείσιμο","Init error.":"Σφάλμα αρχικοποίησης.","Add files to the upload queue and click the start button.":"Προσθέστε αρχεία στην ουρά μεταφόρτωσης και πατήστε το κουμπί εκκίνησης.","Filename":"Όνομα Αρχείου","Image format either wrong or not supported.":"Ο τύπος εικόνας είναι λάθος ή δεν υποστηρίζεται.","Status":"Κατάσταση","HTTP Error.":"Σφάλμα HTTP.","Start Upload":"Εκκίνηση Μεταφόρτωσης","mb":"mb","kb":"kb","Duplicate file error.":"Το αρχείο έχει ξαναπροστεθεί.","File size error.":"Σφάλμα με το μέγεθος του αρχείου.","N/A":"Δεν ισχύει","gb":"gb","Error: Invalid file extension:":"Σφάλμα: Μη έγκυρος τύπος αρχείου:","Select files":"Επιλέξτε Αρχεία","%s already present in the queue.":"Το «%s» βρίσκεται ήδη στην ουρά.","File: %s":"Αρχείο: %s","b":"b","Uploaded %d/%d files":"Μεταφορτώθηκαν %d/%d αρχεία","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Μπορείτε να μεταφορτώσετε μεχρι και %d αρχείο/α κάθε φορά. Τα επιπλέον αρχεία αφαιρέθηκαν.","%d files queued":"%d αρχεία στην ουρά","File: %s, size: %d, max file size: %d":"Αρχείο: %s, μέγεθος: %d, μέγιστο μέγεθος αρχείου: %d","Drag files here.":"Σύρετε αρχεία εδώ","Runtime ran out of available memory.":"Δεν υπάρχει αρκετή διαθέσιμη μνήμη.","File count error.":"Σφάλμα με τον αριθμό αρχείων.","File extension error.":"Σφάλμα με τον τύπο αρχείου.","Error: File too large:":"Σφάλμα: Πολύ μεγάλο αρχείο:","Add Files":"Προσθέστε Αρχεία"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/en.js b/themes/default/js/plugins/plupload/i18n/en.js new file mode 100644 index 000000000..6ab3e2e08 --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/en.js @@ -0,0 +1,2 @@ +// English (en) +plupload.addI18n({"Stop Upload":"Stop Upload","Upload URL might be wrong or doesn't exist.":"Upload URL might be wrong or doesn't exist.","tb":"tb","Size":"Size","Close":"Close","Init error.":"Init error.","Add files to the upload queue and click the start button.":"Add files to the upload queue and click the start button.","Filename":"Filename","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"Status","HTTP Error.":"HTTP Error.","Start Upload":"Start Upload","mb":"mb","kb":"kb","Duplicate file error.":"Duplicate file error.","File size error.":"File size error.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Error: Invalid file extension:","Select files":"Select files","%s already present in the queue.":"%s already present in the queue.","File: %s":"File: %s","b":"b","Uploaded %d/%d files":"Uploaded %d/%d files","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"%d files queued","File: %s, size: %d, max file size: %d":"File: %s, size: %d, max file size: %d","Drag files here.":"Drag files here.","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"File count error.","File extension error.":"File extension error.","Error: File too large:":"Error: File too large:","Add Files":"Add Files"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/es.js b/themes/default/js/plugins/plupload/i18n/es.js new file mode 100644 index 000000000..72b0367ed --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/es.js @@ -0,0 +1,2 @@ +// Spanish (es) +plupload.addI18n({"Stop Upload":"Detener Subida.","Upload URL might be wrong or doesn't exist.":"URL de carga inexistente.","tb":"TB","Size":"Tamaño","Close":"Cerrar","Init error.":"Error de inicialización.","Add files to the upload queue and click the start button.":"Agregue archivos a la lista de subida y pulse clic en el botón de Iniciar carga","Filename":"Nombre de archivo","Image format either wrong or not supported.":"Formato de imagen no soportada.","Status":"Estado","HTTP Error.":"Error de HTTP.","Start Upload":"Iniciar carga","mb":"MB","kb":"KB","Duplicate file error.":"Error, archivo duplicado","File size error.":"Error de tamaño de archivo.","N/A":"No disponible","gb":"GB","Error: Invalid file extension:":"Error: Extensión de archivo inválida:","Select files":"Elija archivos","%s already present in the queue.":"%s ya se encuentra en la lista.","File: %s":"Archivo: %s","b":"B","Uploaded %d/%d files":"Subidos %d/%d archivos","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Se aceptan sólo %d archivo(s) al tiempo. Más, no se tienen en cuenta.","%d files queued":"%d archivos en cola.","File: %s, size: %d, max file size: %d":"Archivo: %s, tamaño: %d, tamaño máximo de archivo: %d","Drag files here.":"Arrastre archivos aquí","Runtime ran out of available memory.":"No hay memoria disponible.","File count error.":"Error en contador de archivos.","File extension error.":"Error de extensión de archivo.","Error: File too large:":"Error: archivo demasiado grande:","Add Files":"Agregar archivos"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/et.js b/themes/default/js/plugins/plupload/i18n/et.js new file mode 100644 index 000000000..3e145b10e --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/et.js @@ -0,0 +1,2 @@ +// Estonian (et) +plupload.addI18n({"Stop Upload":"Stop Upload","Upload URL might be wrong or doesn't exist.":"Üleslaadimise URL võib olla vale või seda pole.","tb":"","Size":"Suurus","Close":"Sulge","Init error.":"Lähtestamise viga.","Add files to the upload queue and click the start button.":"Lisa failid üleslaadimise järjekorda ja klõpsa alustamise nupule.","Filename":"Failinimi","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"Olek","HTTP Error.":"HTTP ühenduse viga.","Start Upload":"Start Upload","mb":"","kb":"","Duplicate file error.":"","File size error.":"Failisuuruse viga.","N/A":"N/A","gb":"","Error: Invalid file extension:":"Error: Invalid file extension:","Select files":"Vali faile","%s already present in the queue.":"","File: %s":"Fail: %s","b":"","Uploaded %d/%d files":"Üles laaditud %d/%d","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Üleslaadimise element saab vastu võtta ainult %d faili ühe korraga. Ülejäänud failid jäetakse laadimata.","%d files queued":"Järjekorras on %d faili","File: %s, size: %d, max file size: %d":"","Drag files here.":"Lohista failid siia.","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"Failide arvu viga.","File extension error.":"Faililaiendi viga.","Error: File too large:":"Error: File too large:","Add Files":"Add Files"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/fa.js b/themes/default/js/plugins/plupload/i18n/fa.js new file mode 100644 index 000000000..e3246cc95 --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/fa.js @@ -0,0 +1,2 @@ +// Persian (fa) +plupload.addI18n({"Stop Upload":"توقف انتقال","Upload URL might be wrong or doesn't exist.":"Upload URL might be wrong or doesn't exist.","tb":"ترابایت","Size":"سایز","Close":"بستن","Init error.":"خطا در استارت اسکریپت","Add files to the upload queue and click the start button.":"اضافه کنید فایل ها را به صف آپلود و دکمه شروع را کلیک کنید.","Filename":"نام فایل","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"وضعیت","HTTP Error.":"HTTP خطای","Start Upload":"شروع انتقال","mb":"مگابایت","kb":"کیلوبایت","Duplicate file error.":"خطای فایل تکراری","File size error.":"خطای سایز فایل","N/A":"N/A","gb":"گیگابایت","Error: Invalid file extension:":"Error: Invalid file extension:","Select files":"انتخاب فایل","%s already present in the queue.":"%s در لیست آپلود وجود دارد.","File: %s":" فایل ها : %s","b":"بایت","Uploaded %d/%d files":"منتقل شد %d/%d از فایلها","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"عنصر بارگذار فقط %d فایل رو در یک زمان می پذیرد. سایر فایل ها مجرد از این موضوع هستند.","%d files queued":"%d فایل در صف","File: %s, size: %d, max file size: %d":"فایل: %s, اندازه: %d, محدودیت اندازه فایل: %d","Drag files here.":"بکشید فایل ها رو به اینجا","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"خطای تعداد فایل","File extension error.":"خطا پیشوند فایل","Error: File too large:":"Error: File too large:","Add Files":"افزودن فایل"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/fi.js b/themes/default/js/plugins/plupload/i18n/fi.js new file mode 100644 index 000000000..e16ebecf8 --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/fi.js @@ -0,0 +1,2 @@ +// Finnish (fi) +plupload.addI18n({"Stop Upload":"Pysäytä lähetys","Upload URL might be wrong or doesn't exist.":"Lähetyksen URL-osoite saattaa olla väärä tai sitä ei ole olemassa.","tb":"TB","Size":"Koko","Close":"Sulje","Init error.":"Init virhe.","Add files to the upload queue and click the start button.":"Lisää tiedostoja lähetysjonoon ja klikkaa aloita-nappia.","Filename":"Tiedostonimi","Image format either wrong or not supported.":"Kuvaformaatti on joko väärä tai ei tuettu.","Status":"Tila","HTTP Error.":"HTTP-virhe.","Start Upload":"Aloita lähetys","mb":"MB","kb":"kB","Duplicate file error.":"Tuplatiedostovirhe.","File size error.":"Tiedostokokovirhe.","N/A":"N/A","gb":"GB","Error: Invalid file extension:":"Virhe: Virheellinen tiedostopääte:","Select files":"Valitse tiedostoja","%s already present in the queue.":"%s on jo jonossa.","File: %s":"Tiedosto: %s","b":"B","Uploaded %d/%d files":"Lähetetty %d/%d tiedostoa","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Vain %d tiedosto(a) voidaan lähettää kerralla. Ylimääräiset tiedostot ohitettiin.","%d files queued":"%d tiedostoa jonossa","File: %s, size: %d, max file size: %d":"Tiedosto: %s, koko: %d, suurin sallittu tiedostokoko: %d","Drag files here.":"Raahaa tiedostot tähän.","Runtime ran out of available memory.":"Toiminnon käytettävissä oleva muisti loppui kesken.","File count error.":"Tiedostolaskentavirhe.","File extension error.":"Tiedostopäätevirhe.","Error: File too large:":"Virhe: Liian suuri tiedosto:","Add Files":"Lisää tiedostoja"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/fr.js b/themes/default/js/plugins/plupload/i18n/fr.js new file mode 100644 index 000000000..7f2a765b4 --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/fr.js @@ -0,0 +1,2 @@ +// French (fr) +plupload.addI18n({"Stop Upload":"Arrêter l'envoi.","Upload URL might be wrong or doesn't exist.":"L'URL d'envoi est soit erronée soit n'existe pas.","tb":"To","Size":"Taille","Close":"Fermer","Init error.":"Erreur d'initialisation.","Add files to the upload queue and click the start button.":"Ajoutez des fichiers à la file d'attente de téléchargement et appuyez sur le bouton 'Démarrer l'envoi'","Filename":"Nom du fichier","Image format either wrong or not supported.":"Le format d'image est soit erroné soit pas géré.","Status":"État","HTTP Error.":"Erreur HTTP.","Start Upload":"Démarrer l'envoi","mb":"Mo","kb":"Ko","Duplicate file error.":"Erreur: Fichier déjà sélectionné.","File size error.":"Erreur de taille de fichier.","N/A":"Non applicable","gb":"Go","Error: Invalid file extension:":"Erreur: Extension de fichier non valide:","Select files":"Sélectionnez les fichiers","%s already present in the queue.":"%s déjà présent dans la file d'attente.","File: %s":"Fichier: %s","b":"o","Uploaded %d/%d files":"%d fichiers sur %d ont été envoyés","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Que %d fichier(s) peuvent être envoyé(s) à la fois. Les fichiers supplémentaires ont été ignorés.","%d files queued":"%d fichiers en attente","File: %s, size: %d, max file size: %d":"Fichier: %s, taille: %d, taille max. d'un fichier: %d","Drag files here.":"Déposez les fichiers ici.","Runtime ran out of available memory.":"Le traitement a manqué de mémoire disponible.","File count error.":"Erreur: Nombre de fichiers.","File extension error.":"Erreur d'extension de fichier","Error: File too large:":"Erreur: Fichier trop volumineux:","Add Files":"Ajouter des fichiers"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/he.js b/themes/default/js/plugins/plupload/i18n/he.js new file mode 100644 index 000000000..710334780 --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/he.js @@ -0,0 +1,2 @@ +// Hebrew (he) +plupload.addI18n({"Stop Upload":"בטל העלאה","Upload URL might be wrong or doesn't exist.":"כתובת URL שגויה או לא קיימת.","tb":"tb","Size":"גודל","Close":"סגור","Init error.":"שגיאת איתחול","Add files to the upload queue and click the start button.":"הוסף קבצים לרשימה ולחץ על כפתור שליחה להתחלת פעולות העלאה","Filename":"שם קובץ","Image format either wrong or not supported.":"תמונה פגומה או סוג תמונה לא נתמך","Status":"אחוז","HTTP Error.":"שגיאת פרוטוקול","Start Upload":"שליחה","mb":"MB","kb":"KB","Duplicate file error.":"קובץ כפול","File size error.":"גודל קובץ חורג מהמותר","N/A":"שגיאה","gb":"GB","Error: Invalid file extension:":"שגיאה: סוג קובץ לא נתמך:","Select files":"בחר קבצים","%s already present in the queue.":"%sקובץ נמצא כבר ברשימת הקבצים.","File: %s":"קובץ: %s","b":"B","Uploaded %d/%d files":"מעלה: %d/%d","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"אלמנטי ההעלאה מקבלים רק %d קובץ(ים) בפעם אחת. קבצים נוספים הוסרו.","%d files queued":"%d קבצים נותרו","File: %s, size: %d, max file size: %d":"קובץ: %s, גודל: %d, גודל מקסימלי: %d","Drag files here.":"גרור קבצים לכאן","Runtime ran out of available memory.":"שגיאת מחסור בזיכרון","File count error.":"שגיאת מספר קבצים","File extension error.":"קובץ זה לא נתמך","Error: File too large:":"שגיאה: קובץ חורג מהגודל המותר:","Add Files":"הוסף קבצים"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/hr.js b/themes/default/js/plugins/plupload/i18n/hr.js new file mode 100644 index 000000000..626dded43 --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/hr.js @@ -0,0 +1,2 @@ +// Croatian (hr) +plupload.addI18n({"Stop Upload":"Zaustavi upload.","Upload URL might be wrong or doesn't exist.":"Upload URL might be wrong or doesn't exist.","tb":"tb","Size":"Veličina","Close":"Zatvori","Init error.":"Greška inicijalizacije.","Add files to the upload queue and click the start button.":"Dodajte datoteke u listu i kliknite Upload.","Filename":"Ime datoteke","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"Status","HTTP Error.":"HTTP greška.","Start Upload":"Pokreni upload.","mb":"mb","kb":"kb","Duplicate file error.":"Pogreška dvostruke datoteke.","File size error.":"Greška veličine datoteke.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Pogreška: Nevažeći nastavak datoteke:","Select files":"Odaberite datoteke:","%s already present in the queue.":"%s je već prisutan u listi čekanja.","File: %s":"Datoteka: %s","b":"b","Uploaded %d/%d files":"Uploadano %d/%d datoteka","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"%d datoteka na čekanju.","File: %s, size: %d, max file size: %d":"Datoteka: %s, veličina: %d, maksimalna veličina: %d","Drag files here.":"Dovucite datoteke ovdje","Runtime ran out of available memory.":"Runtime aplikaciji je ponestalo memorije.","File count error.":"Pogreška u broju datoteka.","File extension error.":"Pogreška u nastavku datoteke.","Error: File too large:":"Pogreška: Datoteka je prevelika:","Add Files":"Dodaj datoteke"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/hu.js b/themes/default/js/plugins/plupload/i18n/hu.js new file mode 100644 index 000000000..ad233566f --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/hu.js @@ -0,0 +1,2 @@ +// Hungarian (hu) +plupload.addI18n({"Stop Upload":"Feltöltés leállítása","Upload URL might be wrong or doesn't exist.":"A feltöltő URL hibás vagy nem létezik.","tb":"TB","Size":"Méret","Close":"Bezárás","Init error.":"Init hiba.","Add files to the upload queue and click the start button.":"A fájlok feltöltési sorhoz való hozzáadása után az Indítás gombra kell kattintani.","Filename":"Fájlnév","Image format either wrong or not supported.":"Rossz vagy nem támogatott képformátum.","Status":"Állapot","HTTP Error.":"HTTP-hiba.","Start Upload":"Feltöltés indítása","mb":"MB","kb":"kB","Duplicate file error.":"Duplikáltfájl-hiba.","File size error.":"Hibás fájlméret.","N/A":"Nem elérhető","gb":"GB","Error: Invalid file extension:":"Hiba: érvénytelen fájlkiterjesztés:","Select files":"Fájlok kiválasztása","%s already present in the queue.":"%s már szerepel a listában.","File: %s":"Fájl: %s","b":"b","Uploaded %d/%d files":"Feltöltött fájlok: %d/%d","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"A feltöltés egyszerre csak %d fájlt fogad el, a többi fájl nem lesz feltöltve.","%d files queued":"%d fájl sorbaállítva","File: %s, size: %d, max file size: %d":"Fájl: %s, méret: %d, legnagyobb fájlméret: %d","Drag files here.":"Ide lehet húzni a fájlokat.","Runtime ran out of available memory.":"Futásidőben elfogyott a rendelkezésre álló memória.","File count error.":"A fájlok számával kapcsolatos hiba.","File extension error.":"Hibás fájlkiterjesztés.","Error: File too large:":"Hiba: a fájl túl nagy:","Add Files":"Fájlok hozzáadása"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/hy.js b/themes/default/js/plugins/plupload/i18n/hy.js new file mode 100644 index 000000000..c13a9653b --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/hy.js @@ -0,0 +1,2 @@ +// Armenian (hy) +plupload.addI18n({"Stop Upload":"Կանգնեցնել","Upload URL might be wrong or doesn't exist.":"Ավեցաված URL-ը սխալ է կամ գոյություն չունի։","tb":"տբ","Size":"Չափ","Close":"Փակել","Init error.":"Ստեղծման սխալ","Add files to the upload queue and click the start button.":"Ավելացրեք ֆայլեր ցուցակում և սեղմեք \"Վերբեռնել\"։","Filename":"Ֆայլի անուն","Image format either wrong or not supported.":"Նկարի ֆորմատը սխալ է կամ չի ընդունվում։","Status":"","HTTP Error.":"HTTP սխալ","Start Upload":"Վերբեռնել","mb":"մբ","kb":"կբ","Duplicate file error.":"Ֆայլի կրկնման սխալ","File size error.":"Ֆայլի չափի սխալ","N/A":"N/A","gb":"գբ","Error: Invalid file extension:":"Սխալ։ Ֆայլի ընդլայնումը սխալ է։","Select files":"Ընտրեք ֆայլերը","%s already present in the queue.":"%s ֆայլը արդեն ավելացված է ցուցակում.","File: %s":"Ֆայլ: %s","b":"բ","Uploaded %d/%d files":"Վերբեռնվել են %d/%d ֆայլերը","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"","%d files queued":"ցուցակում կա %d ֆայլ","File: %s, size: %d, max file size: %d":"Ֆայլ: %s, չափ: %d, ֆայլի մաքսիմում չափ: %d","Drag files here.":"Տեղափոխեք ֆայլերը այստեղ","Runtime ran out of available memory.":"","File count error.":"Ֆայլերի քանակի սխալ","File extension error.":"Ֆայլի ընդլայնման սխալ","Error: File too large:":"Սխալ։ Ֆայլի չափը մեծ է։","Add Files":"Ավելացնել ֆայլեր"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/id.js b/themes/default/js/plugins/plupload/i18n/id.js new file mode 100644 index 000000000..2921c27d1 --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/id.js @@ -0,0 +1,2 @@ +// Indonesian (id) +plupload.addI18n({"Stop Upload":"Hentikan Upload","Upload URL might be wrong or doesn't exist.":"Alamat URL untuk upload tidak benar atau tidak ada","tb":"tb","Size":"Ukuran","Close":"Tutup","Init error.":"Kesalahan pada Init","Add files to the upload queue and click the start button.":"Tambahkan file kedalam antrian upload dan klik tombol Mulai","Filename":"Nama File","Image format either wrong or not supported.":"Kesalahan pada jenis gambar atau jenis file tidak didukung","Status":"Status","HTTP Error.":"HTTP Bermasalah","Start Upload":"Mulai Upload","mb":"mb","kb":"kb","Duplicate file error.":"Terjadi duplikasi file","File size error.":"Kesalahan pada ukuran file","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Kesalahan: Ekstensi file tidak dikenal","Select files":"Pilih file","%s already present in the queue.":"%s sudah ada dalam daftar antrian","File: %s":"File: %s","b":"b","Uploaded %d/%d files":"File terupload %d/%d","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Tempat untuk upload hanya menerima %d file(s) dalam setiap upload. File lainnya tidak akan disertakan","%d files queued":"%d file dalam antrian","File: %s, size: %d, max file size: %d":"File: %s, ukuran: %d, maksimum ukuran file: %d","Drag files here.":"Tarik file kesini","Runtime ran out of available memory.":"Tidak cukup memori","File count error.":"Kesalahan pada jumlah file","File extension error.":"Kesalahan pada ekstensi file","Error: File too large:":"Kesalahan: File terlalu besar","Add Files":"Tambah File"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/it.js b/themes/default/js/plugins/plupload/i18n/it.js new file mode 100644 index 000000000..66c9f9df0 --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/it.js @@ -0,0 +1,2 @@ +// Italian (it) +plupload.addI18n({"Stop Upload":"Ferma Upload","Upload URL might be wrong or doesn't exist.":"URL di Upload errata o non esistente","tb":"tb","Size":"Dimensione","Close":"Chiudi","Init error.":"Errore inizializzazione.","Add files to the upload queue and click the start button.":"Aggiungi i file alla coda di caricamento e clicca il pulsante di avvio.","Filename":"Nome file","Image format either wrong or not supported.":"Formato immagine errato o non supportato.","Status":"Stato","HTTP Error.":"Errore HTTP.","Start Upload":"Inizia Upload","mb":"mb","kb":"kb","Duplicate file error.":"Errore file duplicato.","File size error.":"Errore dimensione file.","N/A":"N/D","gb":"gb","Error: Invalid file extension:":"Errore: Estensione file non valida:","Select files":"Seleziona i files","%s already present in the queue.":"%s già presente nella coda.","File: %s":"File: %s","b":"byte","Uploaded %d/%d files":"Caricati %d/%d file","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"%d file in coda","File: %s, size: %d, max file size: %d":"File: %s, dimensione: %d, dimensione max file: %d","Drag files here.":"Trascina i files qui.","Runtime ran out of available memory.":"Runtime ha esaurito la memoria disponibile.","File count error.":"File count error.","File extension error.":"Errore estensione file.","Error: File too large:":"Errore: File troppo grande:","Add Files":"Aggiungi file"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/ja.js b/themes/default/js/plugins/plupload/i18n/ja.js new file mode 100644 index 000000000..28486992e --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/ja.js @@ -0,0 +1,2 @@ +// Japanese (ja) +plupload.addI18n({"Stop Upload":"アップロード停止","Upload URL might be wrong or doesn't exist.":"アップロード先の URL が存在しません","tb":"TB","Size":"サイズ","Close":"閉じる","Init error.":"イニシャライズエラー","Add files to the upload queue and click the start button.":"ファイルをアップロードキューに追加してスタートボタンをクリックしてください","Filename":"ファイル名","Image format either wrong or not supported.":"画像形式が間違っているかサポートされていません","Status":"ステータス","HTTP Error.":"HTTP エラー","Start Upload":"アップロード開始","mb":"MB","kb":"KB","Duplicate file error.":"重複ファイルエラー","File size error.":"ファイルサイズエラー","N/A":"N/A","gb":"GB","Error: Invalid file extension:":"エラー: ファイルの拡張子が無効です:","Select files":"ファイル選択","%s already present in the queue.":"%s 既にキューに存在しています","File: %s":"ファイル: %s","b":"B","Uploaded %d/%d files":"アップロード中 %d/%d ファイル","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"アップロード可能なファイル数は %d です 余分なファイルは削除されました","%d files queued":"%d ファイルが追加されました","File: %s, size: %d, max file size: %d":"ファイル: %s, サイズ: %d, 最大ファイルサイズ: %d","Drag files here.":"ここにファイルをドラッグ","Runtime ran out of available memory.":"ランタイムが使用するメモリが不足しました","File count error.":"ファイル数エラー","File extension error.":"ファイル拡張子エラー","Error: File too large:":"エラー: ファイルが大きすぎます:","Add Files":"ファイルを追加"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/ka.js b/themes/default/js/plugins/plupload/i18n/ka.js new file mode 100644 index 000000000..b1a1fa9d6 --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/ka.js @@ -0,0 +1,2 @@ +// Georgian (ka) +plupload.addI18n({"Stop Upload":"ატვირთვის შეჩერება","Upload URL might be wrong or doesn't exist.":"ატვირთვის მისამართი არასწორია ან არ არსებობს.","tb":"ტბ","Size":"ზომა","Close":"დავხუროთ","Init error.":"ინიციალიზაციის შეცდომა.","Add files to the upload queue and click the start button.":"დაამატეთ ფაილები და დააჭირეთ ღილაკს - ატვირთვა.","Filename":"ფაილის სახელი","Image format either wrong or not supported.":"ფაილის ფორმატი არ არის მხარდაჭერილი ან არასწორია.","Status":"სტატუსი","HTTP Error.":"HTTP შეცდომა.","Start Upload":"ატვირთვა","mb":"მბ","kb":"კბ","Duplicate file error.":"ესეთი ფაილი უკვე დამატებულია.","File size error.":"ფაილის ზომა დაშვებულზე დიდია.","N/A":"N/A","gb":"გბ","Error: Invalid file extension:":"შეცდომა: ფაილს აქვს არასწორი გაფართოება.","Select files":"ფაილების მონიშვნა","%s already present in the queue.":"%s უკვე დამატებულია.","File: %s":"ფაილი: %s","b":"ბ","Uploaded %d/%d files":"ატვირთულია %d/%d ფაილი","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"ერთდროულად დაშვებულია მხოლოდ %d ფაილის დამატება.","%d files queued":"რიგშია %d ფაილი","File: %s, size: %d, max file size: %d":"ფაილი: %s, ზომა: %d, მაქსიმალური დაშვებული ზომა: %d","Drag files here.":"ჩააგდეთ ფაილები აქ.","Runtime ran out of available memory.":"ხელმისაწვდომი მეხსიერება გადაივსო.","File count error.":"აღმოჩენილია ზედმეტი ფაილები.","File extension error.":"ფაილის ფორმატი დაშვებული არ არის.","Error: File too large:":"შეცდომა: ფაილი ზედმეტად დიდია.","Add Files":"დაამატეთ ფაილები"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/kk.js b/themes/default/js/plugins/plupload/i18n/kk.js new file mode 100644 index 000000000..344922a88 --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/kk.js @@ -0,0 +1,2 @@ +// Kazakh (kk) +plupload.addI18n({"Stop Upload":"Жүктеуді тоқтату","Upload URL might be wrong or doesn't exist.":"Жүктеуді қабылдаушы URL қате не мүлдем көрсетілмеген.","tb":"тб","Size":"Өлшемі","Close":"Жабу","Init error.":"Инициализация қатесі.","Add files to the upload queue and click the start button.":"Жүктеу кезегіне файлдар қосып, Бастау кнопкасын басыңыз.","Filename":"Файл аты","Image format either wrong or not supported.":"Сурет форматы қате немесе оның қолдауы жоқ.","Status":"Күйі","HTTP Error.":"HTTP қатесі.","Start Upload":"Жүктеуді бастау","mb":"мб","kb":"кб","Duplicate file error.":"Файл қайталамасының қатесі.","File size error.":"Файл өлшемінің қатесі.","N/A":"Қ/Ж","gb":"гб","Error: Invalid file extension:":"Қате: Файл кеңейтілуі қате:","Select files":"Файлдар таңдаңыз","%s already present in the queue.":"%s файлы кезекте бұрыннан бар.","File: %s":"Файл: %s","b":"б","Uploaded %d/%d files":"Жүктелген: %d/%d файл","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Жүктеу элементі бір кезде %d файл ғана жүктей алады. Артық файлдар жүктелмейді.","%d files queued":"%d файл кезекке қойылды","File: %s, size: %d, max file size: %d":"Файл: %s, өлшемі: %d, макс. файл өлшемі: %d","Drag files here.":"Файлдарды мына жерге тастаңыз.","Runtime ran out of available memory.":"Орындау кезінде жады жетпей қалды.","File count error.":"Файл санының қатесі.","File extension error.":"Файл кеңейтілуінің қатесі.","Error: File too large:":"Қате: Файл мөлшері тым үлкен:","Add Files":"Файл қосу"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/km.js b/themes/default/js/plugins/plupload/i18n/km.js new file mode 100644 index 000000000..c77cea131 --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/km.js @@ -0,0 +1,2 @@ +// Khmer (km) +plupload.addI18n({"Stop Upload":"បញ្ឈប់​ការ​ផ្ទុក​ឡើង","Upload URL might be wrong or doesn't exist.":"URL ផ្ទុក​ឡើង​អាច​ខុស ឬ​ក៏​គ្មាន។","tb":"tb","Size":"ទំហំ","Close":"បិទ","Init error.":"កំហុស Init។","Add files to the upload queue and click the start button.":"បន្ថែម​ឯកសារ​ទៅ​ក្នុង​ជួរ​លំដាប់​ផ្ទុក​ឡើង ហើយ​ចុច​ប៊ូតុង​ចាប់​ផ្ដើម។","Filename":"ឈ្មោះ​ឯកសារ","Image format either wrong or not supported.":"ទ្រង់​ទ្រាយ​រូបភាព​អាច​ខុស ឬ​ក៏​មិន​ស្គាល់​តែ​ម្ដង។","Status":"ស្ថានភាព","HTTP Error.":"កំហុស HTTP ។","Start Upload":"ចាប់​ផ្ដើម​ផ្ទុក​ឡើង","mb":"mb","kb":"kb","Duplicate file error.":"កំហុស​ឯកសារ​ស្ទួន​គ្នា។","File size error.":"កំហុស​ទំហំ​ឯកសារ។","N/A":"គ្មាន","gb":"gb","Error: Invalid file extension:":"កំហុស៖ កន្ទុយ​ឯកសារ​មិន​ត្រឹម​ត្រូវ៖","Select files":"ជ្រើស​ឯកសារ","%s already present in the queue.":"មាន %s នៅ​ក្នុង​ជួរ​លំដាប់​ហើយ។","File: %s":"ឯកសារ៖ %s","b":"b","Uploaded %d/%d files":"បាន​ផ្ទុក​ឡើង​ឯកសារ %d/%d","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"ការ​ផ្ទុក​ឡើង​ទទួល​ឯកសារ​បាន​តែ %d ប៉ុណ្ណោះ​ក្នុង​ពេល​តែ​មួយ។ ឯកសារ​ផ្សេង​ទៀត​នឹង​ត្រូវ​ដក​ចេញ។","%d files queued":"បាន​ដាក់​ឯកសារ %d បន្ត​គ្នា","File: %s, size: %d, max file size: %d":"ឯកសារ៖ %s, size: %d, ទំហំ​ឯកសារ​អតិបរមា៖ %d","Drag files here.":"អូស​ឯកសារ​មក​ទីនេះ។","Runtime ran out of available memory.":"ពេល​ដំណើរ​ការ​អស់​អង្គ​ចងចាំ​ទំនេរ​ហើយ។","File count error.":"កំហុស​ការ​រាប់​ឯកសារ។","File extension error.":"កំហុស​កន្ទុយ​ឯកសារ។","Error: File too large:":"កំហុស៖ ឯកសារ​ធំ​ពេក៖","Add Files":"បន្ថែម​ឯកសារ"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/ko.js b/themes/default/js/plugins/plupload/i18n/ko.js new file mode 100644 index 000000000..80c656409 --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/ko.js @@ -0,0 +1,2 @@ +// Korean (ko) +plupload.addI18n({"Stop Upload":"업로드 중지","Upload URL might be wrong or doesn't exist.":"업로드할 URL이 존재하지 않습니다.","tb":"tb","Size":"크기","Close":"닫기","Init error.":"초기화 오류.","Add files to the upload queue and click the start button.":"파일을 업로드 큐에 추가한 후 시작 버튼을 클릭하십시오.","Filename":"파일명","Image format either wrong or not supported.":"지원되지 않는 이미지 형식입니다.","Status":"상태","HTTP Error.":"HTTP 오류.","Start Upload":"업로드 시작","mb":"mb","kb":"kb","Duplicate file error.":"파일 중복 오류.","File size error.":"파일 크기 오류.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"오류: 허용되지 않은 확장자입니다.","Select files":"파일 선택","%s already present in the queue.":"%s 파일이 이미 대기열에 존재합니다.","File: %s":"파일: %s","b":"b","Uploaded %d/%d files":"%d / %d 파일 업로드 완료","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"업로드 가능한 파일의 수는 %d 입니다. 불필요한 파일은 삭제되었습니다.","%d files queued":"%d 파일이 추가됨","File: %s, size: %d, max file size: %d":"파일: %s, 크기: %d, 최대 파일 크기: %d","Drag files here.":"이곳에 파일을 드래그 하세요.","Runtime ran out of available memory.":"런타임 메모리가 부족합니다.","File count error.":"파일 갯수 오류.","File extension error.":"파일 확장자 오류.","Error: File too large:":"오류: 파일 크기가 너무 큽니다.","Add Files":"파일 추가"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/lt.js b/themes/default/js/plugins/plupload/i18n/lt.js new file mode 100644 index 000000000..b24e65b03 --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/lt.js @@ -0,0 +1,2 @@ +// Lithuanian (lt) +plupload.addI18n({"Stop Upload":"Stabdyti įkėlimą","Upload URL might be wrong or doesn't exist.":"Klaidinga arba neegzistuojanti įkėlimo nuoroda.","tb":"tb","Size":"Dydis","Close":"Uždaryti","Init error.":"Įkrovimo klaida.","Add files to the upload queue and click the start button.":"Pridėkite bylas į įkėlimo eilę ir paspauskite starto mygtuką.","Filename":"Bylos pavadinimas","Image format either wrong or not supported.":"Paveiksliuko formatas klaidingas arba nebepalaikomas.","Status":"Statusas","HTTP Error.":"HTTP klaida.","Start Upload":"Pradėti įkėlimą","mb":"mb","kb":"kb","Duplicate file error.":"Pasikartojanti byla.","File size error.":"Netinkamas bylos dydis.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Klaida: Netinkamas bylos plėtinys:","Select files":"Žymėti bylas","%s already present in the queue.":"%s jau yra eilėje.","File: %s":"Byla: %s","b":"b","Uploaded %d/%d files":"Įkelta bylų: %d/%d","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Vienu metu galima įkelti tik %d bylas(ų). Papildomos bylos buvo pašalintos.","%d files queued":"%d bylų eilėje","File: %s, size: %d, max file size: %d":"Byla: %s, dydis: %d, galimas dydis: %d","Drag files here.":"Padėti bylas čia.","Runtime ran out of available memory.":"Išeikvota darbinė atmintis.","File count error.":"Netinkamas bylų kiekis.","File extension error.":"Netinkamas pletinys.","Error: File too large:":"Klaida: Byla per didelė:","Add Files":"Pridėti bylas"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/lv.js b/themes/default/js/plugins/plupload/i18n/lv.js new file mode 100644 index 000000000..a0e7be75c --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/lv.js @@ -0,0 +1,2 @@ +// Latvian (lv) +plupload.addI18n({"Stop Upload":"Apturēt augšupielādi","Upload URL might be wrong or doesn't exist.":"Augšupielādes saite neeksistē vai ir nepareiza.","tb":"terrabaiti","Size":"Izmērs","Close":"Aizvērt","Init error.":"Inicializācijas kļūda.","Add files to the upload queue and click the start button.":"Pieveinojiet failus rindai un klikšķiniet uz pogu \"Sākt augšupielādi\".","Filename":"Faila nosaukums","Image format either wrong or not supported.":"Attēla formāts ir nepareizs vai arī netiek atbalstīts.","Status":"Statuss","HTTP Error.":"HTTP kļūda.","Start Upload":"Sākt augšupielādi","mb":"megabaiti","kb":"kilobaiti","Duplicate file error.":"Atkārtota faila kļūda","File size error.":"Faila izmēra kļūda.","N/A":"N/A","gb":"gigabaiti","Error: Invalid file extension:":"Kļūda: Nepareizs faila paplašinājums:","Select files":"Izvēlieties failus","%s already present in the queue.":"%s jau ir atrodams rindā.","File: %s":"Fails: %s","b":"baiti","Uploaded %d/%d files":"Augšupielādēti %d/%d faili","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Iespējams ielādēt tikai %d failus vienā reizē. Atlikušie faili netika pievienoti","%d files queued":"%d faili pievienoti rindai","File: %s, size: %d, max file size: %d":"Fails: %s, izmērs: %d, max faila izmērs: %d","Drag files here.":"Ievelciet failus šeit","Runtime ran out of available memory.":"Pietrūkst izmantojamās atmiņas.","File count error.":"Failu skaita kļūda","File extension error.":"Faila paplašinājuma kļūda.","Error: File too large:":"Kļūda: Fails pārāk liels:","Add Files":"Pievienot failus"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/mn.js b/themes/default/js/plugins/plupload/i18n/mn.js new file mode 100644 index 000000000..4a379b084 --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/mn.js @@ -0,0 +1,2 @@ +// Mongolian (mn) +plupload.addI18n({"Stop Upload":"","Upload URL might be wrong or doesn't exist.":"","tb":"","Size":"","Close":"","Init error.":"","Add files to the upload queue and click the start button.":"","Filename":"","Image format either wrong or not supported.":"","Status":"","HTTP Error.":"","Start Upload":"","mb":"","kb":"","Duplicate file error.":"","File size error.":"","N/A":"","gb":"","Error: Invalid file extension:":"","Select files":"","%s already present in the queue.":"","File: %s":"","b":"","Uploaded %d/%d files":"","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"","%d files queued":"","File: %s, size: %d, max file size: %d":"","Drag files here.":"","Runtime ran out of available memory.":"","File count error.":"","File extension error.":"","Error: File too large:":"","Add Files":""}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/ms.js b/themes/default/js/plugins/plupload/i18n/ms.js new file mode 100644 index 000000000..dffb0ae18 --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/ms.js @@ -0,0 +1,2 @@ +// Malay (ms) +plupload.addI18n({"Stop Upload":"Berhenti Muat naik","Upload URL might be wrong or doesn't exist.":"URL muat naik mungkin salah atau tidak wujud.","tb":"tb","Size":"saiz","Close":"Tutup","Init error.":"Ralat perlaksanaan.","Add files to the upload queue and click the start button.":"Tambah fail ke dalam giliran muat naik dan klik butang Muat Naik.","Filename":"Nama fail","Image format either wrong or not supported.":"Format imej sama ada salah atau tidak disokong.","Status":"Status","HTTP Error.":"Ralat HTTP.","Start Upload":"Muat Naik","mb":"mb","kb":"kb","Duplicate file error.":"Ralat menggandakan fail.","File size error.":"Ralat saiz fail.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Ralat: Sambungan fail tidak sah:","Select files":"Pilih fail","%s already present in the queue.":"%s telah ada dalam barisan.","File: %s":"Fail: %s","b":"b","Uploaded %d/%d files":"%d/%d telah dimuat naik","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Element muat naik hanya menerima %d fail(-fail) pada satu masa. Fail tambahan telah digugurkan.","%d files queued":"%d fail dalam barisan","File: %s, size: %d, max file size: %d":"Fail: %s, saiz: %d, saiz maks fail: %d","Drag files here.":"Seret fail ke sini.","Runtime ran out of available memory.":"Ruang ingatan masa larian tidak mencukupi.","File count error.":"Ralat bilangan fail.","File extension error.":"Ralat sambungan fail.","Error: File too large:":"Ralat: Fail terlalu bersar:","Add Files":"Tambah Fail"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/nl.js b/themes/default/js/plugins/plupload/i18n/nl.js new file mode 100644 index 000000000..9ff3c1c6f --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/nl.js @@ -0,0 +1,2 @@ +// Dutch (nl) +plupload.addI18n({"Stop Upload":"Stop Upload","Upload URL might be wrong or doesn't exist.":"Upload URL is verkeerd of bestaat niet.","tb":"tb","Size":"Grootte","Close":"Sluiten","Init error.":"Initialisatie error.","Add files to the upload queue and click the start button.":"Voeg bestanden toe aan de wachtrij en druk op 'Start'.","Filename":"Bestandsnaam","Image format either wrong or not supported.":"bestandsextensie is verkeerd of niet ondersteund.","Status":"Status","HTTP Error.":"HTTP Error.","Start Upload":"Start Upload","mb":"mb","kb":"kb","Duplicate file error.":"Bestand bestaat al.","File size error.":"Bestandsgrootte error.","N/A":"Niet beschikbaar","gb":"gb","Error: Invalid file extension:":"Error: Ongeldige bestandsextensie:","Select files":"Selecteer bestand(en):","%s already present in the queue.":"%s is al aan de wachtrij toegevoegd.","File: %s":"Bestand: %s","b":"b","Uploaded %d/%d files":"%d/%d bestanden ge-upload","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload accepteert alleen %d bestand(en) tegelijk. Extra bestanden zijn verwijderd.","%d files queued":"%d bestand(en) in de wachtrij","File: %s, size: %d, max file size: %d":"Bestand: %s, grootte: %d, maximale bestandsgrootte: %d","Drag files here.":"Sleep bestanden hierheen.","Runtime ran out of available memory.":"Het maximum bruikbare geheugen is overschreden.","File count error.":"Teveel bestand(en) error.","File extension error.":"Ongeldig bestandsextensie.","Error: File too large:":"Error: Bestand te groot:","Add Files":"Bestand(en) toevoegen"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/pl.js b/themes/default/js/plugins/plupload/i18n/pl.js new file mode 100644 index 000000000..05a5b295f --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/pl.js @@ -0,0 +1,2 @@ +// Polish (pl) +plupload.addI18n({"Stop Upload":"Przerwij transfer.","Upload URL might be wrong or doesn't exist.":"Adres URL moze bys nieprawidlowy lub moze nieistniec","tb":"tb","Size":"Rozmiar","Close":"Zamknij","Init error.":"Błąd inicjalizacji.","Add files to the upload queue and click the start button.":"Dodaj pliki i kliknij 'Rozpocznij transfer'.","Filename":"Nazwa pliku","Image format either wrong or not supported.":"Format zdjecia jest zly lub nieobslugiwany","Status":"Status","HTTP Error.":"Błąd HTTP.","Start Upload":"Wyslij","mb":"mb","kb":"kb","Duplicate file error.":"Blad: duplikacja pliku.","File size error.":"Plik jest zbyt duży.","N/A":"Nie dostępne","gb":"gb","Error: Invalid file extension:":"Blad: Nieprawidlowe rozszerzenie pliku:","Select files":"Wybierz pliki:","%s already present in the queue.":"%s juz wystepuje w kolejce.","File: %s":"Plik: %s","b":"b","Uploaded %d/%d files":"Wysłano %d/%d plików","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"%d plików w kolejce.","File: %s, size: %d, max file size: %d":"Plik: %s, rozmiar: %d, maksymalny rozmiar pliku: %d","Drag files here.":"Przeciągnij tu pliki","Runtime ran out of available memory.":"Wyczerpano pamiec RAM.","File count error.":"Blad liczenia pliku.","File extension error.":"Nieobsługiwany format pliku.","Error: File too large:":"Blad: Plik za duzy:","Add Files":"Dodaj pliki"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/pt_BR.js b/themes/default/js/plugins/plupload/i18n/pt_BR.js new file mode 100644 index 000000000..dcaf6c6fc --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/pt_BR.js @@ -0,0 +1,2 @@ +// Portuguese (Brazil) (pt_BR) +plupload.addI18n({"Stop Upload":"Parar o envio","Upload URL might be wrong or doesn't exist.":"URL de envio está errada ou não existe","tb":"TB","Size":"Tamanho","Close":"Fechar","Init error.":"Erro inicializando.","Add files to the upload queue and click the start button.":"Adicione os arquivos abaixo e clique no botão \"Iniciar o envio\".","Filename":"Nome do arquivo","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"Status","HTTP Error.":"Erro HTTP.","Start Upload":"Iniciar o envio","mb":"MB","kb":"KB","Duplicate file error.":"Erro: Arquivo duplicado.","File size error.":"Tamanho de arquivo não permitido.","N/A":"N/D","gb":"GB","Error: Invalid file extension:":"Error: Invalid file extension:","Select files":"Escolha os arquivos","%s already present in the queue.":"%s já presentes na fila.","File: %s":"Arquivo: %s","b":"Bytes","Uploaded %d/%d files":"Enviado(s) %d/%d arquivo(s)","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Só são aceitos %d arquivos por vez. O que passou disso foi descartado.","%d files queued":"%d arquivo(s)","File: %s, size: %d, max file size: %d":"Arquivo: %s, Tamanho: %d , Tamanho Máximo do Arquivo: %d","Drag files here.":"Arraste os arquivos pra cá","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"Erro na contagem dos arquivos","File extension error.":"Tipo de arquivo não permitido.","Error: File too large:":"Error: File too large:","Add Files":"Adicionar arquivo(s)"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/ro.js b/themes/default/js/plugins/plupload/i18n/ro.js new file mode 100644 index 000000000..2ea3f06cb --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/ro.js @@ -0,0 +1,2 @@ +// Romanian (ro) +plupload.addI18n({"Stop Upload":"Oprește încărcarea","Upload URL might be wrong or doesn't exist.":"Upload URL might be wrong or doesn't exist.","tb":"tb","Size":"Mărime","Close":"Închide","Init error.":"Eroare inițializare.","Add files to the upload queue and click the start button.":"Adaugă fișiere în lista apoi apasă butonul \"Începe încărcarea\".","Filename":"Nume fișier","Image format either wrong or not supported.":"Formatul de imagine ori este greșit ori nu este suportat.","Status":"Stare","HTTP Error.":"Eroare HTTP","Start Upload":"Începe încărcarea","mb":"mb","kb":"kb","Duplicate file error.":"Eroare duplicat fișier.","File size error.":"Eroare dimensiune fișier.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Eroare: Extensia fișierului este invalidă:","Select files":"Selectează fișierele","%s already present in the queue.":"%s există deja în lista de așteptare.","File: %s":"Fișier: %s","b":"b","Uploaded %d/%d files":"Fișiere încărcate %d/%d","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"%d fișiere listate","File: %s, size: %d, max file size: %d":"Fișier: %s, mărime: %d, mărime maximă: %d","Drag files here.":"Trage aici fișierele.","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"Eroare numărare fișiere.","File extension error.":"Eroare extensie fișier.","Error: File too large:":"Eroare: Fișierul este prea mare:","Add Files":"Adaugă fișiere"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/ru.js b/themes/default/js/plugins/plupload/i18n/ru.js new file mode 100644 index 000000000..ae2470bee --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/ru.js @@ -0,0 +1,2 @@ +// Russian (ru) +plupload.addI18n({"Stop Upload":"Остановить Загрузку","Upload URL might be wrong or doesn't exist.":"Адрес заргузки неправильный или он не существует.","tb":"тб","Size":"Размер","Close":"Закрыть","Init error.":"Ошибка инициализации.","Add files to the upload queue and click the start button.":"Добавьте файлы в очередь и нажмите кнопку \"Загрузить файлы\".","Filename":"Имя файла","Image format either wrong or not supported.":"Формат картинки неправильный или он не поддерживается.","Status":"Статус","HTTP Error.":"Ошибка HTTP.","Start Upload":"Начать загрузку","mb":"мб","kb":"кб","Duplicate file error.":"Такой файл уже присутствует в очереди.","File size error.":"Неправильный размер файла.","N/A":"N/A","gb":"гб","Error: Invalid file extension:":"Ошибка: У файла неправильное расширение:","Select files":"Выберите файлы","%s already present in the queue.":"%s уже присутствует в очереди.","File: %s":"Файл: %s","b":"б","Uploaded %d/%d files":"Загружено %d/%d файлов","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Загрузочный элемент за раз принимает только %d файл(ов). Лишние файлы были отброшены.","%d files queued":"В очереди %d файл(ов)","File: %s, size: %d, max file size: %d":"Файл: %s, размер: %d, макс. размер файла: %d","Drag files here.":"Перетащите файлы сюда.","Runtime ran out of available memory.":"Рабочая среда превысила лимит достуной памяти.","File count error.":"Слишком много файлов.","File extension error.":"Неправильное расширение файла.","Error: File too large:":"Ошибка: Файл слишком большой:","Add Files":"Добавьте файлы"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/sk.js b/themes/default/js/plugins/plupload/i18n/sk.js new file mode 100644 index 000000000..18c9351c4 --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/sk.js @@ -0,0 +1,2 @@ +// Slovak (sk) +plupload.addI18n({"Stop Upload":"Zastaviť nahrávanie","Upload URL might be wrong or doesn't exist.":"URL pre nahratie nie je správna alebo neexistuje.","tb":"tb","Size":"Veľkosť","Close":"Zatvoriť","Init error.":"Chyba inicializácie.","Add files to the upload queue and click the start button.":"Pridajte súbory do zoznamu a potom spustite nahrávanie.","Filename":"Názov súboru","Image format either wrong or not supported.":"Formát obrázku je nesprávny alebo nie je podporovaný.","Status":"Stav","HTTP Error.":"HTTP Chyba.","Start Upload":"Spustiť nahrávanie","mb":"mb","kb":"kb","Duplicate file error.":"Duplicitný súbor.","File size error.":"Súbor je príliš veľký.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Error: Nesprávny typ súboru:","Select files":"Vyberte súbory","%s already present in the queue.":"%s sa už nachádza v zozname.","File: %s":"Súbor: %s","b":"b","Uploaded %d/%d files":"Nahraných %d/%d súborov","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"%d súborov pridaných do zoznamu","File: %s, size: %d, max file size: %d":"Súbor: %s, veľkosť: %d, max. veľkosť súboru: %d","Drag files here.":"Sem pretiahnite súbory.","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"Nesprávny počet súborov.","File extension error.":"Chybný typ súboru.","Error: File too large:":"Chyba: Súbor je príliš veľký:","Add Files":"Pridať súbory"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/sq.js b/themes/default/js/plugins/plupload/i18n/sq.js new file mode 100644 index 000000000..1268954e3 --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/sq.js @@ -0,0 +1,2 @@ +// Albanian (sq) +plupload.addI18n({"Stop Upload":"","Upload URL might be wrong or doesn't exist.":"","tb":"TB","Size":"","Close":"","Init error.":"Init gabim.","Add files to the upload queue and click the start button.":"","Filename":"","Image format either wrong or not supported.":"","Status":"","HTTP Error.":"HTTP Gabim.","Start Upload":"","mb":"MB","kb":"KB","Duplicate file error.":"Gabim i dublikatës të dosjes.","File size error.":"Gabim i madhësisë së dosjes.","N/A":"Nuk është në dispozicion","gb":"GB","Error: Invalid file extension:":"","Select files":"Zhgjidhni dosjet.","%s already present in the queue.":"","File: %s":"","b":"B","Uploaded %d/%d files":"","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"","%d files queued":"","File: %s, size: %d, max file size: %d":"","Drag files here.":"","Runtime ran out of available memory.":"","File count error.":"","File extension error.":"Gabim i zgerimit të dosjes.","Error: File too large:":"","Add Files":""}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/sr.js b/themes/default/js/plugins/plupload/i18n/sr.js new file mode 100644 index 000000000..bb9581c8b --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/sr.js @@ -0,0 +1,2 @@ +// Serbian (sr) +plupload.addI18n({"Stop Upload":"Stop Upload","Upload URL might be wrong or doesn't exist.":"Upload URL might be wrong or doesn't exist.","tb":"","Size":"Veličina","Close":"Close","Init error.":"Init error.","Add files to the upload queue and click the start button.":"Dodajte fajlove u listu i kliknite na dugme Start.","Filename":"Naziv fajla","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"Status","HTTP Error.":"HTTP Error.","Start Upload":"Počni upload","mb":"","kb":"","Duplicate file error.":"","File size error.":"File size error.","N/A":"N/A","gb":"","Error: Invalid file extension:":"Error: Invalid file extension:","Select files":"Izaberite fajlove","%s already present in the queue.":"","File: %s":"File: %s","b":"","Uploaded %d/%d files":"Snimljeno %d/%d fajlova","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"%d files queued","File: %s, size: %d, max file size: %d":"","Drag files here.":"Prevucite fajlove ovde.","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"File count error.","File extension error.":"File extension error.","Error: File too large:":"Error: File too large:","Add Files":"Dodaj fajlove"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/sr_RS.js b/themes/default/js/plugins/plupload/i18n/sr_RS.js new file mode 100644 index 000000000..d72d0a912 --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/sr_RS.js @@ -0,0 +1,2 @@ +// Serbian (Serbia) (sr_RS) +plupload.addI18n({"Stop Upload":"","Upload URL might be wrong or doesn't exist.":"","tb":"","Size":"","Close":"","Init error.":"","Add files to the upload queue and click the start button.":"","Filename":"","Image format either wrong or not supported.":"","Status":"","HTTP Error.":"","Start Upload":"","mb":"","kb":"","Duplicate file error.":"","File size error.":"","N/A":"","gb":"","Error: Invalid file extension:":"","Select files":"","%s already present in the queue.":"","File: %s":"","b":"","Uploaded %d/%d files":"","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"","%d files queued":"","File: %s, size: %d, max file size: %d":"","Drag files here.":"","Runtime ran out of available memory.":"","File count error.":"","File extension error.":"","Error: File too large:":"","Add Files":""}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/sv.js b/themes/default/js/plugins/plupload/i18n/sv.js new file mode 100644 index 000000000..f25ed818f --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/sv.js @@ -0,0 +1,2 @@ +// Swedish (sv) +plupload.addI18n({"Stop Upload":"Avbryt","Upload URL might be wrong or doesn't exist.":"URL:en va fel eller existerar inte.","tb":"tb","Size":"Storlek","Close":"Stäng","Init error.":"Problem vid initialisering.","Add files to the upload queue and click the start button.":"Lägg till filer till kön och tryck på start.","Filename":"Filnamn","Image format either wrong or not supported.":"Bildformatet är fel eller så finns inte stöd för det.","Status":"Status","HTTP Error.":"HTTP problem.","Start Upload":"Starta","mb":"mb","kb":"kb","Duplicate file error.":"Problem med dubbla filer.","File size error.":"Problem med filstorlek.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Fel: Ej godkänd filändelse.","Select files":"Välj filer","%s already present in the queue.":"%s är redan tillagd.","File: %s":"Fil: %s","b":"b","Uploaded %d/%d files":"Laddade upp %d/%d filer","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Det går bara lägga till %d filer åt gången, allt utöver detta togs bort.","%d files queued":"%d filer i kö","File: %s, size: %d, max file size: %d":"Fil: %s, storlek: %d, max storlek: %d","Drag files here.":"Dra filer hit","Runtime ran out of available memory.":"Slut på minne.","File count error.":"Räknefel.","File extension error.":"Problem med filändelse.","Error: File too large:":"Fel: Filen är för stor:","Add Files":"Lägg till"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/th_TH.js b/themes/default/js/plugins/plupload/i18n/th_TH.js new file mode 100644 index 000000000..53b995e6d --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/th_TH.js @@ -0,0 +1,2 @@ +// Thai (Thailand) (th_TH) +plupload.addI18n({"Stop Upload":"หยุดอัพโหลด","Upload URL might be wrong or doesn't exist.":"URL ของการอัพโหลดอาจจะผิดหรือไม่มีอยู่","tb":"เทราไบต์","Size":"ขนาด","Close":"ปิด","Init error.":"Init เกิดข้อผิดพลาด","Add files to the upload queue and click the start button.":"เพิ่มไฟล์ไปยังคิวอัพโหลดและคลิกที่ปุ่มเริ่ม","Filename":"ชื่อไฟล์","Image format either wrong or not supported.":"รูปแบบรูปภาพทั้งสองผิดหรือไม่รองรับ","Status":"สถานะ","HTTP Error.":"HTTP เกิดข้อผิดพลาด","Start Upload":"เริ่มอัพโหลด","mb":"เมกะไบต์","kb":"กิโลไบต์","Duplicate file error.":"ไฟล์ที่ซ้ำกันเกิดข้อผิดพลาด","File size error.":"ขนาดไฟล์เกิดข้อผิดพลาด","N/A":"N/A","gb":"กิกะไบต์","Error: Invalid file extension:":"ข้อผิดพลาด: นามสกุลไฟล์ไม่ถูกต้อง:","Select files":"เลือกไฟล์","%s already present in the queue.":"%s อยู่ในคิวแล้ว","File: %s":"ไฟล์: %s","b":"ไบต์","Uploaded %d/%d files":"อัพโหลดแล้ว %d/%d ไฟล์","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"การอัพโหลดจะยอมรับเฉพาะ %d ไฟล์(s) ในช่วงเวลาเดียวกัน เมื่อไฟล์พิเศษถูกปลดออก","%d files queued":"%d ไฟล์ที่อยู่ในคิว","File: %s, size: %d, max file size: %d":"ไฟล์: %s, ขนาด: %d, ขนาดไฟล์สูงสุด: %d","Drag files here.":"ลากไฟล์มาที่นี่","Runtime ran out of available memory.":"รันไทม์วิ่งออกมาจากหน่วยความจำ","File count error.":"การนับไฟล์เกิดข้อผิดพลาด","File extension error.":"นามสกุลไฟล์เกิดข้อผิดพลาด","Error: File too large:":"ข้อผิดพลาด: ไฟล์ใหญ่เกินไป:","Add Files":"เพิ่มไฟล์"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/tr.js b/themes/default/js/plugins/plupload/i18n/tr.js new file mode 100644 index 000000000..47fec4ea3 --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/tr.js @@ -0,0 +1,2 @@ +// Turkish (tr) +plupload.addI18n({"Stop Upload":"Yüklemeyi durdur","Upload URL might be wrong or doesn't exist.":"URL yok ya da hatalı olabilir.","tb":"tb","Size":"Boyut","Close":"Kapat","Init error.":"Başlangıç hatası.","Add files to the upload queue and click the start button.":"Dosyaları kuyruğa ekleyin ve başlatma butonuna tıklayın.","Filename":"Dosya adı","Image format either wrong or not supported.":"Resim formatı yanlış ya da desteklenmiyor.","Status":"Durum","HTTP Error.":"HTTP hatası.","Start Upload":"Yüklemeyi başlat","mb":"mb","kb":"kb","Duplicate file error.":"Yinelenen dosya hatası.","File size error.":"Dosya boyutu hatası.","N/A":"-","gb":"gb","Error: Invalid file extension:":"Hata: Geçersiz dosya uzantısı:","Select files":"Dosyaları seç","%s already present in the queue.":"%s kuyrukta zaten mevcut.","File: %s":"Dosya: %s","b":"bayt","Uploaded %d/%d files":"%d/%d dosya yüklendi","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Yükleme elemanı aynı anda %d dosya kabul eder. Ekstra dosyalar işleme konulmaz.","%d files queued":"Kuyrukta %d dosya var.","File: %s, size: %d, max file size: %d":"Dosya: %s, boyut: %d, maksimum dosya boyutu: %d","Drag files here.":"Dosyaları buraya bırakın.","Runtime ran out of available memory.":"İşlem için yeterli bellek yok.","File count error.":"Dosya sayım hatası.","File extension error.":"Dosya uzantısı hatası.","Error: File too large:":"Hata: Dosya çok büyük:","Add Files":"Dosya ekle"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/uk_UA.js b/themes/default/js/plugins/plupload/i18n/uk_UA.js new file mode 100644 index 000000000..726bf94cd --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/uk_UA.js @@ -0,0 +1,2 @@ +// Ukrainian (Ukraine) (uk_UA) +plupload.addI18n({"Stop Upload":"Зупинити завантаження","Upload URL might be wrong or doesn't exist.":"Адреса завантаження неправильна або не існує.","tb":"тб","Size":"Розмір","Close":"Закрити","Init error.":"Помилка ініціалізації.","Add files to the upload queue and click the start button.":"Додайте файли в чергу та натисніть кнопку \"Завантажити файли\".","Filename":"Назва файлу","Image format either wrong or not supported.":"Формат картинки не правильний або не підтримується.","Status":"Статус","HTTP Error.":"Помилка HTTP.","Start Upload":"Почати завантаження","mb":"мб","kb":"кб","Duplicate file error.":"Такий файл вже присутній в черзі.","File size error.":"Неправильний розмір файлу.","N/A":"Н/Д","gb":"гб","Error: Invalid file extension:":"Помилка: У файлу неправильне розширення:","Select files":"Оберіть файли","%s already present in the queue.":"%s вже присутній у черзі.","File: %s":"Файл: %s","b":"б","Uploaded %d/%d files":"Завантажено %d/%d файлів","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Завантажувальний елемент приймає лише %d файл(ів) одночасно. Зайві файли було відкинуто.","%d files queued":"В черзі %d файл(ів)","File: %s, size: %d, max file size: %d":"Файл: %s, розмір: %d, макс. розмір файлу: %d","Drag files here.":"Перетягніть файли сюди.","Runtime ran out of available memory.":"Робоче середовище перевищило ліміт доступної пам'яті.","File count error.":"Занадто багато файлів.","File extension error.":"Неправильне розширення файлу.","Error: File too large:":"Помилка: Файл занадто великий:","Add Files":"Додати файли"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/zh_CN.js b/themes/default/js/plugins/plupload/i18n/zh_CN.js new file mode 100644 index 000000000..f48e0c43e --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/zh_CN.js @@ -0,0 +1,2 @@ +// Chinese (China) (zh_CN) +plupload.addI18n({"Stop Upload":"停止上传","Upload URL might be wrong or doesn't exist.":"上传的URL可能是错误的或不存在。","tb":"tb","Size":"大小","Close":"关闭","Init error.":"初始化错误。","Add files to the upload queue and click the start button.":"将文件添加到上传队列,然后点击”开始上传“按钮。","Filename":"文件名","Image format either wrong or not supported.":"图片格式错误或者不支持。","Status":"状态","HTTP Error.":"HTTP 错误。","Start Upload":"开始上传","mb":"mb","kb":"kb","Duplicate file error.":"重复文件错误。","File size error.":"文件大小错误。","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"错误:无效的文件扩展名:","Select files":"选择文件","%s already present in the queue.":"%s 已经在当前队列里。","File: %s":"文件: %s","b":"b","Uploaded %d/%d files":"已上传 %d/%d 个文件","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"每次只接受同时上传 %d 个文件,多余的文件将会被删除。","%d files queued":"%d 个文件加入到队列","File: %s, size: %d, max file size: %d":"文件: %s, 大小: %d, 最大文件大小: %d","Drag files here.":"把文件拖到这里。","Runtime ran out of available memory.":"运行时已消耗所有可用内存。","File count error.":"文件数量错误。","File extension error.":"文件扩展名错误。","Error: File too large:":"错误: 文件太大:","Add Files":"增加文件"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/i18n/zh_TW.js b/themes/default/js/plugins/plupload/i18n/zh_TW.js new file mode 100644 index 000000000..2deebe2d6 --- /dev/null +++ b/themes/default/js/plugins/plupload/i18n/zh_TW.js @@ -0,0 +1,2 @@ +// Chinese (Taiwan) (zh_TW) +plupload.addI18n({"Stop Upload":"停止上傳","Upload URL might be wrong or doesn't exist.":"檔案URL可能有誤或者不存在。","tb":"tb","Size":"大小","Close":"關閉","Init error.":"初始化錯誤。","Add files to the upload queue and click the start button.":"將檔案加入上傳序列,然後點選”開始上傳“按鈕。","Filename":"檔案名稱","Image format either wrong or not supported.":"圖片格式錯誤或者不支援。","Status":"狀態","HTTP Error.":"HTTP 錯誤。","Start Upload":"開始上傳","mb":"mb","kb":"kb","Duplicate file error.":"錯誤:檔案重複。","File size error.":"錯誤:檔案大小超過限制。","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"錯誤:不接受的檔案格式:","Select files":"選擇檔案","%s already present in the queue.":"%s 已經存在目前的檔案序列。","File: %s":"檔案: %s","b":"b","Uploaded %d/%d files":"已上傳 %d/%d 個文件","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"每次只能上傳 %d 個檔案,超過限制數量的檔案將被忽略。","%d files queued":"%d 個檔案加入到序列","File: %s, size: %d, max file size: %d":"檔案: %s, 大小: %d, 檔案大小上限: %d","Drag files here.":"把檔案拖曳到這裡。","Runtime ran out of available memory.":"執行時耗盡了所有可用的記憶體。","File count error.":"檔案數量錯誤。","File extension error.":"檔案副檔名錯誤。","Error: File too large:":"錯誤: 檔案大小太大:","Add Files":"增加檔案"}); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/jquery.plupload.queue/css/jquery.plupload.queue.css b/themes/default/js/plugins/plupload/jquery.plupload.queue/css/jquery.plupload.queue.css new file mode 100644 index 000000000..6bfe0e5e3 --- /dev/null +++ b/themes/default/js/plugins/plupload/jquery.plupload.queue/css/jquery.plupload.queue.css @@ -0,0 +1,185 @@ +/* + Plupload +------------------------------------------------------------------- */ + +.plupload_wrapper * { + box-sizing: content-box; +} + +.plupload_button { + display: -moz-inline-box; /* FF < 3*/ + display: inline-block; + font: normal 12px sans-serif; + text-decoration: none; + color: #42454a; + border: 1px solid #bababa; + padding: 2px 8px 3px 20px; + margin-right: 4px; + background: #f3f3f3 url('../img/buttons.png') no-repeat 0 center; + outline: 0; + + /* Optional rounded corners for browsers that support it */ + -moz-border-radius: 3px; + -khtml-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; +} + +.plupload_button:hover { + color: #000; + text-decoration: none; +} + +.plupload_disabled, a.plupload_disabled:hover { + color: #737373; + border-color: #c5c5c5; + background: #ededed url('../img/buttons-disabled.png') no-repeat 0 center; + cursor: default; +} + +.plupload_add { + background-position: -181px center; +} + +.plupload_wrapper { + font: normal 11px Verdana,sans-serif; + width: 100%; +} + +.plupload_container { + padding: 8px; + background: url('../img/transp50.png'); + /*-moz-border-radius: 5px;*/ +} + +.plupload_container input { + border: 1px solid #DDD; + font: normal 11px Verdana,sans-serif; + width: 98%; +} + +.plupload_header {background: #2A2C2E url('../img/backgrounds.gif') repeat-x;} +.plupload_header_content { + background: url('../img/backgrounds.gif') no-repeat 0 -317px; + min-height: 56px; + padding-left: 60px; + color: #FFF; +} +.plupload_header_title { + font: normal 18px sans-serif; + padding: 6px 0 3px; +} +.plupload_header_text { + font: normal 12px sans-serif; +} + +.plupload_filelist { + margin: 0; + padding: 0; + list-style: none; +} + +.plupload_scroll .plupload_filelist { + height: 185px; + background: #F5F5F5; + overflow-y: scroll; +} + +.plupload_filelist li { + padding: 10px 8px; + background: #F5F5F5 url('../img/backgrounds.gif') repeat-x 0 -156px; + border-bottom: 1px solid #DDD; +} + +.plupload_filelist_header, .plupload_filelist_footer { + background: #DFDFDF; + padding: 8px 8px; + color: #42454A; +} +.plupload_filelist_header { + border-top: 1px solid #EEE; + border-bottom: 1px solid #CDCDCD; +} + +.plupload_filelist_footer {border-top: 1px solid #FFF; height: 22px; line-height: 20px; vertical-align: middle;} +.plupload_file_name {float: left; overflow: hidden} +.plupload_file_status {color: #777;} +.plupload_file_status span {color: #42454A;} +.plupload_file_size, .plupload_file_status, .plupload_progress { + float: right; + width: 80px; +} +.plupload_file_size, .plupload_file_status, .plupload_file_action {text-align: right;} + +.plupload_filelist .plupload_file_name { + width: 205px; + white-space: nowrap; + text-overflow: ellipsis; +} + +.plupload_file_action { + float: right; + width: 16px; + height: 16px; + margin-left: 15px; +} + +.plupload_file_action * { + display: none; + width: 16px; + height: 16px; +} + +li.plupload_uploading {background: #ECF3DC url('../img/backgrounds.gif') repeat-x 0 -238px;} +li.plupload_done {color:#AAA} + +li.plupload_delete a { + background: url('../img/delete.gif'); +} + +li.plupload_failed a { + background: url('../img/error.gif'); + cursor: default; +} + +li.plupload_done a { + background: url('../img/done.gif'); + cursor: default; +} + +.plupload_progress, .plupload_upload_status { + display: none; +} + +.plupload_progress_container { + margin-top: 3px; + border: 1px solid #CCC; + background: #FFF; + padding: 1px; +} +.plupload_progress_bar { + width: 0px; + height: 7px; + background: #CDEB8B; +} + +.plupload_scroll .plupload_filelist_header .plupload_file_action, .plupload_scroll .plupload_filelist_footer .plupload_file_action { + margin-right: 17px; +} + +/* Floats */ + +.plupload_clear,.plupload_clearer {clear: both;} +.plupload_clearer, .plupload_progress_bar { + display: block; + font-size: 0; + line-height: 0; +} + +li.plupload_droptext { + background: transparent; + text-align: center; + vertical-align: middle; + border: 0; + line-height: 165px; +} diff --git a/themes/default/js/plugins/plupload/jquery.plupload.queue/img/backgrounds.gif b/themes/default/js/plugins/plupload/jquery.plupload.queue/img/backgrounds.gif new file mode 100644 index 000000000..39e33ebc0 Binary files /dev/null and b/themes/default/js/plugins/plupload/jquery.plupload.queue/img/backgrounds.gif differ diff --git a/themes/default/js/plugins/plupload/jquery.plupload.queue/img/buttons-disabled.png b/themes/default/js/plugins/plupload/jquery.plupload.queue/img/buttons-disabled.png new file mode 100644 index 000000000..afa11af9b Binary files /dev/null and b/themes/default/js/plugins/plupload/jquery.plupload.queue/img/buttons-disabled.png differ diff --git a/themes/default/js/plugins/plupload/jquery.plupload.queue/img/buttons.png b/themes/default/js/plugins/plupload/jquery.plupload.queue/img/buttons.png new file mode 100644 index 000000000..153e73885 Binary files /dev/null and b/themes/default/js/plugins/plupload/jquery.plupload.queue/img/buttons.png differ diff --git a/themes/default/js/plugins/plupload/jquery.plupload.queue/img/delete.gif b/themes/default/js/plugins/plupload/jquery.plupload.queue/img/delete.gif new file mode 100644 index 000000000..78ca8b3b4 Binary files /dev/null and b/themes/default/js/plugins/plupload/jquery.plupload.queue/img/delete.gif differ diff --git a/themes/default/js/plugins/plupload/jquery.plupload.queue/img/done.gif b/themes/default/js/plugins/plupload/jquery.plupload.queue/img/done.gif new file mode 100644 index 000000000..29f3ed7c9 Binary files /dev/null and b/themes/default/js/plugins/plupload/jquery.plupload.queue/img/done.gif differ diff --git a/themes/default/js/plugins/plupload/jquery.plupload.queue/img/error.gif b/themes/default/js/plugins/plupload/jquery.plupload.queue/img/error.gif new file mode 100644 index 000000000..4682b6300 Binary files /dev/null and b/themes/default/js/plugins/plupload/jquery.plupload.queue/img/error.gif differ diff --git a/themes/default/js/plugins/plupload/jquery.plupload.queue/img/throbber.gif b/themes/default/js/plugins/plupload/jquery.plupload.queue/img/throbber.gif new file mode 100644 index 000000000..4ae8b16a5 Binary files /dev/null and b/themes/default/js/plugins/plupload/jquery.plupload.queue/img/throbber.gif differ diff --git a/themes/default/js/plugins/plupload/jquery.plupload.queue/img/transp50.png b/themes/default/js/plugins/plupload/jquery.plupload.queue/img/transp50.png new file mode 100644 index 000000000..eb0efe104 Binary files /dev/null and b/themes/default/js/plugins/plupload/jquery.plupload.queue/img/transp50.png differ diff --git a/themes/default/js/plugins/plupload/jquery.plupload.queue/jquery.plupload.queue.js b/themes/default/js/plugins/plupload/jquery.plupload.queue/jquery.plupload.queue.js new file mode 100644 index 000000000..6894ecde9 --- /dev/null +++ b/themes/default/js/plugins/plupload/jquery.plupload.queue/jquery.plupload.queue.js @@ -0,0 +1,428 @@ +/** + * jquery.plupload.queue.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/* global jQuery:true, alert:true */ + +/** +jQuery based implementation of the Plupload API - multi-runtime file uploading API. + +To use the widget you must include _jQuery_. It is not meant to be extended in any way and is provided to be +used as it is. + +@example + +
+

Your browser doesn't have Flash, Silverlight or HTML5 support.

+
+ + + +@example + // Retrieving a reference to plupload.Uploader object + var uploader = $('#uploader').pluploadQueue(); + + uploader.bind('FilesAdded', function() { + + // Autostart + setTimeout(uploader.start, 1); // "detach" from the main thread + }); + +@class pluploadQueue +@constructor +@param {Object} settings For detailed information about each option check documentation. + @param {String} settings.url URL of the server-side upload handler. + @param {Number|String} [settings.chunk_size=0] Chunk size in bytes to slice the file into. Shorcuts with b, kb, mb, gb, tb suffixes also supported. `e.g. 204800 or "204800b" or "200kb"`. By default - disabled. + @param {String} [settings.file_data_name="file"] Name for the file field in Multipart formated message. + @param {Array} [settings.filters=[]] Set of file type filters, each one defined by hash of title and extensions. `e.g. {title : "Image files", extensions : "jpg,jpeg,gif,png"}`. Dispatches `plupload.FILE_EXTENSION_ERROR` + @param {String} [settings.flash_swf_url] URL of the Flash swf. + @param {Object} [settings.headers] Custom headers to send with the upload. Hash of name/value pairs. + @param {Number|String} [settings.max_file_size] Maximum file size that the user can pick, in bytes. Optionally supports b, kb, mb, gb, tb suffixes. `e.g. "10mb" or "1gb"`. By default - not set. Dispatches `plupload.FILE_SIZE_ERROR`. + @param {Number} [settings.max_retries=0] How many times to retry the chunk or file, before triggering Error event. + @param {Boolean} [settings.multipart=true] Whether to send file and additional parameters as Multipart formated message. + @param {Object} [settings.multipart_params] Hash of key/value pairs to send with every file upload. + @param {Boolean} [settings.multi_selection=true] Enable ability to select multiple files at once in file dialog. + @param {Boolean} [settings.prevent_duplicates=false] Do not let duplicates into the queue. Dispatches `plupload.FILE_DUPLICATE_ERROR`. + @param {String|Object} [settings.required_features] Either comma-separated list or hash of required features that chosen runtime should absolutely possess. + @param {Object} [settings.resize] Enable resizng of images on client-side. Applies to `image/jpeg` and `image/png` only. `e.g. {width : 200, height : 200, quality : 90, crop: true}` + @param {Number} [settings.resize.width] If image is bigger, it will be resized. + @param {Number} [settings.resize.height] If image is bigger, it will be resized. + @param {Number} [settings.resize.quality=90] Compression quality for jpegs (1-100). + @param {Boolean} [settings.resize.crop=false] Whether to crop images to exact dimensions. By default they will be resized proportionally. + @param {String} [settings.runtimes="html5,flash,silverlight,html4"] Comma separated list of runtimes, that Plupload will try in turn, moving to the next if previous fails. + @param {String} [settings.silverlight_xap_url] URL of the Silverlight xap. + @param {Boolean} [settings.unique_names=false] If true will generate unique filenames for uploaded files. + + @param {Boolean} [settings.dragdrop=true] Enable ability to add file to the queue by drag'n'dropping them from the desktop. + @param {Boolean} [settings.rename=false] Enable ability to rename files in the queue. + @param {Boolean} [settings.multiple_queues=true] Re-activate the widget after each upload procedure. +*/ +;(function($, o) { + var uploaders = {}; + + function _(str) { + return plupload.translate(str) || str; + } + + function renderUI(id, target) { + // Remove all existing non plupload items + target.contents().each(function(i, node) { + node = $(node); + + if (!node.is('.plupload')) { + node.remove(); + } + }); + + target.prepend( + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + _('Select files') + '
' + + '
' + _('Add files to the upload queue and click the start button.') + '
' + + '
' + + '
' + + + '
' + + '
' + + '
' + _('Filename') + '
' + + '
 
' + + '
' + _('Status') + '
' + + '
' + _('Size') + '
' + + '
 
' + + '
' + + + '
    ' + + + '' + + '
    ' + + '
    ' + + '
    ' + + '' + + '
    ' + ); + } + + $.fn.pluploadQueue = function(settings) { + if (settings) { + this.each(function() { + var uploader, target, id, contents_bak; + + target = $(this); + id = target.attr('id'); + + if (!id) { + id = plupload.guid(); + target.attr('id', id); + } + + contents_bak = target.html(); + renderUI(id, target); + + settings = $.extend({ + dragdrop : true, + browse_button : id + '_browse', + container : id + }, settings); + + // Enable drag/drop (see PostInit handler as well) + if (settings.dragdrop) { + settings.drop_element = id + '_filelist'; + } + + uploader = new plupload.Uploader(settings); + + uploaders[id] = uploader; + + function handleStatus(file) { + var actionClass; + + if (file.status == plupload.DONE) { + actionClass = 'plupload_done'; + } + + if (file.status == plupload.FAILED) { + actionClass = 'plupload_failed'; + } + + if (file.status == plupload.QUEUED) { + actionClass = 'plupload_delete'; + } + + if (file.status == plupload.UPLOADING) { + actionClass = 'plupload_uploading'; + } + + var icon = $('#' + file.id).attr('class', actionClass).find('a').css('display', 'block'); + if (file.hint) { + icon.attr('title', file.hint); + } + } + + function updateTotalProgress() { + $('span.plupload_total_status', target).html(uploader.total.percent + '%'); + $('div.plupload_progress_bar', target).css('width', uploader.total.percent + '%'); + $('span.plupload_upload_status', target).html( + o.sprintf(_('Uploaded %d/%d files'), uploader.total.uploaded, uploader.files.length) + ); + } + + function updateList() { + var fileList = $('ul.plupload_filelist', target).html(''), inputCount = 0, inputHTML; + + $.each(uploader.files, function(i, file) { + inputHTML = ''; + + if (file.status == plupload.DONE) { + if (file.target_name) { + inputHTML += ''; + } + + inputHTML += ''; + inputHTML += ''; + + inputCount++; + + $('#' + id + '_count').val(inputCount); + } + + fileList.append( + '
  • ' + + '
    ' + file.name + '
    ' + + '
    ' + + '
    ' + file.percent + '%
    ' + + '
    ' + plupload.formatSize(file.size) + '
    ' + + '
     
    ' + + inputHTML + + '
  • ' + ); + + handleStatus(file); + + $('#' + file.id + '.plupload_delete a').click(function(e) { + $('#' + file.id).remove(); + uploader.removeFile(file); + + e.preventDefault(); + }); + }); + + $('span.plupload_total_file_size', target).html(plupload.formatSize(uploader.total.size)); + + if (uploader.total.queued === 0) { + $('span.plupload_add_text', target).html(_('Add Files')); + } else { + $('span.plupload_add_text', target).html(o.sprintf(_('%d files queued'), uploader.total.queued)); + } + + $('a.plupload_start', target).toggleClass('plupload_disabled', uploader.files.length == (uploader.total.uploaded + uploader.total.failed)); + + // Scroll to end of file list + fileList[0].scrollTop = fileList[0].scrollHeight; + + updateTotalProgress(); + + // Re-add drag message if there is no files + if (!uploader.files.length && uploader.features.dragdrop && uploader.settings.dragdrop) { + $('#' + id + '_filelist').append('
  • ' + _("Drag files here.") + '
  • '); + } + } + + function destroy() { + delete uploaders[id]; + uploader.destroy(); + target.html(contents_bak); + uploader = target = contents_bak = null; + } + + uploader.bind("UploadFile", function(up, file) { + $('#' + file.id).addClass('plupload_current_file'); + }); + + uploader.bind('Init', function(up, res) { + // Enable rename support + if (!settings.unique_names && settings.rename) { + target.on('click', '#' + id + '_filelist div.plupload_file_name span', function(e) { + var targetSpan = $(e.target), file, parts, name, ext = ""; + + // Get file name and split out name and extension + file = up.getFile(targetSpan.parents('li')[0].id); + name = file.name; + parts = /^(.+)(\.[^.]+)$/.exec(name); + if (parts) { + name = parts[1]; + ext = parts[2]; + } + + // Display input element + targetSpan.hide().after(''); + targetSpan.next().val(name).focus().blur(function() { + targetSpan.show().next().remove(); + }).keydown(function(e) { + var targetInput = $(this); + + if (e.keyCode == 13) { + e.preventDefault(); + + // Rename file and glue extension back on + file.name = targetInput.val() + ext; + targetSpan.html(file.name); + targetInput.blur(); + } + }); + }); + } + + $('#' + id + '_container').attr('title', 'Using runtime: ' + res.runtime); + + $('a.plupload_start', target).click(function(e) { + if (!$(this).hasClass('plupload_disabled')) { + uploader.start(); + } + + e.preventDefault(); + }); + + $('a.plupload_stop', target).click(function(e) { + e.preventDefault(); + uploader.stop(); + }); + + $('a.plupload_start', target).addClass('plupload_disabled'); + }); + + uploader.bind("Error", function(up, err) { + var file = err.file, message; + + if (file) { + message = err.message; + + if (err.details) { + message += " (" + err.details + ")"; + } + + if (err.code == plupload.FILE_SIZE_ERROR) { + alert(_("Error: File too large:") + " " + file.name); + } + + if (err.code == plupload.FILE_EXTENSION_ERROR) { + alert(_("Error: Invalid file extension:") + " " + file.name); + } + + file.hint = message; + $('#' + file.id).attr('class', 'plupload_failed').find('a').css('display', 'block').attr('title', message); + } + + if (err.code === plupload.INIT_ERROR) { + setTimeout(function() { + destroy(); + }, 1); + } + }); + + uploader.bind("PostInit", function(up) { + // features are populated only after input components are fully instantiated + if (up.settings.dragdrop && up.features.dragdrop) { + $('#' + id + '_filelist').append('
  • ' + _("Drag files here.") + '
  • '); + } + }); + + uploader.init(); + + uploader.bind('StateChanged', function() { + if (uploader.state === plupload.STARTED) { + $('li.plupload_delete a,div.plupload_buttons', target).hide(); + uploader.disableBrowse(true); + + $('span.plupload_upload_status,div.plupload_progress,a.plupload_stop', target).css('display', 'block'); + $('span.plupload_upload_status', target).html('Uploaded ' + uploader.total.uploaded + '/' + uploader.files.length + ' files'); + + if (settings.multiple_queues) { + $('span.plupload_total_status,span.plupload_total_file_size', target).show(); + } + } else { + updateList(); + $('a.plupload_stop,div.plupload_progress', target).hide(); + $('a.plupload_delete', target).css('display', 'block'); + + if (settings.multiple_queues && uploader.total.uploaded + uploader.total.failed == uploader.files.length) { + $(".plupload_buttons,.plupload_upload_status", target).css("display", "inline"); + uploader.disableBrowse(false); + + $(".plupload_start", target).addClass("plupload_disabled"); + $('span.plupload_total_status,span.plupload_total_file_size', target).hide(); + } + } + }); + + uploader.bind('FilesAdded', updateList); + + uploader.bind('FilesRemoved', function() { + // since the whole file list is redrawn for every change in the queue + // we need to scroll back to the file removal point to avoid annoying + // scrolling to the bottom bug (see #926) + var scrollTop = $('#' + id + '_filelist').scrollTop(); + updateList(); + $('#' + id + '_filelist').scrollTop(scrollTop); + }); + + uploader.bind('FileUploaded', function(up, file) { + handleStatus(file); + }); + + uploader.bind("UploadProgress", function(up, file) { + // Set file specific progress + $('#' + file.id + ' div.plupload_file_status', target).html(file.percent + '%'); + + handleStatus(file); + updateTotalProgress(); + }); + + // Call setup function + if (settings.setup) { + settings.setup(uploader); + } + }); + + return this; + } else { + // Get uploader instance for specified element + return uploaders[$(this[0]).attr('id')]; + } + }; +})(jQuery, mOxie); diff --git a/themes/default/js/plugins/plupload/jquery.plupload.queue/jquery.plupload.queue.min.js b/themes/default/js/plugins/plupload/jquery.plupload.queue/jquery.plupload.queue.min.js new file mode 100644 index 000000000..d7f7b9636 --- /dev/null +++ b/themes/default/js/plugins/plupload/jquery.plupload.queue/jquery.plupload.queue.min.js @@ -0,0 +1 @@ +;(function(e,t){function r(e){return plupload.translate(e)||e}function i(t,n){n.contents().each(function(t,n){n=e(n),n.is(".plupload")||n.remove()}),n.prepend('
    '+'
    '+'
    '+'
    '+'
    '+r("Select files")+"
    "+'
    '+r("Add files to the upload queue and click the start button.")+"
    "+"
    "+"
    "+'
    '+'
    '+'
    '+r("Filename")+"
    "+'
     
    '+'
    '+r("Status")+"
    "+'
    '+r("Size")+"
    "+'
     
    '+"
    "+'
      '+'"+"
      "+"
      "+"
      "+''+"
      ")}var n={};e.fn.pluploadQueue=function(s){return s?(this.each(function(){function c(t){var n;t.status==plupload.DONE&&(n="plupload_done"),t.status==plupload.FAILED&&(n="plupload_failed"),t.status==plupload.QUEUED&&(n="plupload_delete"),t.status==plupload.UPLOADING&&(n="plupload_uploading");var r=e("#"+t.id).attr("class",n).find("a").css("display","block");t.hint&&r.attr("title",t.hint)}function h(){e("span.plupload_total_status",a).html(u.total.percent+"%"),e("div.plupload_progress_bar",a).css("width",u.total.percent+"%"),e("span.plupload_upload_status",a).html(t.sprintf(r("Uploaded %d/%d files"),u.total.uploaded,u.files.length))}function p(){var n=e("ul.plupload_filelist",a).html(""),i=0,s;e.each(u.files,function(t,r){s="",r.status==plupload.DONE&&(r.target_name&&(s+=''),s+='',s+='',i++,e("#"+f+"_count").val(i)),n.append('
    • '+'
      '+r.name+"
      "+'
      '+'
      '+r.percent+"%
      "+'
      '+plupload.formatSize(r.size)+"
      "+'
       
      '+s+"
    • "),c(r),e("#"+r.id+".plupload_delete a").click(function(t){e("#"+r.id).remove(),u.removeFile(r),t.preventDefault()})}),e("span.plupload_total_file_size",a).html(plupload.formatSize(u.total.size)),u.total.queued===0?e("span.plupload_add_text",a).html(r("Add Files")):e("span.plupload_add_text",a).html(t.sprintf(r("%d files queued"),u.total.queued)),e("a.plupload_start",a).toggleClass("plupload_disabled",u.files.length==u.total.uploaded+u.total.failed),n[0].scrollTop=n[0].scrollHeight,h(),!u.files.length&&u.features.dragdrop&&u.settings.dragdrop&&e("#"+f+"_filelist").append('
    • '+r("Drag files here.")+"
    • ")}function d(){delete n[f],u.destroy(),a.html(l),u=a=l=null}var u,a,f,l;a=e(this),f=a.attr("id"),f||(f=plupload.guid(),a.attr("id",f)),l=a.html(),i(f,a),s=e.extend({dragdrop:!0,browse_button:f+"_browse",container:f},s),s.dragdrop&&(s.drop_element=f+"_filelist"),u=new plupload.Uploader(s),n[f]=u,u.bind("UploadFile",function(t,n){e("#"+n.id).addClass("plupload_current_file")}),u.bind("Init",function(t,n){!s.unique_names&&s.rename&&a.on("click","#"+f+"_filelist div.plupload_file_name span",function(n){var r=e(n.target),i,s,o,u="";i=t.getFile(r.parents("li")[0].id),o=i.name,s=/^(.+)(\.[^.]+)$/.exec(o),s&&(o=s[1],u=s[2]),r.hide().after(''),r.next().val(o).focus().blur(function(){r.show().next().remove()}).keydown(function(t){var n=e(this);t.keyCode==13&&(t.preventDefault(),i.name=n.val()+u,r.html(i.name),n.blur())})}),e("#"+f+"_container").attr("title","Using runtime: "+n.runtime),e("a.plupload_start",a).click(function(t){e(this).hasClass("plupload_disabled")||u.start(),t.preventDefault()}),e("a.plupload_stop",a).click(function(e){e.preventDefault(),u.stop()}),e("a.plupload_start",a).addClass("plupload_disabled")}),u.bind("Error",function(t,n){var i=n.file,s;i&&(s=n.message,n.details&&(s+=" ("+n.details+")"),n.code==plupload.FILE_SIZE_ERROR&&alert(r("Error: File too large:")+" "+i.name),n.code==plupload.FILE_EXTENSION_ERROR&&alert(r("Error: Invalid file extension:")+" "+i.name),i.hint=s,e("#"+i.id).attr("class","plupload_failed").find("a").css("display","block").attr("title",s)),n.code===plupload.INIT_ERROR&&setTimeout(function(){d()},1)}),u.bind("PostInit",function(t){t.settings.dragdrop&&t.features.dragdrop&&e("#"+f+"_filelist").append('
    • '+r("Drag files here.")+"
    • ")}),u.init(),u.bind("StateChanged",function(){u.state===plupload.STARTED?(e("li.plupload_delete a,div.plupload_buttons",a).hide(),u.disableBrowse(!0),e("span.plupload_upload_status,div.plupload_progress,a.plupload_stop",a).css("display","block"),e("span.plupload_upload_status",a).html("Uploaded "+u.total.uploaded+"/"+u.files.length+" files"),s.multiple_queues&&e("span.plupload_total_status,span.plupload_total_file_size",a).show()):(p(),e("a.plupload_stop,div.plupload_progress",a).hide(),e("a.plupload_delete",a).css("display","block"),s.multiple_queues&&u.total.uploaded+u.total.failed==u.files.length&&(e(".plupload_buttons,.plupload_upload_status",a).css("display","inline"),u.disableBrowse(!1),e(".plupload_start",a).addClass("plupload_disabled"),e("span.plupload_total_status,span.plupload_total_file_size",a).hide()))}),u.bind("FilesAdded",p),u.bind("FilesRemoved",function(){var t=e("#"+f+"_filelist").scrollTop();p(),e("#"+f+"_filelist").scrollTop(t)}),u.bind("FileUploaded",function(e,t){c(t)}),u.bind("UploadProgress",function(t,n){e("#"+n.id+" div.plupload_file_status",a).html(n.percent+"%"),c(n),h()}),s.setup&&s.setup(u)}),this):n[e(this[0]).attr("id")]}})(jQuery,mOxie); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/jquery.ui.plupload/css/jquery.ui.plupload.css b/themes/default/js/plugins/plupload/jquery.ui.plupload/css/jquery.ui.plupload.css new file mode 100644 index 000000000..c230b83eb --- /dev/null +++ b/themes/default/js/plugins/plupload/jquery.ui.plupload/css/jquery.ui.plupload.css @@ -0,0 +1,371 @@ +/* + Plupload +------------------------------------------------------------------- */ + +.plupload_wrapper * { + box-sizing: content-box; +} + +.plupload_button { + cursor: pointer; + outline: none; +} + +.plupload_wrapper { + font: normal 11px Verdana,sans-serif; + width: 100%; + min-width: 520px; + line-height: 12px; +} + +.plupload_container { + _height: 300px; + min-height: 300px; + position: relative; +} + +.plupload_filelist_footer {border-width: 1px 0 0 0} +.plupload_file {border-width: 0 0 1px 0} +.plupload_container .plupload_header {border-width: 0 0 1px 0; position: relative;} + +.plupload_delete .ui-icon, +.plupload_done .ui-icon, +.plupload_failed .ui-icon { + cursor:pointer; +} + +.plupload_header_content { + height: 56px; + padding: 0 160px 0 60px; + position: relative; +} + +.plupload_logo { + display:none; + width: 40px; + height: 40px; + background: url('../img/plupload.png') no-repeat 0 0; + position: absolute; + top: 8px; + left: 8px; +} + +.plupload_header_content_bw .plupload_logo { + background-position: -40px 0; +} + +.plupload_header_title { + font: normal 18px sans-serif; + line-height: 19px; + padding: 6px 0 3px; +} + +.plupload_header_text { + font: normal 12px sans-serif; +} + +.plupload_view_switch { + position: absolute; + right: 16px; + bottom: 8px; + margin: 0; + display: none; +} + +.plupload_view_switch .ui-button { + margin-right: -0.31em; +} + +.plupload_content { + position: absolute; + top: 86px; + bottom: 44px; + left: 0; + right: 0; + overflow-y: auto; + width: 100%; +} + +.plupload_filelist { + border-collapse: collapse; + border-left: none; + border-right: none; + margin: 0; + padding: 0; + width: 100%; + -moz-user-select: none; + -webkit-user-select: none; + user-select: none; +} + +.plupload_filelist_content { + padding: 0; + margin: 0; +} + +.plupload_cell {padding: 8px 6px;} + +.plupload_file { + list-style: none; + display: block; + position: relative; + overflow: hidden; + line-height: 12px; +} + +.plupload_file_thumb { + position: relative; + background-image: none; + background-color: #eee; +} + +.plupload_file_loading .plupload_file_thumb { + background: #eee url(../img/loading.gif) center no-repeat; +} + +.plupload_file_name { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.plupload_filelist_header { + border-top: none; +} + +.plupload_filelist_footer { + position: absolute; + bottom: 0; + left: 0; + right: 0; +} + +.plupload_buttons { + position: relative; +} + +/* list view */ +.plupload_view_list .plupload_file { + border-left: none; + border-right: none; + border-top: none; + height: 29px; + width: 100% !important; + /* fix IE6 vertical white-space bug */ + _float: left; + _clear: left; +} + +.plupload_view_list div.plupload_file_size, +.plupload_view_list div.plupload_file_status, +.plupload_view_list div.plupload_file_action { + padding: 8px 6px; + position: absolute; + top: 0; + right: 0; +} + +.plupload_view_list div.plupload_file_name { + margin-right: 156px; + padding: 8px 6px; + _width: 75%; +} + +.plupload_view_list div.plupload_file_size { + right: 28px; +} + +.plupload_view_list div.plupload_file_status { + right: 82px; +} + +.plupload_view_list .plupload_file_rename { + margin-left: -2px; +} + +.plupload_view_list .plupload_file_size, +.plupload_view_list .plupload_file_status, +.plupload_filelist_footer .plupload_file_size, +.plupload_filelist_footer .plupload_file_status { + text-align: right; + width: 52px; +} + +.plupload_view_list .plupload_file_thumb { + position: absolute; + top: -999px; +} + +.plupload_view_list .plupload_file_progress { + display: none; +} + + +/* thumbs view */ +.plupload_view_thumbs .plupload_content { + top: 57px; +} + +.plupload_view_thumbs .plupload_filelist_header { + display: none; +} + +.plupload_view_thumbs .plupload_file { + padding: 16px; + margin: 10px; + border: 1px solid #fff; + float: left; +} + +.plupload_view_thumbs .plupload_file_thumb, +.plupload_view_thumbs .plupload_file_dummy { + text-align: center; + overflow: hidden; +} + +.plupload_view_thumbs .plupload_file_dummy { + font-size: 21px; + font-weight: bold; + text-transform: lowercase; + overflow: hidden; + border: none; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +.plupload_view_thumbs div.plupload_file_action { + position: absolute; + top: 0; + right: 0; +} + +.plupload_view_thumbs div.plupload_file_name { + padding: 0; + font-weight: bold; +} + +.plupload_view_thumbs .plupload_file_rename { + padding: 1px 0; + width: 100% !important; +} + +.plupload_view_thumbs div.plupload_file_size { + font-size: 0.8em; + font-weight: normal; +} + +.plupload_view_thumbs div.plupload_file_status { + position: relative; + height: 3px; + overflow: hidden; + text-indent: -999px; + margin-bottom: 3px; +} + +.plupload_view_thumbs div.plupload_file_progress { + border: none; + height: 100%; +} + +.plupload .ui-sortable-helper, +.plupload .ui-sortable .plupload_file { + cursor:move; +} + +.plupload_file_action {width: 16px;} +.plupload_file_name { + overflow: hidden; + padding-left: 10px; +} + +.plupload_file_rename { + border: none; + font: normal 11px Verdana, sans-serif; + padding: 1px 2px; + line-height: 11px; + height: 11px; +} + +.plupload_progress {width: 60px;} +.plupload_progress_container {padding: 1px;} + + +/* Floats */ + +.plupload_right {float: right;} +.plupload_left {float: left;} +.plupload_clear,.plupload_clearer {clear: both;} +.plupload_clearer, .plupload_progress_bar { + display: block; + font-size: 0; + line-height: 0; +} +.plupload_clearer {height: 0;} + +/* Misc */ +.plupload_hidden {display: none !important;} + +.plupload_droptext { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: transparent; + text-align: center; + vertical-align: middle; + border: 0; + line-height: 160px; + display: none; +} + +.plupload_dropbox .plupload_droptext { + display: block; +} + +.plupload_buttons, .plupload_upload_status {float: left} + +.plupload_message { + position: absolute; + top: -1px; + left: -1px; + height: 100%; + width: 100%; +} + +.plupload_message p { + padding:0.7em; + margin:0; +} + +.plupload_message strong { + font-weight: bold; +} + +plupload_message i { + font-style: italic; +} + +.plupload_message p span.ui-icon { + float: left; + margin-right: 0.3em; +} + +.plupload_header_content .ui-state-error, +.plupload_header_content .ui-state-highlight { + border:none; +} + +.plupload_message_close { + position:absolute; + top:5px; + right:5px; + cursor:pointer; +} + +.plupload .ui-sortable-placeholder { + height:35px; +} diff --git a/themes/default/js/plugins/plupload/jquery.ui.plupload/css/jquery.ui.plupload.css.orig b/themes/default/js/plugins/plupload/jquery.ui.plupload/css/jquery.ui.plupload.css.orig new file mode 100644 index 000000000..87d54814d --- /dev/null +++ b/themes/default/js/plugins/plupload/jquery.ui.plupload/css/jquery.ui.plupload.css.orig @@ -0,0 +1,370 @@ +/* + Plupload +------------------------------------------------------------------- */ + +.plupload_wrapper * { + box-sizing: content-box; +} + +.plupload_button { + cursor: pointer; + outline: none; +} + +.plupload_wrapper { + font: normal 11px Verdana,sans-serif; + width: 100%; + min-width: 520px; + line-height: 12px; +} + +.plupload_container { + _height: 300px; + min-height: 300px; + position: relative; +} + +.plupload_filelist_footer {border-width: 1px 0 0 0} +.plupload_file {border-width: 0 0 1px 0} +.plupload_container .plupload_header {border-width: 0 0 1px 0; position: relative;} + +.plupload_delete .ui-icon, +.plupload_done .ui-icon, +.plupload_failed .ui-icon { + cursor:pointer; +} + +.plupload_header_content { + height: 56px; + padding: 0 160px 0 60px; + position: relative; +} + +.plupload_logo { + width: 40px; + height: 40px; + background: url('../img/plupload.png') no-repeat 0 0; + position: absolute; + top: 8px; + left: 8px; +} + +.plupload_header_content_bw .plupload_logo { + background-position: -40px 0; +} + +.plupload_header_title { + font: normal 18px sans-serif; + line-height: 19px; + padding: 6px 0 3px; +} + +.plupload_header_text { + font: normal 12px sans-serif; +} + +.plupload_view_switch { + position: absolute; + right: 16px; + bottom: 8px; + margin: 0; + display: none; +} + +.plupload_view_switch .ui-button { + margin-right: -0.31em; +} + +.plupload_content { + position: absolute; + top: 86px; + bottom: 44px; + left: 0; + right: 0; + overflow-y: auto; + width: 100%; +} + +.plupload_filelist { + border-collapse: collapse; + border-left: none; + border-right: none; + margin: 0; + padding: 0; + width: 100%; + -moz-user-select: none; + -webkit-user-select: none; + user-select: none; +} + +.plupload_filelist_content { + padding: 0; + margin: 0; +} + +.plupload_cell {padding: 8px 6px;} + +.plupload_file { + list-style: none; + display: block; + position: relative; + overflow: hidden; + line-height: 12px; +} + +.plupload_file_thumb { + position: relative; + background-image: none; + background-color: #eee; +} + +.plupload_file_loading .plupload_file_thumb { + background: #eee url(../img/loading.gif) center no-repeat; +} + +.plupload_file_name { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.plupload_filelist_header { + border-top: none; +} + +.plupload_filelist_footer { + position: absolute; + bottom: 0; + left: 0; + right: 0; +} + +.plupload_buttons { + position: relative; +} + +/* list view */ +.plupload_view_list .plupload_file { + border-left: none; + border-right: none; + border-top: none; + height: 29px; + width: 100% !important; + /* fix IE6 vertical white-space bug */ + _float: left; + _clear: left; +} + +.plupload_view_list div.plupload_file_size, +.plupload_view_list div.plupload_file_status, +.plupload_view_list div.plupload_file_action { + padding: 8px 6px; + position: absolute; + top: 0; + right: 0; +} + +.plupload_view_list div.plupload_file_name { + margin-right: 156px; + padding: 8px 6px; + _width: 75%; +} + +.plupload_view_list div.plupload_file_size { + right: 28px; +} + +.plupload_view_list div.plupload_file_status { + right: 82px; +} + +.plupload_view_list .plupload_file_rename { + margin-left: -2px; +} + +.plupload_view_list .plupload_file_size, +.plupload_view_list .plupload_file_status, +.plupload_filelist_footer .plupload_file_size, +.plupload_filelist_footer .plupload_file_status { + text-align: right; + width: 52px; +} + +.plupload_view_list .plupload_file_thumb { + position: absolute; + top: -999px; +} + +.plupload_view_list .plupload_file_progress { + display: none; +} + + +/* thumbs view */ +.plupload_view_thumbs .plupload_content { + top: 57px; +} + +.plupload_view_thumbs .plupload_filelist_header { + display: none; +} + +.plupload_view_thumbs .plupload_file { + padding: 16px; + margin: 10px; + border: 1px solid #fff; + float: left; +} + +.plupload_view_thumbs .plupload_file_thumb, +.plupload_view_thumbs .plupload_file_dummy { + text-align: center; + overflow: hidden; +} + +.plupload_view_thumbs .plupload_file_dummy { + font-size: 21px; + font-weight: bold; + text-transform: lowercase; + overflow: hidden; + border: none; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +.plupload_view_thumbs div.plupload_file_action { + position: absolute; + top: 0; + right: 0; +} + +.plupload_view_thumbs div.plupload_file_name { + padding: 0; + font-weight: bold; +} + +.plupload_view_thumbs .plupload_file_rename { + padding: 1px 0; + width: 100% !important; +} + +.plupload_view_thumbs div.plupload_file_size { + font-size: 0.8em; + font-weight: normal; +} + +.plupload_view_thumbs div.plupload_file_status { + position: relative; + height: 3px; + overflow: hidden; + text-indent: -999px; + margin-bottom: 3px; +} + +.plupload_view_thumbs div.plupload_file_progress { + border: none; + height: 100%; +} + +.plupload .ui-sortable-helper, +.plupload .ui-sortable .plupload_file { + cursor:move; +} + +.plupload_file_action {width: 16px;} +.plupload_file_name { + overflow: hidden; + padding-left: 10px; +} + +.plupload_file_rename { + border: none; + font: normal 11px Verdana, sans-serif; + padding: 1px 2px; + line-height: 11px; + height: 11px; +} + +.plupload_progress {width: 60px;} +.plupload_progress_container {padding: 1px;} + + +/* Floats */ + +.plupload_right {float: right;} +.plupload_left {float: left;} +.plupload_clear,.plupload_clearer {clear: both;} +.plupload_clearer, .plupload_progress_bar { + display: block; + font-size: 0; + line-height: 0; +} +.plupload_clearer {height: 0;} + +/* Misc */ +.plupload_hidden {display: none !important;} + +.plupload_droptext { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: transparent; + text-align: center; + vertical-align: middle; + border: 0; + line-height: 160px; + display: none; +} + +.plupload_dropbox .plupload_droptext { + display: block; +} + +.plupload_buttons, .plupload_upload_status {float: left} + +.plupload_message { + position: absolute; + top: -1px; + left: -1px; + height: 100%; + width: 100%; +} + +.plupload_message p { + padding:0.7em; + margin:0; +} + +.plupload_message strong { + font-weight: bold; +} + +plupload_message i { + font-style: italic; +} + +.plupload_message p span.ui-icon { + float: left; + margin-right: 0.3em; +} + +.plupload_header_content .ui-state-error, +.plupload_header_content .ui-state-highlight { + border:none; +} + +.plupload_message_close { + position:absolute; + top:5px; + right:5px; + cursor:pointer; +} + +.plupload .ui-sortable-placeholder { + height:35px; +} diff --git a/themes/default/js/plugins/plupload/jquery.ui.plupload/img/loading.gif b/themes/default/js/plugins/plupload/jquery.ui.plupload/img/loading.gif new file mode 100644 index 000000000..f0109d170 Binary files /dev/null and b/themes/default/js/plugins/plupload/jquery.ui.plupload/img/loading.gif differ diff --git a/themes/default/js/plugins/plupload/jquery.ui.plupload/img/plupload.png b/themes/default/js/plugins/plupload/jquery.ui.plupload/img/plupload.png new file mode 100644 index 000000000..8ae0f90b5 Binary files /dev/null and b/themes/default/js/plugins/plupload/jquery.ui.plupload/img/plupload.png differ diff --git a/themes/default/js/plugins/plupload/jquery.ui.plupload/jquery.ui.plupload.js b/themes/default/js/plugins/plupload/jquery.ui.plupload/jquery.ui.plupload.js new file mode 100644 index 000000000..af9193761 --- /dev/null +++ b/themes/default/js/plugins/plupload/jquery.ui.plupload/jquery.ui.plupload.js @@ -0,0 +1,1323 @@ +/** + * jquery.ui.plupload.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.button.js + * jquery.ui.progressbar.js + * + * Optionally: + * jquery.ui.sortable.js + */ + + /* global jQuery:true */ + +/** +jQuery UI based implementation of the Plupload API - multi-runtime file uploading API. + +To use the widget you must include _jQuery_ and _jQuery UI_ bundle (including `ui.core`, `ui.widget`, `ui.button`, +`ui.progressbar` and `ui.sortable`). + +In general the widget is designed the way that you do not usually need to do anything to it after you instantiate it. +But! You still can intervenue, to some extent, in case you need to. Although, due to the fact that widget is based on +_jQuery UI_ widget factory, there are some specifics. See examples below for more details. + +@example + +
      +

      Your browser doesn't have Flash, Silverlight or HTML5 support.

      +
      + + + +@example + // Invoking methods: + $('#uploader').plupload(options); + + // Display welcome message in the notification area + $('#uploader').plupload('notify', 'info', "This might be obvious, but you need to click 'Add Files' to add some files."); + +@example + // Subscribing to the events... + // ... on initialization: + $('#uploader').plupload({ + ... + viewchanged: function(event, args) { + // stuff ... + } + }); + // ... or after initialization + $('#uploader').on("viewchanged", function(event, args) { + // stuff ... + }); + +@class UI.Plupload +@constructor +@param {Object} settings For detailed information about each option check documentation. + @param {String} settings.url URL of the server-side upload handler. + @param {Number|String} [settings.chunk_size=0] Chunk size in bytes to slice the file into. Shorcuts with b, kb, mb, gb, tb suffixes also supported. `e.g. 204800 or "204800b" or "200kb"`. By default - disabled. + @param {String} [settings.file_data_name="file"] Name for the file field in Multipart formated message. + @param {Object} [settings.filters={}] Set of file type filters. + @param {Array} [settings.filters.mime_types=[]] List of file types to accept, each one defined by title and list of extensions. `e.g. {title : "Image files", extensions : "jpg,jpeg,gif,png"}`. Dispatches `plupload.FILE_EXTENSION_ERROR` + @param {String|Number} [settings.filters.max_file_size=0] Maximum file size that the user can pick, in bytes. Optionally supports b, kb, mb, gb, tb suffixes. `e.g. "10mb" or "1gb"`. By default - not set. Dispatches `plupload.FILE_SIZE_ERROR`. + @param {Boolean} [settings.filters.prevent_duplicates=false] Do not let duplicates into the queue. Dispatches `plupload.FILE_DUPLICATE_ERROR`. + @param {Number} [settings.filters.max_file_count=0] Limit the number of files that can reside in the queue at the same time (default is 0 - no limit). + @param {String} [settings.flash_swf_url] URL of the Flash swf. + @param {Object} [settings.headers] Custom headers to send with the upload. Hash of name/value pairs. + @param {Number|String} [settings.max_file_size] Maximum file size that the user can pick, in bytes. Optionally supports b, kb, mb, gb, tb suffixes. `e.g. "10mb" or "1gb"`. By default - not set. Dispatches `plupload.FILE_SIZE_ERROR`. + @param {Number} [settings.max_retries=0] How many times to retry the chunk or file, before triggering Error event. + @param {Boolean} [settings.multipart=true] Whether to send file and additional parameters as Multipart formated message. + @param {Object} [settings.multipart_params] Hash of key/value pairs to send with every file upload. + @param {Boolean} [settings.multi_selection=true] Enable ability to select multiple files at once in file dialog. + @param {Boolean} [settings.prevent_duplicates=false] Do not let duplicates into the queue. Dispatches `plupload.FILE_DUPLICATE_ERROR`. + @param {String|Object} [settings.required_features] Either comma-separated list or hash of required features that chosen runtime should absolutely possess. + @param {Object} [settings.resize] Enable resizng of images on client-side. Applies to `image/jpeg` and `image/png` only. `e.g. {width : 200, height : 200, quality : 90, crop: true}` + @param {Number} [settings.resize.width] If image is bigger, it will be resized. + @param {Number} [settings.resize.height] If image is bigger, it will be resized. + @param {Number} [settings.resize.quality=90] Compression quality for jpegs (1-100). + @param {Boolean} [settings.resize.crop=false] Whether to crop images to exact dimensions. By default they will be resized proportionally. + @param {String} [settings.runtimes="html5,flash,silverlight,html4"] Comma separated list of runtimes, that Plupload will try in turn, moving to the next if previous fails. + @param {String} [settings.silverlight_xap_url] URL of the Silverlight xap. + @param {Boolean} [settings.unique_names=false] If true will generate unique filenames for uploaded files. + + @param {Boolean} [settings.autostart=false] Whether to auto start uploading right after file selection. + @param {Boolean} [settings.dragdrop=true] Enable ability to add file to the queue by drag'n'dropping them from the desktop. + @param {Boolean} [settings.rename=false] Enable ability to rename files in the queue. + @param {Boolean} [settings.sortable=false] Enable ability to sort files in the queue, changing their uploading priority. + @param {Object} [settings.buttons] Control the visibility of functional buttons. + @param {Boolean} [settings.buttons.browse=true] Display browse button. + @param {Boolean} [settings.buttons.start=true] Display start button. + @param {Boolean} [settings.buttons.stop=true] Display stop button. + @param {Object} [settings.views] Control various views of the file queue. + @param {Boolean} [settings.views.list=true] Enable list view. + @param {Boolean} [settings.views.thumbs=false] Enable thumbs view. + @param {String} [settings.views.default='list'] Default view. + @param {Boolean} [settings.views.remember=true] Whether to remember the current view (requires jQuery Cookie plugin). + @param {Boolean} [settings.multiple_queues=true] Re-activate the widget after each upload procedure. +*/ +;(function(window, document, plupload, o, $) { + +/** +Dispatched when the widget is initialized and ready. + +@event ready +@param {plupload.Uploader} uploader Uploader instance sending the event. +*/ + +/** +Dispatched when file dialog is closed. + +@event selected +@param {plupload.Uploader} uploader Uploader instance sending the event. +@param {Array} files Array of selected files represented by plupload.File objects +*/ + +/** +Dispatched when file dialog is closed. + +@event removed +@param {plupload.Uploader} uploader Uploader instance sending the event. +@param {Array} files Array of removed files represented by plupload.File objects +*/ + +/** +Dispatched when upload is started. + +@event start +@param {plupload.Uploader} uploader Uploader instance sending the event. +*/ + +/** +Dispatched when upload is stopped. + +@event stop +@param {plupload.Uploader} uploader Uploader instance sending the event. +*/ + +/** +Dispatched during the upload process. + +@event progress +@param {plupload.Uploader} uploader Uploader instance sending the event. +@param {plupload.File} file File that is being uploaded (includes loaded and percent properties among others). + @param {Number} size Total file size in bytes. + @param {Number} loaded Number of bytes uploaded of the files total size. + @param {Number} percent Number of percentage uploaded of the file. +*/ + +/** +Dispatched when file is uploaded. + +@event uploaded +@param {plupload.Uploader} uploader Uploader instance sending the event. +@param {plupload.File} file File that was uploaded. + @param {Enum} status Status constant matching the plupload states QUEUED, UPLOADING, FAILED, DONE. +*/ + +/** +Dispatched when upload of the whole queue is complete. + +@event complete +@param {plupload.Uploader} uploader Uploader instance sending the event. +@param {Array} files Array of uploaded files represented by plupload.File objects +*/ + +/** +Dispatched when the view is changed, e.g. from `list` to `thumbs` or vice versa. + +@event viewchanged +@param {plupload.Uploader} uploader Uploader instance sending the event. +@param {String} type Current view type. +*/ + +/** +Dispatched when error of some kind is detected. + +@event error +@param {plupload.Uploader} uploader Uploader instance sending the event. +@param {String} error Error message. +@param {plupload.File} file File that was uploaded. + @param {Enum} status Status constant matching the plupload states QUEUED, UPLOADING, FAILED, DONE. +*/ + +var uploaders = {}; + +function _(str) { + return plupload.translate(str) || str; +} + +function renderUI(obj) { + obj.id = obj.attr('id'); + + obj.html( + '
      ' + + '
      ' + + '
      ' + + '
      ' + + '' + + '
      ' + _("Select files") + '
      ' + + '
      ' + _("Add files to the upload queue and click the start button.") + '
      ' + + '
      ' + + '' + + '' + + '
      ' + + '
      ' + + '
      ' + + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '
      ' + _('Filename') + '' + _('Status') + '' + _('Size') + ' 
      ' + + + '
      ' + + '
      ' + _("Drag files here.") + '
      ' + + '
      ' + + '
       
      ' + + '
      ' + + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + + '
      ' + + '' + + '
      ' + ); +} + + +$.widget("ui.plupload", { + + widgetEventPrefix: '', + + contents_bak: '', + + options: { + browse_button_hover: 'ui-state-hover', + browse_button_active: 'ui-state-active', + + filters: {}, + + // widget specific + buttons: { + browse: true, + start: true, + stop: true + }, + + views: { + list: true, + thumbs: false, + active: 'list', + remember: true // requires: https://github.com/carhartl/jquery-cookie, otherwise disabled even if set to true + }, + + thumb_width: 100, + thumb_height: 60, + + multiple_queues: true, // re-use widget by default + dragdrop : true, + autostart: false, + sortable: false, + rename: false + }, + + FILE_COUNT_ERROR: -9001, + + _create: function() { + var id = this.element.attr('id'); + if (!id) { + id = plupload.guid(); + this.element.attr('id', id); + } + this.id = id; + + // backup the elements initial state + this.contents_bak = this.element.html(); + renderUI(this.element); + + // container, just in case + this.container = $('.plupload_container', this.element).attr('id', id + '_container'); + + this.content = $('.plupload_content', this.element); + + if ($.fn.resizable) { + this.container.resizable({ + handles: 's', + minHeight: 300 + }); + } + + // list of files, may become sortable + this.filelist = $('.plupload_filelist_content', this.container) + .attr({ + id: id + '_filelist', + unselectable: 'on' + }); + + + // buttons + this.browse_button = $('.plupload_add', this.container).attr('id', id + '_browse'); + this.start_button = $('.plupload_start', this.container).attr('id', id + '_start'); + this.stop_button = $('.plupload_stop', this.container).attr('id', id + '_stop'); + this.thumbs_switcher = $('#' + id + '_view_thumbs'); + this.list_switcher = $('#' + id + '_view_list'); + + if ($.ui.button) { + this.browse_button.button({ + icons: { primary: 'ui-icon-circle-plus' }, + disabled: true + }); + + this.start_button.button({ + icons: { primary: 'ui-icon-circle-arrow-e' }, + disabled: true + }); + + this.stop_button.button({ + icons: { primary: 'ui-icon-circle-close' } + }); + + this.list_switcher.button({ + text: false, + icons: { secondary: "ui-icon-grip-dotted-horizontal" } + }); + + this.thumbs_switcher.button({ + text: false, + icons: { secondary: "ui-icon-image" } + }); + } + + // progressbar + this.progressbar = $('.plupload_progress_container', this.container); + + if ($.ui.progressbar) { + this.progressbar.progressbar(); + } + + // counter + this.counter = $('.plupload_count', this.element) + .attr({ + id: id + '_count', + name: id + '_count' + }); + + // initialize uploader instance + this._initUploader(); + }, + + _initUploader: function() { + var self = this + , id = this.id + , uploader + , options = { + container: id + '_buttons', + browse_button: id + '_browse' + } + ; + + $('.plupload_buttons', this.element).attr('id', id + '_buttons'); + + if (self.options.dragdrop) { + this.filelist.parent().attr('id', this.id + '_dropbox'); + options.drop_element = this.id + '_dropbox'; + } + + this.filelist.on('click', function(e) { + if ($(e.target).hasClass('plupload_action_icon')) { + self.removeFile($(e.target).closest('.plupload_file').attr('id')); + e.preventDefault(); + } + }); + + uploader = this.uploader = uploaders[id] = new plupload.Uploader($.extend(this.options, options)); + + if (self.options.views.thumbs) { + uploader.settings.required_features.display_media = true; + } + + // for backward compatibility + if (self.options.max_file_count) { + plupload.extend(uploader.getOption('filters'), { + max_file_count: self.options.max_file_count + }); + } + + plupload.addFileFilter('max_file_count', function(maxCount, file, cb) { + if (maxCount <= this.files.length - (this.total.uploaded + this.total.failed)) { + self.browse_button.button('disable'); + this.disableBrowse(); + + this.trigger('Error', { + code : self.FILE_COUNT_ERROR, + message : _("File count error."), + file : file + }); + cb(false); + } else { + cb(true); + } + }); + + + uploader.bind('Error', function(up, err) { + var message, details = ""; + + message = '' + err.message + ''; + + switch (err.code) { + case plupload.FILE_EXTENSION_ERROR: + details = o.sprintf(_("File: %s"), err.file.name); + break; + + case plupload.FILE_SIZE_ERROR: + details = o.sprintf(_("File: %s, size: %d, max file size: %d"), err.file.name, plupload.formatSize(err.file.size), plupload.formatSize(plupload.parseSize(up.getOption('filters').max_file_size))); + break; + + case plupload.FILE_DUPLICATE_ERROR: + details = o.sprintf(_("%s already present in the queue."), err.file.name); + break; + + case self.FILE_COUNT_ERROR: + details = o.sprintf(_("Upload element accepts only %d file(s) at a time. Extra files were stripped."), up.getOption('filters').max_file_count || 0); + break; + + case plupload.IMAGE_FORMAT_ERROR : + details = _("Image format either wrong or not supported."); + break; + + case plupload.IMAGE_MEMORY_ERROR : + details = _("Runtime ran out of available memory."); + break; + + /* // This needs a review + case plupload.IMAGE_DIMENSIONS_ERROR : + details = o.sprintf(_('Resoultion out of boundaries! %s runtime supports images only up to %wx%hpx.'), up.runtime, up.features.maxWidth, up.features.maxHeight); + break; */ + + case plupload.HTTP_ERROR: + details = _("Upload URL might be wrong or doesn't exist."); + break; + } + + message += "
      " + details + ""; + + self._trigger('error', null, { up: up, error: err } ); + + // do not show UI if no runtime can be initialized + if (err.code === plupload.INIT_ERROR) { + setTimeout(function() { + self.destroy(); + }, 1); + } else { + self.notify('error', message); + } + }); + + + uploader.bind('PostInit', function(up) { + // all buttons are optional, so they can be disabled and hidden + if (!self.options.buttons.browse) { + self.browse_button.button('disable').hide(); + up.disableBrowse(true); + } else { + self.browse_button.button('enable'); + } + + if (!self.options.buttons.start) { + self.start_button.button('disable').hide(); + } + + if (!self.options.buttons.stop) { + self.stop_button.button('disable').hide(); + } + + if (!self.options.unique_names && self.options.rename) { + self._enableRenaming(); + } + + if (self.options.dragdrop && up.features.dragdrop) { + self.filelist.parent().addClass('plupload_dropbox'); + } + + self._enableViewSwitcher(); + + self.start_button.click(function(e) { + if (!$(this).button('option', 'disabled')) { + self.start(); + } + e.preventDefault(); + }); + + self.stop_button.click(function(e) { + self.stop(); + e.preventDefault(); + }); + + self._trigger('ready', null, { up: up }); + }); + + // uploader internal events must run first + uploader.init(); + + uploader.bind('FileFiltered', function(up, file) { + self._addFiles(file); + }); + + uploader.bind('FilesAdded', function(up, files) { + self._trigger('selected', null, { up: up, files: files } ); + + // re-enable sortable + if (self.options.sortable && $.ui.sortable) { + self._enableSortingList(); + } + + self._trigger('updatelist', null, { filelist: self.filelist }); + + if (self.options.autostart) { + // set a little delay to make sure that QueueChanged triggered by the core has time to complete + setTimeout(function() { + self.start(); + }, 10); + } + }); + + uploader.bind('FilesRemoved', function(up, files) { + // destroy sortable if enabled + if ($.ui.sortable && self.options.sortable) { + $('tbody', self.filelist).sortable('destroy'); + } + + $.each(files, function(i, file) { + $('#' + file.id).toggle("highlight", function() { + $(this).remove(); + }); + }); + + if (up.files.length) { + // re-initialize sortable + if (self.options.sortable && $.ui.sortable) { + self._enableSortingList(); + } + } + + self._trigger('updatelist', null, { filelist: self.filelist }); + self._trigger('removed', null, { up: up, files: files } ); + }); + + uploader.bind('QueueChanged StateChanged', function() { + self._handleState(); + }); + + uploader.bind('UploadFile', function(up, file) { + self._handleFileStatus(file); + }); + + uploader.bind('FileUploaded', function(up, file) { + self._handleFileStatus(file); + self._trigger('uploaded', null, { up: up, file: file } ); + }); + + uploader.bind('UploadProgress', function(up, file) { + self._handleFileStatus(file); + self._updateTotalProgress(); + self._trigger('progress', null, { up: up, file: file } ); + }); + + uploader.bind('UploadComplete', function(up, files) { + self._addFormFields(); + self._trigger('complete', null, { up: up, files: files } ); + }); + }, + + + _setOption: function(key, value) { + var self = this; + + if (key == 'buttons' && typeof(value) == 'object') { + value = $.extend(self.options.buttons, value); + + if (!value.browse) { + self.browse_button.button('disable').hide(); + self.uploader.disableBrowse(true); + } else { + self.browse_button.button('enable').show(); + self.uploader.disableBrowse(false); + } + + if (!value.start) { + self.start_button.button('disable').hide(); + } else { + self.start_button.button('enable').show(); + } + + if (!value.stop) { + self.stop_button.button('disable').hide(); + } else { + self.start_button.button('enable').show(); + } + } + + self.uploader.settings[key] = value; + }, + + + /** + Start upload. Triggers `start` event. + + @method start + */ + start: function() { + this.uploader.start(); + this._trigger('start', null, { up: this.uploader }); + }, + + + /** + Stop upload. Triggers `stop` event. + + @method stop + */ + stop: function() { + this.uploader.stop(); + this._trigger('stop', null, { up: this.uploader }); + }, + + + /** + Enable browse button. + + @method enable + */ + enable: function() { + this.browse_button.button('enable'); + this.uploader.disableBrowse(false); + }, + + + /** + Disable browse button. + + @method disable + */ + disable: function() { + this.browse_button.button('disable'); + this.uploader.disableBrowse(true); + }, + + + /** + Retrieve file by it's unique id. + + @method getFile + @param {String} id Unique id of the file + @return {plupload.File} + */ + getFile: function(id) { + var file; + + if (typeof id === 'number') { + file = this.uploader.files[id]; + } else { + file = this.uploader.getFile(id); + } + return file; + }, + + /** + Return array of files currently in the queue. + + @method getFiles + @return {Array} Array of files in the queue represented by plupload.File objects + */ + getFiles: function() { + return this.uploader.files; + }, + + + /** + Remove the file from the queue. + + @method removeFile + @param {plupload.File|String} file File to remove, might be specified directly or by it's unique id + */ + removeFile: function(file) { + if (plupload.typeOf(file) === 'string') { + file = this.getFile(file); + } + this.uploader.removeFile(file); + }, + + + /** + Clear the file queue. + + @method clearQueue + */ + clearQueue: function() { + this.uploader.splice(); + }, + + + /** + Retrieve internal plupload.Uploader object (usually not required). + + @method getUploader + @return {plupload.Uploader} + */ + getUploader: function() { + return this.uploader; + }, + + + /** + Trigger refresh procedure, specifically browse_button re-measure and re-position operations. + Might get handy, when UI Widget is placed within the popup, that is constantly hidden and shown + again - without calling this method after each show operation, dialog trigger might get displaced + and disfunctional. + + @method refresh + */ + refresh: function() { + this.uploader.refresh(); + }, + + + /** + Display a message in notification area. + + @method notify + @param {Enum} type Type of the message, either `error` or `info` + @param {String} message The text message to display. + */ + notify: function(type, message) { + var popup = $( + '
      ' + + '' + + '

      ' + message + '

      ' + + '
      ' + ); + + popup + .addClass('ui-state-' + (type === 'error' ? 'error' : 'highlight')) + .find('p .ui-icon') + .addClass('ui-icon-' + (type === 'error' ? 'alert' : 'info')) + .end() + .find('.plupload_message_close') + .click(function() { + popup.remove(); + }) + .end(); + + $('.plupload_header', this.container).append(popup); + }, + + + /** + Destroy the widget, the uploader, free associated resources and bring back original html. + + @method destroy + */ + destroy: function() { + // destroy uploader instance + this.uploader.destroy(); + + // unbind all button events + $('.plupload_button', this.element).unbind(); + + // destroy buttons + if ($.ui.button) { + $('.plupload_add, .plupload_start, .plupload_stop', this.container) + .button('destroy'); + } + + // destroy progressbar + if ($.ui.progressbar) { + this.progressbar.progressbar('destroy'); + } + + // destroy sortable behavior + if ($.ui.sortable && this.options.sortable) { + $('tbody', this.filelist).sortable('destroy'); + } + + // restore the elements initial state + this.element + .empty() + .html(this.contents_bak); + this.contents_bak = ''; + + $.Widget.prototype.destroy.apply(this); + }, + + + _handleState: function() { + var up = this.uploader + , filesPending = up.files.length - (up.total.uploaded + up.total.failed) + , maxCount = up.getOption('filters').max_file_count || 0 + ; + + if (plupload.STARTED === up.state) { + $([]) + .add(this.stop_button) + .add('.plupload_started') + .removeClass('plupload_hidden'); + + this.start_button.button('disable'); + + if (!this.options.multiple_queues) { + this.browse_button.button('disable'); + up.disableBrowse(); + } + + $('.plupload_upload_status', this.element).html(o.sprintf(_('Uploaded %d/%d files'), up.total.uploaded, up.files.length)); + $('.plupload_header_content', this.element).addClass('plupload_header_content_bw'); + } + else if (plupload.STOPPED === up.state) { + $([]) + .add(this.stop_button) + .add('.plupload_started') + .addClass('plupload_hidden'); + + if (filesPending) { + this.start_button.button('enable'); + } else { + this.start_button.button('disable'); + } + + if (this.options.multiple_queues) { + $('.plupload_header_content', this.element).removeClass('plupload_header_content_bw'); + } + + // if max_file_count defined, only that many files can be queued at once + if (this.options.multiple_queues && maxCount && maxCount > filesPending) { + this.browse_button.button('enable'); + up.disableBrowse(false); + } + + this._updateTotalProgress(); + } + + if (up.total.queued === 0) { + $('.ui-button-text', this.browse_button).html(_('Add Files')); + } else { + $('.ui-button-text', this.browse_button).html(o.sprintf(_('%d files queued'), up.total.queued)); + } + + up.refresh(); + }, + + + _handleFileStatus: function(file) { + var $file = $('#' + file.id), actionClass, iconClass; + + // since this method might be called asynchronously, file row might not yet be rendered + if (!$file.length) { + return; + } + + switch (file.status) { + case plupload.DONE: + actionClass = 'plupload_done'; + iconClass = 'plupload_action_icon ui-icon ui-icon-circle-check'; + break; + + case plupload.FAILED: + actionClass = 'ui-state-error plupload_failed'; + iconClass = 'plupload_action_icon ui-icon ui-icon-alert'; + break; + + case plupload.QUEUED: + actionClass = 'plupload_delete'; + iconClass = 'plupload_action_icon ui-icon ui-icon-circle-minus'; + break; + + case plupload.UPLOADING: + actionClass = 'ui-state-highlight plupload_uploading'; + iconClass = 'plupload_action_icon ui-icon ui-icon-circle-arrow-w'; + + // scroll uploading file into the view if its bottom boundary is out of it + var scroller = $('.plupload_scroll', this.container) + , scrollTop = scroller.scrollTop() + , scrollerHeight = scroller.height() + , rowOffset = $file.position().top + $file.height() + ; + + if (scrollerHeight < rowOffset) { + scroller.scrollTop(scrollTop + rowOffset - scrollerHeight); + } + + // Set file specific progress + $file + .find('.plupload_file_percent') + .html(file.percent + '%') + .end() + .find('.plupload_file_progress') + .css('width', file.percent + '%') + .end() + .find('.plupload_file_size') + .html(plupload.formatSize(file.size)); + break; + } + actionClass += ' ui-state-default plupload_file'; + + $file + .attr('class', actionClass) + .find('.plupload_action_icon') + .attr('class', iconClass); + }, + + + _updateTotalProgress: function() { + var up = this.uploader; + + // Scroll to end of file list + this.filelist[0].scrollTop = this.filelist[0].scrollHeight; + + this.progressbar.progressbar('value', up.total.percent); + + this.element + .find('.plupload_total_status') + .html(up.total.percent + '%') + .end() + .find('.plupload_total_file_size') + .html(plupload.formatSize(up.total.size)) + .end() + .find('.plupload_upload_status') + .html(o.sprintf(_('Uploaded %d/%d files'), up.total.uploaded, up.files.length)); + }, + + + _displayThumbs: function() { + var self = this + , tw, th // thumb width/height + , cols + , num = 0 // number of simultaneously visible thumbs + , thumbs = [] // array of thumbs to preload at any given moment + , loading = false + ; + + if (!this.options.views.thumbs) { + return; + } + + + function onLast(el, eventName, cb) { + var timer; + + el.on(eventName, function() { + clearTimeout(timer); + timer = setTimeout(function() { + clearTimeout(timer); + cb(); + }, 300); + }); + } + + + // calculate number of simultaneously visible thumbs + function measure() { + if (!tw || !th) { + var wrapper = $('.plupload_file:eq(0)', self.filelist); + tw = wrapper.outerWidth(true); + th = wrapper.outerHeight(true); + } + + var aw = self.content.width(), ah = self.content.height(); + cols = Math.floor(aw / tw); + num = cols * (Math.ceil(ah / th) + 1); + } + + + function pickThumbsToLoad() { + // calculate index of virst visible thumb + var startIdx = Math.floor(self.content.scrollTop() / th) * cols; + // get potentially visible thumbs that are not yet visible + thumbs = $('.plupload_file', self.filelist) + .slice(startIdx, startIdx + num) + .filter('.plupload_file_loading') + .get(); + } + + + function init() { + function mpl() { // measure, pick, load + if (self.view_mode !== 'thumbs') { + return; + } + measure(); + pickThumbsToLoad(); + lazyLoad(); + } + + if ($.fn.resizable) { + onLast(self.container, 'resize', mpl); + } + + onLast(self.window, 'resize', mpl); + onLast(self.content, 'scroll', mpl); + + self.element.on('viewchanged selected', mpl); + + mpl(); + } + + + function preloadThumb(file, cb) { + var img = new o.Image(); + + img.onload = function() { + var thumb = $('#' + file.id + ' .plupload_file_thumb', self.filelist).html(''); + this.embed(thumb[0], { + width:  self.options.thumb_width, + height: self.options.thumb_height, + crop: true, + swf_url: o.resolveUrl(self.options.flash_swf_url), + xap_url: o.resolveUrl(self.options.silverlight_xap_url) + }); + }; + + img.bind("embedded error", function() { + $('#' + file.id, self.filelist).removeClass('plupload_file_loading'); + this.destroy(); + setTimeout(cb, 1); // detach, otherwise ui might hang (in SilverLight for example) + }); + + img.load(file.getSource()); + } + + + function lazyLoad() { + if (self.view_mode !== 'thumbs' || loading) { + return; + } + + pickThumbsToLoad(); + if (!thumbs.length) { + return; + } + + loading = true; + + preloadThumb(self.getFile($(thumbs.shift()).attr('id')), function() { + loading = false; + lazyLoad(); + }); + } + + // this has to run only once to measure structures and bind listeners + this.element.on('selected', function onselected() { + self.element.off('selected', onselected); + init(); + }); + }, + + + _addFiles: function(files) { + var self = this, file_html, html = ''; + + file_html = '
    • ' + + '
      ' + + '
      %ext%
      ' + + '
      ' + + '
      ' + + '
      ' + + '%percent% ' + + '
      ' + + '
      ' + + '%name% ' + + '
      ' + + '
      ' + + '
      ' + + '
      ' + + '
      %size%
      ' + + '
      ' + + '
    • '; + + if (plupload.typeOf(files) !== 'array') { + files = [files]; + } + + $.each(files, function(i, file) { + var ext = o.Mime.getFileExtension(file.name) || 'none'; + + html += file_html.replace(/%(\w+)%/g, function($0, $1) { + switch ($1) { + case 'thumb_width': + case 'thumb_height': + return self.options[$1]; + + case 'size': + return plupload.formatSize(file.size); + + case 'ext': + return ext; + + default: + return file[$1] || ''; + } + }); + }); + + self.filelist.append(html); + }, + + + _addFormFields: function() { + var self = this; + + // re-add from fresh + $('.plupload_file_fields', this.filelist).html(''); + + plupload.each(this.uploader.files, function(file, count) { + var fields = '' + , id = self.id + '_' + count + ; + + if (file.target_name) { + fields += ''; + } + fields += ''; + fields += ''; + + $('#' + file.id).find('.plupload_file_fields').html(fields); + }); + + this.counter.val(this.uploader.files.length); + }, + + + _viewChanged: function(view) { + // update or write a new cookie + if (this.options.views.remember && $.cookie) { + $.cookie('plupload_ui_view', view, { expires: 7, path: '/' }); + } + + // ugly fix for IE6 - make content area stretchable + if (o.Env.browser === 'IE' && o.Env.version < 7) { + this.content.attr('style', 'height:expression(document.getElementById("' + this.id + '_container' + '").clientHeight - ' + (view === 'list' ? 132 : 102) + ')'); + } + + this.container.removeClass('plupload_view_list plupload_view_thumbs').addClass('plupload_view_' + view); + this.view_mode = view; + this._trigger('viewchanged', null, { view: view }); + }, + + + _enableViewSwitcher: function() { + var self = this + , view + , switcher = $('.plupload_view_switch', this.container) + , buttons + , button + ; + + plupload.each(['list', 'thumbs'], function(view) { + if (!self.options.views[view]) { + switcher.find('[for="' + self.id + '_view_' + view + '"], #'+ self.id +'_view_' + view).remove(); + } + }); + + // check if any visible left + buttons = switcher.find('.plupload_button'); + + if (buttons.length === 1) { + switcher.hide(); + view = buttons.eq(0).data('view'); + this._viewChanged(view); + } else if ($.ui.button && buttons.length > 1) { + if (this.options.views.remember && $.cookie) { + view = $.cookie('plupload_ui_view'); + } + + // if wierd case, bail out to default + if (!~plupload.inArray(view, ['list', 'thumbs'])) { + view = this.options.views.active; + } + + switcher + .show() + .buttonset() + .find('.ui-button') + .click(function(e) { + view = $(this).data('view'); + self._viewChanged(view); + e.preventDefault(); // avoid auto scrolling to widget in IE and FF (see #850) + }); + + // if view not active - happens when switcher wasn't clicked manually + button = switcher.find('[for="' + self.id + '_view_'+view+'"]'); + if (button.length) { + button.trigger('click'); + } + } else { + switcher.show(); + this._viewChanged(this.options.views.active); + } + + // initialize thumb viewer if requested + if (this.options.views.thumbs) { + this._displayThumbs(); + } + }, + + + _enableRenaming: function() { + var self = this; + + this.filelist.dblclick(function(e) { + var nameSpan = $(e.target), nameInput, file, parts, name, ext = ""; + + if (!nameSpan.hasClass('plupload_file_name_wrapper')) { + return; + } + + // Get file name and split out name and extension + file = self.uploader.getFile(nameSpan.closest('.plupload_file')[0].id); + name = file.name; + parts = /^(.+)(\.[^.]+)$/.exec(name); + if (parts) { + name = parts[1]; + ext = parts[2]; + } + + // Display input element + nameInput = $('').width(nameSpan.width()).insertAfter(nameSpan.hide()); + nameInput.val(name).blur(function() { + nameSpan.show().parent().scrollLeft(0).end().next().remove(); + }).keydown(function(e) { + var nameInput = $(this); + + if ($.inArray(e.keyCode, [13, 27]) !== -1) { + e.preventDefault(); + + // Rename file and glue extension back on + if (e.keyCode === 13) { + file.name = nameInput.val() + ext; + nameSpan.html(file.name); + } + nameInput.blur(); + } + })[0].focus(); + }); + }, + + + _enableSortingList: function() { + var self = this; + + if ($('.plupload_file', this.filelist).length < 2) { + return; + } + + // destroy sortable if enabled + $('tbody', this.filelist).sortable('destroy'); + + // enable + this.filelist.sortable({ + items: '.plupload_delete', + + cancel: 'object, .plupload_clearer', + + stop: function() { + var files = []; + + $.each($(this).sortable('toArray'), function(i, id) { + files[files.length] = self.uploader.getFile(id); + }); + + files.unshift(files.length); + files.unshift(0); + + // re-populate files array + Array.prototype.splice.apply(self.uploader.files, files); + } + }); + } +}); + +} (window, document, plupload, mOxie, jQuery)); diff --git a/themes/default/js/plugins/plupload/jquery.ui.plupload/jquery.ui.plupload.min.js b/themes/default/js/plugins/plupload/jquery.ui.plupload/jquery.ui.plupload.min.js new file mode 100644 index 000000000..c276ad3fc --- /dev/null +++ b/themes/default/js/plugins/plupload/jquery.ui.plupload/jquery.ui.plupload.min.js @@ -0,0 +1 @@ +;(function(e,t,n,r,i){function o(e){return n.translate(e)||e}function u(e){e.id=e.attr("id"),e.html('
      '+o("Select files")+"
      "+'
      '+o("Add files to the upload queue and click the start button.")+"
      "+'
      '+'"+'"+"
      "+"
      "+"
      "+''+""+'"+'"+'"+''+""+"
      '+o("Filename")+"'+o("Status")+"'+o("Size")+" 
      "+'
      '+'
      '+o("Drag files here.")+"
      "+'
      '+'
       
      '+"
      "+''+""+'"+''+''+''+""+""+"
      "+''+"
      ")}var s={};i.widget("ui.plupload",{widgetEventPrefix:"",contents_bak:"",options:{browse_button_hover:"ui-state-hover",browse_button_active:"ui-state-active",filters:{},buttons:{browse:!0,start:!0,stop:!0},views:{list:!0,thumbs:!1,active:"list",remember:!0},thumb_width:100,thumb_height:60,multiple_queues:!0,dragdrop:!0,autostart:!1,sortable:!1,rename:!1},FILE_COUNT_ERROR:-9001,_create:function(){var e=this.element.attr("id");e||(e=n.guid(),this.element.attr("id",e)),this.id=e,this.contents_bak=this.element.html(),u(this.element),this.container=i(".plupload_container",this.element).attr("id",e+"_container"),this.content=i(".plupload_content",this.element),i.fn.resizable&&this.container.resizable({handles:"s",minHeight:300}),this.filelist=i(".plupload_filelist_content",this.container).attr({id:e+"_filelist",unselectable:"on"}),this.browse_button=i(".plupload_add",this.container).attr("id",e+"_browse"),this.start_button=i(".plupload_start",this.container).attr("id",e+"_start"),this.stop_button=i(".plupload_stop",this.container).attr("id",e+"_stop"),this.thumbs_switcher=i("#"+e+"_view_thumbs"),this.list_switcher=i("#"+e+"_view_list"),i.ui.button&&(this.browse_button.button({icons:{primary:"ui-icon-circle-plus"},disabled:!0}),this.start_button.button({icons:{primary:"ui-icon-circle-arrow-e"},disabled:!0}),this.stop_button.button({icons:{primary:"ui-icon-circle-close"}}),this.list_switcher.button({text:!1,icons:{secondary:"ui-icon-grip-dotted-horizontal"}}),this.thumbs_switcher.button({text:!1,icons:{secondary:"ui-icon-image"}})),this.progressbar=i(".plupload_progress_container",this.container),i.ui.progressbar&&this.progressbar.progressbar(),this.counter=i(".plupload_count",this.element).attr({id:e+"_count",name:e+"_count"}),this._initUploader()},_initUploader:function(){var e=this,t=this.id,u,a={container:t+"_buttons",browse_button:t+"_browse"};i(".plupload_buttons",this.element).attr("id",t+"_buttons"),e.options.dragdrop&&(this.filelist.parent().attr("id",this.id+"_dropbox"),a.drop_element=this.id+"_dropbox"),this.filelist.on("click",function(t){i(t.target).hasClass("plupload_action_icon")&&(e.removeFile(i(t.target).closest(".plupload_file").attr("id")),t.preventDefault())}),u=this.uploader=s[t]=new n.Uploader(i.extend(this.options,a)),e.options.views.thumbs&&(u.settings.required_features.display_media=!0),e.options.max_file_count&&n.extend(u.getOption("filters"),{max_file_count:e.options.max_file_count}),n.addFileFilter("max_file_count",function(t,n,r){t<=this.files.length-(this.total.uploaded+this.total.failed)?(e.browse_button.button("disable"),this.disableBrowse(),this.trigger("Error",{code:e.FILE_COUNT_ERROR,message:o("File count error."),file:n}),r(!1)):r(!0)}),u.bind("Error",function(t,i){var s,u="";s=""+i.message+"";switch(i.code){case n.FILE_EXTENSION_ERROR:u=r.sprintf(o("File: %s"),i.file.name);break;case n.FILE_SIZE_ERROR:u=r.sprintf(o("File: %s, size: %d, max file size: %d"),i.file.name,n.formatSize(i.file.size),n.formatSize(n.parseSize(t.getOption("filters").max_file_size)));break;case n.FILE_DUPLICATE_ERROR:u=r.sprintf(o("%s already present in the queue."),i.file.name);break;case e.FILE_COUNT_ERROR:u=r.sprintf(o("Upload element accepts only %d file(s) at a time. Extra files were stripped."),t.getOption("filters").max_file_count||0);break;case n.IMAGE_FORMAT_ERROR:u=o("Image format either wrong or not supported.");break;case n.IMAGE_MEMORY_ERROR:u=o("Runtime ran out of available memory.");break;case n.HTTP_ERROR:u=o("Upload URL might be wrong or doesn't exist.")}s+="
      "+u+"",e._trigger("error",null,{up:t,error:i}),i.code===n.INIT_ERROR?setTimeout(function(){e.destroy()},1):e.notify("error",s)}),u.bind("PostInit",function(t){e.options.buttons.browse?e.browse_button.button("enable"):(e.browse_button.button("disable").hide(),t.disableBrowse(!0)),e.options.buttons.start||e.start_button.button("disable").hide(),e.options.buttons.stop||e.stop_button.button("disable").hide(),!e.options.unique_names&&e.options.rename&&e._enableRenaming(),e.options.dragdrop&&t.features.dragdrop&&e.filelist.parent().addClass("plupload_dropbox"),e._enableViewSwitcher(),e.start_button.click(function(t){i(this).button("option","disabled")||e.start(),t.preventDefault()}),e.stop_button.click(function(t){e.stop(),t.preventDefault()}),e._trigger("ready",null,{up:t})}),u.init(),u.bind("FileFiltered",function(t,n){e._addFiles(n)}),u.bind("FilesAdded",function(t,n){e._trigger("selected",null,{up:t,files:n}),e.options.sortable&&i.ui.sortable&&e._enableSortingList(),e._trigger("updatelist",null,{filelist:e.filelist}),e.options.autostart&&setTimeout(function(){e.start()},10)}),u.bind("FilesRemoved",function(t,n){i.ui.sortable&&e.options.sortable&&i("tbody",e.filelist).sortable("destroy"),i.each(n,function(e,t){i("#"+t.id).toggle("highlight",function(){i(this).remove()})}),t.files.length&&e.options.sortable&&i.ui.sortable&&e._enableSortingList(),e._trigger("updatelist",null,{filelist:e.filelist}),e._trigger("removed",null,{up:t,files:n})}),u.bind("QueueChanged StateChanged",function(){e._handleState()}),u.bind("UploadFile",function(t,n){e._handleFileStatus(n)}),u.bind("FileUploaded",function(t,n){e._handleFileStatus(n),e._trigger("uploaded",null,{up:t,file:n})}),u.bind("UploadProgress",function(t,n){e._handleFileStatus(n),e._updateTotalProgress(),e._trigger("progress",null,{up:t,file:n})}),u.bind("UploadComplete",function(t,n){e._addFormFields(),e._trigger("complete",null,{up:t,files:n})})},_setOption:function(e,t){var n=this;e=="buttons"&&typeof t=="object"&&(t=i.extend(n.options.buttons,t),t.browse?(n.browse_button.button("enable").show(),n.uploader.disableBrowse(!1)):(n.browse_button.button("disable").hide(),n.uploader.disableBrowse(!0)),t.start?n.start_button.button("enable").show():n.start_button.button("disable").hide(),t.stop?n.start_button.button("enable").show():n.stop_button.button("disable").hide()),n.uploader.settings[e]=t},start:function(){this.uploader.start(),this._trigger("start",null,{up:this.uploader})},stop:function(){this.uploader.stop(),this._trigger("stop",null,{up:this.uploader})},enable:function(){this.browse_button.button("enable"),this.uploader.disableBrowse(!1)},disable:function(){this.browse_button.button("disable"),this.uploader.disableBrowse(!0)},getFile:function(e){var t;return typeof e=="number"?t=this.uploader.files[e]:t=this.uploader.getFile(e),t},getFiles:function(){return this.uploader.files},removeFile:function(e){n.typeOf(e)==="string"&&(e=this.getFile(e)),this.uploader.removeFile(e)},clearQueue:function(){this.uploader.splice()},getUploader:function(){return this.uploader},refresh:function(){this.uploader.refresh()},notify:function(e,t){var n=i('
      '+'

      '+t+"

      "+"
      ");n.addClass("ui-state-"+(e==="error"?"error":"highlight")).find("p .ui-icon").addClass("ui-icon-"+(e==="error"?"alert":"info")).end().find(".plupload_message_close").click(function(){n.remove()}).end(),i(".plupload_header",this.container).append(n)},destroy:function(){this.uploader.destroy(),i(".plupload_button",this.element).unbind(),i.ui.button&&i(".plupload_add, .plupload_start, .plupload_stop",this.container).button("destroy"),i.ui.progressbar&&this.progressbar.progressbar("destroy"),i.ui.sortable&&this.options.sortable&&i("tbody",this.filelist).sortable("destroy"),this.element.empty().html(this.contents_bak),this.contents_bak="",i.Widget.prototype.destroy.apply(this)},_handleState:function(){var e=this.uploader,t=e.files.length-(e.total.uploaded+e.total.failed),s=e.getOption("filters").max_file_count||0;n.STARTED===e.state?(i([]).add(this.stop_button).add(".plupload_started").removeClass("plupload_hidden"),this.start_button.button("disable"),this.options.multiple_queues||(this.browse_button.button("disable"),e.disableBrowse()),i(".plupload_upload_status",this.element).html(r.sprintf(o("Uploaded %d/%d files"),e.total.uploaded,e.files.length)),i(".plupload_header_content",this.element).addClass("plupload_header_content_bw")):n.STOPPED===e.state&&(i([]).add(this.stop_button).add(".plupload_started").addClass("plupload_hidden"),t?this.start_button.button("enable"):this.start_button.button("disable"),this.options.multiple_queues&&i(".plupload_header_content",this.element).removeClass("plupload_header_content_bw"),this.options.multiple_queues&&s&&s>t&&(this.browse_button.button("enable"),e.disableBrowse(!1)),this._updateTotalProgress()),e.total.queued===0?i(".ui-button-text",this.browse_button).html(o("Add Files")):i(".ui-button-text",this.browse_button).html(r.sprintf(o("%d files queued"),e.total.queued)),e.refresh()},_handleFileStatus:function(e){var t=i("#"+e.id),r,s;if(!t.length)return;switch(e.status){case n.DONE:r="plupload_done",s="plupload_action_icon ui-icon ui-icon-circle-check";break;case n.FAILED:r="ui-state-error plupload_failed",s="plupload_action_icon ui-icon ui-icon-alert";break;case n.QUEUED:r="plupload_delete",s="plupload_action_icon ui-icon ui-icon-circle-minus";break;case n.UPLOADING:r="ui-state-highlight plupload_uploading",s="plupload_action_icon ui-icon ui-icon-circle-arrow-w";var o=i(".plupload_scroll",this.container),u=o.scrollTop(),a=o.height(),f=t.position().top+t.height();a
      %ext%
      %percent%
      %name%
      %size%
      ',n.typeOf(e)!=="array"&&(e=[e]),i.each(e,function(e,i){var u=r.Mime.getFileExtension(i.name)||"none";o+=s.replace(/%(\w+)%/g,function(e,r){switch(r){case"thumb_width":case"thumb_height":return t.options[r];case"size":return n.formatSize(i.size);case"ext":return u;default:return i[r]||""}})}),t.filelist.append(o)},_addFormFields:function(){var e=this;i(".plupload_file_fields",this.filelist).html(""),n.each(this.uploader.files,function(t,r){var s="",o=e.id+"_"+r;t.target_name&&(s+=''),s+='',s+='',i("#"+t.id).find(".plupload_file_fields").html(s)}),this.counter.val(this.uploader.files.length)},_viewChanged:function(e){this.options.views.remember&&i.cookie&&i.cookie("plupload_ui_view",e,{expires:7,path:"/"}),r.Env.browser==="IE"&&r.Env.version<7&&this.content.attr("style",'height:expression(document.getElementById("'+this.id+"_container"+'").clientHeight - '+(e==="list"?132:102)+")"),this.container.removeClass("plupload_view_list plupload_view_thumbs").addClass("plupload_view_"+e),this.view_mode=e,this._trigger("viewchanged",null,{view:e})},_enableViewSwitcher:function(){var e=this,t,r=i(".plupload_view_switch",this.container),s,o;n.each(["list","thumbs"],function(t){e.options.views[t]||r.find('[for="'+e.id+"_view_"+t+'"], #'+e.id+"_view_"+t).remove()}),s=r.find(".plupload_button"),s.length===1?(r.hide(),t=s.eq(0).data("view"),this._viewChanged(t)):i.ui.button&&s.length>1?(this.options.views.remember&&i.cookie&&(t=i.cookie("plupload_ui_view")),~n.inArray(t,["list","thumbs"])||(t=this.options.views.active),r.show().buttonset().find(".ui-button").click(function(n){t=i(this).data("view"),e._viewChanged(t),n.preventDefault()}),o=r.find('[for="'+e.id+"_view_"+t+'"]'),o.length&&o.trigger("click")):(r.show(),this._viewChanged(this.options.views.active)),this.options.views.thumbs&&this._displayThumbs()},_enableRenaming:function(){var e=this;this.filelist.dblclick(function(t){var n=i(t.target),r,s,o,u,a="";if(!n.hasClass("plupload_file_name_wrapper"))return;s=e.uploader.getFile(n.closest(".plupload_file")[0].id),u=s.name,o=/^(.+)(\.[^.]+)$/.exec(u),o&&(u=o[1],a=o[2]),r=i('').width(n.width()).insertAfter(n.hide()),r.val(u).blur(function(){n.show().parent().scrollLeft(0).end().next().remove()}).keydown(function(e){var t=i(this);i.inArray(e.keyCode,[13,27])!==-1&&(e.preventDefault(),e.keyCode===13&&(s.name=t.val()+a,n.html(s.name)),t.blur())})[0].focus()})},_enableSortingList:function(){var e=this;if(i(".plupload_file",this.filelist).length<2)return;i("tbody",this.filelist).sortable("destroy"),this.filelist.sortable({items:".plupload_delete",cancel:"object, .plupload_clearer",stop:function(){var t=[];i.each(i(this).sortable("toArray"),function(n,r){t[t.length]=e.uploader.getFile(r)}),t.unshift(t.length),t.unshift(0),Array.prototype.splice.apply(e.uploader.files,t)}})}})})(window,document,plupload,mOxie,jQuery); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/moxie.js b/themes/default/js/plugins/plupload/moxie.js new file mode 100644 index 000000000..51c72cb5a --- /dev/null +++ b/themes/default/js/plugins/plupload/moxie.js @@ -0,0 +1,10726 @@ +/** + * mOxie - multi-runtime File API & XMLHttpRequest L2 Polyfill + * v1.2.1 + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + * + * Date: 2014-05-14 + */ +/** + * Compiled inline version. (Library mode) + */ + +/*jshint smarttabs:true, undef:true, latedef:true, curly:true, bitwise:true, camelcase:true */ +/*globals $code */ + +(function(exports, undefined) { + "use strict"; + + var modules = {}; + + function require(ids, callback) { + var module, defs = []; + + for (var i = 0; i < ids.length; ++i) { + module = modules[ids[i]] || resolve(ids[i]); + if (!module) { + throw 'module definition dependecy not found: ' + ids[i]; + } + + defs.push(module); + } + + callback.apply(null, defs); + } + + function define(id, dependencies, definition) { + if (typeof id !== 'string') { + throw 'invalid module definition, module id must be defined and be a string'; + } + + if (dependencies === undefined) { + throw 'invalid module definition, dependencies must be specified'; + } + + if (definition === undefined) { + throw 'invalid module definition, definition function must be specified'; + } + + require(dependencies, function() { + modules[id] = definition.apply(null, arguments); + }); + } + + function defined(id) { + return !!modules[id]; + } + + function resolve(id) { + var target = exports; + var fragments = id.split(/[.\/]/); + + for (var fi = 0; fi < fragments.length; ++fi) { + if (!target[fragments[fi]]) { + return; + } + + target = target[fragments[fi]]; + } + + return target; + } + + function expose(ids) { + for (var i = 0; i < ids.length; i++) { + var target = exports; + var id = ids[i]; + var fragments = id.split(/[.\/]/); + + for (var fi = 0; fi < fragments.length - 1; ++fi) { + if (target[fragments[fi]] === undefined) { + target[fragments[fi]] = {}; + } + + target = target[fragments[fi]]; + } + + target[fragments[fragments.length - 1]] = modules[id]; + } + } + +// Included from: src/javascript/core/utils/Basic.js + +/** + * Basic.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define('moxie/core/utils/Basic', [], function() { + /** + Gets the true type of the built-in object (better version of typeof). + @author Angus Croll (http://javascriptweblog.wordpress.com/) + + @method typeOf + @for Utils + @static + @param {Object} o Object to check. + @return {String} Object [[Class]] + */ + var typeOf = function(o) { + var undef; + + if (o === undef) { + return 'undefined'; + } else if (o === null) { + return 'null'; + } else if (o.nodeType) { + return 'node'; + } + + // the snippet below is awesome, however it fails to detect null, undefined and arguments types in IE lte 8 + return ({}).toString.call(o).match(/\s([a-z|A-Z]+)/)[1].toLowerCase(); + }; + + /** + Extends the specified object with another object. + + @method extend + @static + @param {Object} target Object to extend. + @param {Object} [obj]* Multiple objects to extend with. + @return {Object} Same as target, the extended object. + */ + var extend = function(target) { + var undef; + + each(arguments, function(arg, i) { + if (i > 0) { + each(arg, function(value, key) { + if (value !== undef) { + if (typeOf(target[key]) === typeOf(value) && !!~inArray(typeOf(value), ['array', 'object'])) { + extend(target[key], value); + } else { + target[key] = value; + } + } + }); + } + }); + return target; + }; + + /** + Executes the callback function for each item in array/object. If you return false in the + callback it will break the loop. + + @method each + @static + @param {Object} obj Object to iterate. + @param {function} callback Callback function to execute for each item. + */ + var each = function(obj, callback) { + var length, key, i, undef; + + if (obj) { + try { + length = obj.length; + } catch(ex) { + length = undef; + } + + if (length === undef) { + // Loop object items + for (key in obj) { + if (obj.hasOwnProperty(key)) { + if (callback(obj[key], key) === false) { + return; + } + } + } + } else { + // Loop array items + for (i = 0; i < length; i++) { + if (callback(obj[i], i) === false) { + return; + } + } + } + } + }; + + /** + Checks if object is empty. + + @method isEmptyObj + @static + @param {Object} o Object to check. + @return {Boolean} + */ + var isEmptyObj = function(obj) { + var prop; + + if (!obj || typeOf(obj) !== 'object') { + return true; + } + + for (prop in obj) { + return false; + } + + return true; + }; + + /** + Recieve an array of functions (usually async) to call in sequence, each function + receives a callback as first argument that it should call, when it completes. Finally, + after everything is complete, main callback is called. Passing truthy value to the + callback as a first argument will interrupt the sequence and invoke main callback + immediately. + + @method inSeries + @static + @param {Array} queue Array of functions to call in sequence + @param {Function} cb Main callback that is called in the end, or in case of error + */ + var inSeries = function(queue, cb) { + var i = 0, length = queue.length; + + if (typeOf(cb) !== 'function') { + cb = function() {}; + } + + if (!queue || !queue.length) { + cb(); + } + + function callNext(i) { + if (typeOf(queue[i]) === 'function') { + queue[i](function(error) { + /*jshint expr:true */ + ++i < length && !error ? callNext(i) : cb(error); + }); + } + } + callNext(i); + }; + + + /** + Recieve an array of functions (usually async) to call in parallel, each function + receives a callback as first argument that it should call, when it completes. After + everything is complete, main callback is called. Passing truthy value to the + callback as a first argument will interrupt the process and invoke main callback + immediately. + + @method inParallel + @static + @param {Array} queue Array of functions to call in sequence + @param {Function} cb Main callback that is called in the end, or in case of erro + */ + var inParallel = function(queue, cb) { + var count = 0, num = queue.length, cbArgs = new Array(num); + + each(queue, function(fn, i) { + fn(function(error) { + if (error) { + return cb(error); + } + + var args = [].slice.call(arguments); + args.shift(); // strip error - undefined or not + + cbArgs[i] = args; + count++; + + if (count === num) { + cbArgs.unshift(null); + cb.apply(this, cbArgs); + } + }); + }); + }; + + + /** + Find an element in array and return it's index if present, otherwise return -1. + + @method inArray + @static + @param {Mixed} needle Element to find + @param {Array} array + @return {Int} Index of the element, or -1 if not found + */ + var inArray = function(needle, array) { + if (array) { + if (Array.prototype.indexOf) { + return Array.prototype.indexOf.call(array, needle); + } + + for (var i = 0, length = array.length; i < length; i++) { + if (array[i] === needle) { + return i; + } + } + } + return -1; + }; + + + /** + Returns elements of first array if they are not present in second. And false - otherwise. + + @private + @method arrayDiff + @param {Array} needles + @param {Array} array + @return {Array|Boolean} + */ + var arrayDiff = function(needles, array) { + var diff = []; + + if (typeOf(needles) !== 'array') { + needles = [needles]; + } + + if (typeOf(array) !== 'array') { + array = [array]; + } + + for (var i in needles) { + if (inArray(needles[i], array) === -1) { + diff.push(needles[i]); + } + } + return diff.length ? diff : false; + }; + + + /** + Find intersection of two arrays. + + @private + @method arrayIntersect + @param {Array} array1 + @param {Array} array2 + @return {Array} Intersection of two arrays or null if there is none + */ + var arrayIntersect = function(array1, array2) { + var result = []; + each(array1, function(item) { + if (inArray(item, array2) !== -1) { + result.push(item); + } + }); + return result.length ? result : null; + }; + + + /** + Forces anything into an array. + + @method toArray + @static + @param {Object} obj Object with length field. + @return {Array} Array object containing all items. + */ + var toArray = function(obj) { + var i, arr = []; + + for (i = 0; i < obj.length; i++) { + arr[i] = obj[i]; + } + + return arr; + }; + + + /** + Generates an unique ID. This is 99.99% unique since it takes the current time and 5 random numbers. + The only way a user would be able to get the same ID is if the two persons at the same exact milisecond manages + to get 5 the same random numbers between 0-65535 it also uses a counter so each call will be guaranteed to be page unique. + It's more probable for the earth to be hit with an ansteriod. Y + + @method guid + @static + @param {String} prefix to prepend (by default 'o' will be prepended). + @method guid + @return {String} Virtually unique id. + */ + var guid = (function() { + var counter = 0; + + return function(prefix) { + var guid = new Date().getTime().toString(32), i; + + for (i = 0; i < 5; i++) { + guid += Math.floor(Math.random() * 65535).toString(32); + } + + return (prefix || 'o_') + guid + (counter++).toString(32); + }; + }()); + + + /** + Trims white spaces around the string + + @method trim + @static + @param {String} str + @return {String} + */ + var trim = function(str) { + if (!str) { + return str; + } + return String.prototype.trim ? String.prototype.trim.call(str) : str.toString().replace(/^\s*/, '').replace(/\s*$/, ''); + }; + + + /** + Parses the specified size string into a byte value. For example 10kb becomes 10240. + + @method parseSizeStr + @static + @param {String/Number} size String to parse or number to just pass through. + @return {Number} Size in bytes. + */ + var parseSizeStr = function(size) { + if (typeof(size) !== 'string') { + return size; + } + + var muls = { + t: 1099511627776, + g: 1073741824, + m: 1048576, + k: 1024 + }, + mul; + + size = /^([0-9]+)([mgk]?)$/.exec(size.toLowerCase().replace(/[^0-9mkg]/g, '')); + mul = size[2]; + size = +size[1]; + + if (muls.hasOwnProperty(mul)) { + size *= muls[mul]; + } + return size; + }; + + + return { + guid: guid, + typeOf: typeOf, + extend: extend, + each: each, + isEmptyObj: isEmptyObj, + inSeries: inSeries, + inParallel: inParallel, + inArray: inArray, + arrayDiff: arrayDiff, + arrayIntersect: arrayIntersect, + toArray: toArray, + trim: trim, + parseSizeStr: parseSizeStr + }; +}); + +// Included from: src/javascript/core/I18n.js + +/** + * I18n.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define("moxie/core/I18n", [ + "moxie/core/utils/Basic" +], function(Basic) { + var i18n = {}; + + return { + /** + * Extends the language pack object with new items. + * + * @param {Object} pack Language pack items to add. + * @return {Object} Extended language pack object. + */ + addI18n: function(pack) { + return Basic.extend(i18n, pack); + }, + + /** + * Translates the specified string by checking for the english string in the language pack lookup. + * + * @param {String} str String to look for. + * @return {String} Translated string or the input string if it wasn't found. + */ + translate: function(str) { + return i18n[str] || str; + }, + + /** + * Shortcut for translate function + * + * @param {String} str String to look for. + * @return {String} Translated string or the input string if it wasn't found. + */ + _: function(str) { + return this.translate(str); + }, + + /** + * Pseudo sprintf implementation - simple way to replace tokens with specified values. + * + * @param {String} str String with tokens + * @return {String} String with replaced tokens + */ + sprintf: function(str) { + var args = [].slice.call(arguments, 1); + + return str.replace(/%[a-z]/g, function() { + var value = args.shift(); + return Basic.typeOf(value) !== 'undefined' ? value : ''; + }); + } + }; +}); + +// Included from: src/javascript/core/utils/Mime.js + +/** + * Mime.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define("moxie/core/utils/Mime", [ + "moxie/core/utils/Basic", + "moxie/core/I18n" +], function(Basic, I18n) { + + var mimeData = "" + + "application/msword,doc dot," + + "application/pdf,pdf," + + "application/pgp-signature,pgp," + + "application/postscript,ps ai eps," + + "application/rtf,rtf," + + "application/vnd.ms-excel,xls xlb," + + "application/vnd.ms-powerpoint,ppt pps pot," + + "application/zip,zip," + + "application/x-shockwave-flash,swf swfl," + + "application/vnd.openxmlformats-officedocument.wordprocessingml.document,docx," + + "application/vnd.openxmlformats-officedocument.wordprocessingml.template,dotx," + + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,xlsx," + + "application/vnd.openxmlformats-officedocument.presentationml.presentation,pptx," + + "application/vnd.openxmlformats-officedocument.presentationml.template,potx," + + "application/vnd.openxmlformats-officedocument.presentationml.slideshow,ppsx," + + "application/x-javascript,js," + + "application/json,json," + + "audio/mpeg,mp3 mpga mpega mp2," + + "audio/x-wav,wav," + + "audio/x-m4a,m4a," + + "audio/ogg,oga ogg," + + "audio/aiff,aiff aif," + + "audio/flac,flac," + + "audio/aac,aac," + + "audio/ac3,ac3," + + "audio/x-ms-wma,wma," + + "image/bmp,bmp," + + "image/gif,gif," + + "image/jpeg,jpg jpeg jpe," + + "image/photoshop,psd," + + "image/png,png," + + "image/svg+xml,svg svgz," + + "image/tiff,tiff tif," + + "text/plain,asc txt text diff log," + + "text/html,htm html xhtml," + + "text/css,css," + + "text/csv,csv," + + "text/rtf,rtf," + + "video/mpeg,mpeg mpg mpe m2v," + + "video/quicktime,qt mov," + + "video/mp4,mp4," + + "video/x-m4v,m4v," + + "video/x-flv,flv," + + "video/x-ms-wmv,wmv," + + "video/avi,avi," + + "video/webm,webm," + + "video/3gpp,3gpp 3gp," + + "video/3gpp2,3g2," + + "video/vnd.rn-realvideo,rv," + + "video/ogg,ogv," + + "video/x-matroska,mkv," + + "application/vnd.oasis.opendocument.formula-template,otf," + + "application/octet-stream,exe"; + + + var Mime = { + + mimes: {}, + + extensions: {}, + + // Parses the default mime types string into a mimes and extensions lookup maps + addMimeType: function (mimeData) { + var items = mimeData.split(/,/), i, ii, ext; + + for (i = 0; i < items.length; i += 2) { + ext = items[i + 1].split(/ /); + + // extension to mime lookup + for (ii = 0; ii < ext.length; ii++) { + this.mimes[ext[ii]] = items[i]; + } + // mime to extension lookup + this.extensions[items[i]] = ext; + } + }, + + + extList2mimes: function (filters, addMissingExtensions) { + var self = this, ext, i, ii, type, mimes = []; + + // convert extensions to mime types list + for (i = 0; i < filters.length; i++) { + ext = filters[i].extensions.split(/\s*,\s*/); + + for (ii = 0; ii < ext.length; ii++) { + + // if there's an asterisk in the list, then accept attribute is not required + if (ext[ii] === '*') { + return []; + } + + type = self.mimes[ext[ii]]; + if (!type) { + if (addMissingExtensions && /^\w+$/.test(ext[ii])) { + mimes.push('.' + ext[ii]); + } else { + return []; // accept all + } + } else if (Basic.inArray(type, mimes) === -1) { + mimes.push(type); + } + } + } + return mimes; + }, + + + mimes2exts: function(mimes) { + var self = this, exts = []; + + Basic.each(mimes, function(mime) { + if (mime === '*') { + exts = []; + return false; + } + + // check if this thing looks like mime type + var m = mime.match(/^(\w+)\/(\*|\w+)$/); + if (m) { + if (m[2] === '*') { + // wildcard mime type detected + Basic.each(self.extensions, function(arr, mime) { + if ((new RegExp('^' + m[1] + '/')).test(mime)) { + [].push.apply(exts, self.extensions[mime]); + } + }); + } else if (self.extensions[mime]) { + [].push.apply(exts, self.extensions[mime]); + } + } + }); + return exts; + }, + + + mimes2extList: function(mimes) { + var accept = [], exts = []; + + if (Basic.typeOf(mimes) === 'string') { + mimes = Basic.trim(mimes).split(/\s*,\s*/); + } + + exts = this.mimes2exts(mimes); + + accept.push({ + title: I18n.translate('Files'), + extensions: exts.length ? exts.join(',') : '*' + }); + + // save original mimes string + accept.mimes = mimes; + + return accept; + }, + + + getFileExtension: function(fileName) { + var matches = fileName && fileName.match(/\.([^.]+)$/); + if (matches) { + return matches[1].toLowerCase(); + } + return ''; + }, + + getFileMime: function(fileName) { + return this.mimes[this.getFileExtension(fileName)] || ''; + } + }; + + Mime.addMimeType(mimeData); + + return Mime; +}); + +// Included from: src/javascript/core/utils/Env.js + +/** + * Env.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define("moxie/core/utils/Env", [ + "moxie/core/utils/Basic" +], function(Basic) { + + // UAParser.js v0.6.2 + // Lightweight JavaScript-based User-Agent string parser + // https://github.com/faisalman/ua-parser-js + // + // Copyright © 2012-2013 Faisalman + // Dual licensed under GPLv2 & MIT + + var UAParser = (function (undefined) { + + ////////////// + // Constants + ///////////// + + + var EMPTY = '', + UNKNOWN = '?', + FUNC_TYPE = 'function', + UNDEF_TYPE = 'undefined', + OBJ_TYPE = 'object', + MAJOR = 'major', + MODEL = 'model', + NAME = 'name', + TYPE = 'type', + VENDOR = 'vendor', + VERSION = 'version', + ARCHITECTURE= 'architecture', + CONSOLE = 'console', + MOBILE = 'mobile', + TABLET = 'tablet'; + + + /////////// + // Helper + ////////// + + + var util = { + has : function (str1, str2) { + return str2.toLowerCase().indexOf(str1.toLowerCase()) !== -1; + }, + lowerize : function (str) { + return str.toLowerCase(); + } + }; + + + /////////////// + // Map helper + ////////////// + + + var mapper = { + + rgx : function () { + + // loop through all regexes maps + for (var result, i = 0, j, k, p, q, matches, match, args = arguments; i < args.length; i += 2) { + + var regex = args[i], // even sequence (0,2,4,..) + props = args[i + 1]; // odd sequence (1,3,5,..) + + // construct object barebones + if (typeof(result) === UNDEF_TYPE) { + result = {}; + for (p in props) { + q = props[p]; + if (typeof(q) === OBJ_TYPE) { + result[q[0]] = undefined; + } else { + result[q] = undefined; + } + } + } + + // try matching uastring with regexes + for (j = k = 0; j < regex.length; j++) { + matches = regex[j].exec(this.getUA()); + if (!!matches) { + for (p = 0; p < props.length; p++) { + match = matches[++k]; + q = props[p]; + // check if given property is actually array + if (typeof(q) === OBJ_TYPE && q.length > 0) { + if (q.length == 2) { + if (typeof(q[1]) == FUNC_TYPE) { + // assign modified match + result[q[0]] = q[1].call(this, match); + } else { + // assign given value, ignore regex match + result[q[0]] = q[1]; + } + } else if (q.length == 3) { + // check whether function or regex + if (typeof(q[1]) === FUNC_TYPE && !(q[1].exec && q[1].test)) { + // call function (usually string mapper) + result[q[0]] = match ? q[1].call(this, match, q[2]) : undefined; + } else { + // sanitize match using given regex + result[q[0]] = match ? match.replace(q[1], q[2]) : undefined; + } + } else if (q.length == 4) { + result[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined; + } + } else { + result[q] = match ? match : undefined; + } + } + break; + } + } + + if(!!matches) break; // break the loop immediately if match found + } + return result; + }, + + str : function (str, map) { + + for (var i in map) { + // check if array + if (typeof(map[i]) === OBJ_TYPE && map[i].length > 0) { + for (var j = 0; j < map[i].length; j++) { + if (util.has(map[i][j], str)) { + return (i === UNKNOWN) ? undefined : i; + } + } + } else if (util.has(map[i], str)) { + return (i === UNKNOWN) ? undefined : i; + } + } + return str; + } + }; + + + /////////////// + // String map + ////////////// + + + var maps = { + + browser : { + oldsafari : { + major : { + '1' : ['/8', '/1', '/3'], + '2' : '/4', + '?' : '/' + }, + version : { + '1.0' : '/8', + '1.2' : '/1', + '1.3' : '/3', + '2.0' : '/412', + '2.0.2' : '/416', + '2.0.3' : '/417', + '2.0.4' : '/419', + '?' : '/' + } + } + }, + + device : { + sprint : { + model : { + 'Evo Shift 4G' : '7373KT' + }, + vendor : { + 'HTC' : 'APA', + 'Sprint' : 'Sprint' + } + } + }, + + os : { + windows : { + version : { + 'ME' : '4.90', + 'NT 3.11' : 'NT3.51', + 'NT 4.0' : 'NT4.0', + '2000' : 'NT 5.0', + 'XP' : ['NT 5.1', 'NT 5.2'], + 'Vista' : 'NT 6.0', + '7' : 'NT 6.1', + '8' : 'NT 6.2', + '8.1' : 'NT 6.3', + 'RT' : 'ARM' + } + } + } + }; + + + ////////////// + // Regex map + ///////////// + + + var regexes = { + + browser : [[ + + // Presto based + /(opera\smini)\/((\d+)?[\w\.-]+)/i, // Opera Mini + /(opera\s[mobiletab]+).+version\/((\d+)?[\w\.-]+)/i, // Opera Mobi/Tablet + /(opera).+version\/((\d+)?[\w\.]+)/i, // Opera > 9.80 + /(opera)[\/\s]+((\d+)?[\w\.]+)/i // Opera < 9.80 + + ], [NAME, VERSION, MAJOR], [ + + /\s(opr)\/((\d+)?[\w\.]+)/i // Opera Webkit + ], [[NAME, 'Opera'], VERSION, MAJOR], [ + + // Mixed + /(kindle)\/((\d+)?[\w\.]+)/i, // Kindle + /(lunascape|maxthon|netfront|jasmine|blazer)[\/\s]?((\d+)?[\w\.]+)*/i, + // Lunascape/Maxthon/Netfront/Jasmine/Blazer + + // Trident based + /(avant\s|iemobile|slim|baidu)(?:browser)?[\/\s]?((\d+)?[\w\.]*)/i, + // Avant/IEMobile/SlimBrowser/Baidu + /(?:ms|\()(ie)\s((\d+)?[\w\.]+)/i, // Internet Explorer + + // Webkit/KHTML based + /(rekonq)((?:\/)[\w\.]+)*/i, // Rekonq + /(chromium|flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron)\/((\d+)?[\w\.-]+)/i + // Chromium/Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron + ], [NAME, VERSION, MAJOR], [ + + /(trident).+rv[:\s]((\d+)?[\w\.]+).+like\sgecko/i // IE11 + ], [[NAME, 'IE'], VERSION, MAJOR], [ + + /(yabrowser)\/((\d+)?[\w\.]+)/i // Yandex + ], [[NAME, 'Yandex'], VERSION, MAJOR], [ + + /(comodo_dragon)\/((\d+)?[\w\.]+)/i // Comodo Dragon + ], [[NAME, /_/g, ' '], VERSION, MAJOR], [ + + /(chrome|omniweb|arora|[tizenoka]{5}\s?browser)\/v?((\d+)?[\w\.]+)/i + // Chrome/OmniWeb/Arora/Tizen/Nokia + ], [NAME, VERSION, MAJOR], [ + + /(dolfin)\/((\d+)?[\w\.]+)/i // Dolphin + ], [[NAME, 'Dolphin'], VERSION, MAJOR], [ + + /((?:android.+)crmo|crios)\/((\d+)?[\w\.]+)/i // Chrome for Android/iOS + ], [[NAME, 'Chrome'], VERSION, MAJOR], [ + + /((?:android.+))version\/((\d+)?[\w\.]+)\smobile\ssafari/i // Android Browser + ], [[NAME, 'Android Browser'], VERSION, MAJOR], [ + + /version\/((\d+)?[\w\.]+).+?mobile\/\w+\s(safari)/i // Mobile Safari + ], [VERSION, MAJOR, [NAME, 'Mobile Safari']], [ + + /version\/((\d+)?[\w\.]+).+?(mobile\s?safari|safari)/i // Safari & Safari Mobile + ], [VERSION, MAJOR, NAME], [ + + /webkit.+?(mobile\s?safari|safari)((\/[\w\.]+))/i // Safari < 3.0 + ], [NAME, [MAJOR, mapper.str, maps.browser.oldsafari.major], [VERSION, mapper.str, maps.browser.oldsafari.version]], [ + + /(konqueror)\/((\d+)?[\w\.]+)/i, // Konqueror + /(webkit|khtml)\/((\d+)?[\w\.]+)/i + ], [NAME, VERSION, MAJOR], [ + + // Gecko based + /(navigator|netscape)\/((\d+)?[\w\.-]+)/i // Netscape + ], [[NAME, 'Netscape'], VERSION, MAJOR], [ + /(swiftfox)/i, // Swiftfox + /(icedragon|iceweasel|camino|chimera|fennec|maemo\sbrowser|minimo|conkeror)[\/\s]?((\d+)?[\w\.\+]+)/i, + // IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror + /(firefox|seamonkey|k-meleon|icecat|iceape|firebird|phoenix)\/((\d+)?[\w\.-]+)/i, + // Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix + /(mozilla)\/((\d+)?[\w\.]+).+rv\:.+gecko\/\d+/i, // Mozilla + + // Other + /(uc\s?browser|polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|qqbrowser)[\/\s]?((\d+)?[\w\.]+)/i, + // UCBrowser/Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/QQBrowser + /(links)\s\(((\d+)?[\w\.]+)/i, // Links + /(gobrowser)\/?((\d+)?[\w\.]+)*/i, // GoBrowser + /(ice\s?browser)\/v?((\d+)?[\w\._]+)/i, // ICE Browser + /(mosaic)[\/\s]((\d+)?[\w\.]+)/i // Mosaic + ], [NAME, VERSION, MAJOR] + ], + + engine : [[ + + /(presto)\/([\w\.]+)/i, // Presto + /(webkit|trident|netfront|netsurf|amaya|lynx|w3m)\/([\w\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m + /(khtml|tasman|links)[\/\s]\(?([\w\.]+)/i, // KHTML/Tasman/Links + /(icab)[\/\s]([23]\.[\d\.]+)/i // iCab + ], [NAME, VERSION], [ + + /rv\:([\w\.]+).*(gecko)/i // Gecko + ], [VERSION, NAME] + ], + + os : [[ + + // Windows based + /(windows)\snt\s6\.2;\s(arm)/i, // Windows RT + /(windows\sphone(?:\sos)*|windows\smobile|windows)[\s\/]?([ntce\d\.\s]+\w)/i + ], [NAME, [VERSION, mapper.str, maps.os.windows.version]], [ + /(win(?=3|9|n)|win\s9x\s)([nt\d\.]+)/i + ], [[NAME, 'Windows'], [VERSION, mapper.str, maps.os.windows.version]], [ + + // Mobile/Embedded OS + /\((bb)(10);/i // BlackBerry 10 + ], [[NAME, 'BlackBerry'], VERSION], [ + /(blackberry)\w*\/?([\w\.]+)*/i, // Blackberry + /(tizen)\/([\w\.]+)/i, // Tizen + /(android|webos|palm\os|qnx|bada|rim\stablet\sos|meego)[\/\s-]?([\w\.]+)*/i + // Android/WebOS/Palm/QNX/Bada/RIM/MeeGo + ], [NAME, VERSION], [ + /(symbian\s?os|symbos|s60(?=;))[\/\s-]?([\w\.]+)*/i // Symbian + ], [[NAME, 'Symbian'], VERSION],[ + /mozilla.+\(mobile;.+gecko.+firefox/i // Firefox OS + ], [[NAME, 'Firefox OS'], VERSION], [ + + // Console + /(nintendo|playstation)\s([wids3portablevu]+)/i, // Nintendo/Playstation + + // GNU/Linux based + /(mint)[\/\s\(]?(\w+)*/i, // Mint + /(joli|[kxln]?ubuntu|debian|[open]*suse|gentoo|arch|slackware|fedora|mandriva|centos|pclinuxos|redhat|zenwalk)[\/\s-]?([\w\.-]+)*/i, + // Joli/Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware + // Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk + /(hurd|linux)\s?([\w\.]+)*/i, // Hurd/Linux + /(gnu)\s?([\w\.]+)*/i // GNU + ], [NAME, VERSION], [ + + /(cros)\s[\w]+\s([\w\.]+\w)/i // Chromium OS + ], [[NAME, 'Chromium OS'], VERSION],[ + + // Solaris + /(sunos)\s?([\w\.]+\d)*/i // Solaris + ], [[NAME, 'Solaris'], VERSION], [ + + // BSD based + /\s([frentopc-]{0,4}bsd|dragonfly)\s?([\w\.]+)*/i // FreeBSD/NetBSD/OpenBSD/PC-BSD/DragonFly + ], [NAME, VERSION],[ + + /(ip[honead]+)(?:.*os\s*([\w]+)*\slike\smac|;\sopera)/i // iOS + ], [[NAME, 'iOS'], [VERSION, /_/g, '.']], [ + + /(mac\sos\sx)\s?([\w\s\.]+\w)*/i // Mac OS + ], [NAME, [VERSION, /_/g, '.']], [ + + // Other + /(haiku)\s(\w+)/i, // Haiku + /(aix)\s((\d)(?=\.|\)|\s)[\w\.]*)*/i, // AIX + /(macintosh|mac(?=_powerpc)|plan\s9|minix|beos|os\/2|amigaos|morphos|risc\sos)/i, + // Plan9/Minix/BeOS/OS2/AmigaOS/MorphOS/RISCOS + /(unix)\s?([\w\.]+)*/i // UNIX + ], [NAME, VERSION] + ] + }; + + + ///////////////// + // Constructor + //////////////// + + + var UAParser = function (uastring) { + + var ua = uastring || ((window && window.navigator && window.navigator.userAgent) ? window.navigator.userAgent : EMPTY); + + this.getBrowser = function () { + return mapper.rgx.apply(this, regexes.browser); + }; + this.getEngine = function () { + return mapper.rgx.apply(this, regexes.engine); + }; + this.getOS = function () { + return mapper.rgx.apply(this, regexes.os); + }; + this.getResult = function() { + return { + ua : this.getUA(), + browser : this.getBrowser(), + engine : this.getEngine(), + os : this.getOS() + }; + }; + this.getUA = function () { + return ua; + }; + this.setUA = function (uastring) { + ua = uastring; + return this; + }; + this.setUA(ua); + }; + + return new UAParser().getResult(); + })(); + + + function version_compare(v1, v2, operator) { + // From: http://phpjs.org/functions + // + original by: Philippe Jausions (http://pear.php.net/user/jausions) + // + original by: Aidan Lister (http://aidanlister.com/) + // + reimplemented by: Kankrelune (http://www.webfaktory.info/) + // + improved by: Brett Zamir (http://brett-zamir.me) + // + improved by: Scott Baker + // + improved by: Theriault + // * example 1: version_compare('8.2.5rc', '8.2.5a'); + // * returns 1: 1 + // * example 2: version_compare('8.2.50', '8.2.52', '<'); + // * returns 2: true + // * example 3: version_compare('5.3.0-dev', '5.3.0'); + // * returns 3: -1 + // * example 4: version_compare('4.1.0.52','4.01.0.51'); + // * returns 4: 1 + + // Important: compare must be initialized at 0. + var i = 0, + x = 0, + compare = 0, + // vm maps textual PHP versions to negatives so they're less than 0. + // PHP currently defines these as CASE-SENSITIVE. It is important to + // leave these as negatives so that they can come before numerical versions + // and as if no letters were there to begin with. + // (1alpha is < 1 and < 1.1 but > 1dev1) + // If a non-numerical value can't be mapped to this table, it receives + // -7 as its value. + vm = { + 'dev': -6, + 'alpha': -5, + 'a': -5, + 'beta': -4, + 'b': -4, + 'RC': -3, + 'rc': -3, + '#': -2, + 'p': 1, + 'pl': 1 + }, + // This function will be called to prepare each version argument. + // It replaces every _, -, and + with a dot. + // It surrounds any nonsequence of numbers/dots with dots. + // It replaces sequences of dots with a single dot. + // version_compare('4..0', '4.0') == 0 + // Important: A string of 0 length needs to be converted into a value + // even less than an unexisting value in vm (-7), hence [-8]. + // It's also important to not strip spaces because of this. + // version_compare('', ' ') == 1 + prepVersion = function (v) { + v = ('' + v).replace(/[_\-+]/g, '.'); + v = v.replace(/([^.\d]+)/g, '.$1.').replace(/\.{2,}/g, '.'); + return (!v.length ? [-8] : v.split('.')); + }, + // This converts a version component to a number. + // Empty component becomes 0. + // Non-numerical component becomes a negative number. + // Numerical component becomes itself as an integer. + numVersion = function (v) { + return !v ? 0 : (isNaN(v) ? vm[v] || -7 : parseInt(v, 10)); + }; + + v1 = prepVersion(v1); + v2 = prepVersion(v2); + x = Math.max(v1.length, v2.length); + for (i = 0; i < x; i++) { + if (v1[i] == v2[i]) { + continue; + } + v1[i] = numVersion(v1[i]); + v2[i] = numVersion(v2[i]); + if (v1[i] < v2[i]) { + compare = -1; + break; + } else if (v1[i] > v2[i]) { + compare = 1; + break; + } + } + if (!operator) { + return compare; + } + + // Important: operator is CASE-SENSITIVE. + // "No operator" seems to be treated as "<." + // Any other values seem to make the function return null. + switch (operator) { + case '>': + case 'gt': + return (compare > 0); + case '>=': + case 'ge': + return (compare >= 0); + case '<=': + case 'le': + return (compare <= 0); + case '==': + case '=': + case 'eq': + return (compare === 0); + case '<>': + case '!=': + case 'ne': + return (compare !== 0); + case '': + case '<': + case 'lt': + return (compare < 0); + default: + return null; + } + } + + + var can = (function() { + var caps = { + define_property: (function() { + /* // currently too much extra code required, not exactly worth it + try { // as of IE8, getters/setters are supported only on DOM elements + var obj = {}; + if (Object.defineProperty) { + Object.defineProperty(obj, 'prop', { + enumerable: true, + configurable: true + }); + return true; + } + } catch(ex) {} + + if (Object.prototype.__defineGetter__ && Object.prototype.__defineSetter__) { + return true; + }*/ + return false; + }()), + + create_canvas: (function() { + // On the S60 and BB Storm, getContext exists, but always returns undefined + // so we actually have to call getContext() to verify + // github.com/Modernizr/Modernizr/issues/issue/97/ + var el = document.createElement('canvas'); + return !!(el.getContext && el.getContext('2d')); + }()), + + return_response_type: function(responseType) { + try { + if (Basic.inArray(responseType, ['', 'text', 'document']) !== -1) { + return true; + } else if (window.XMLHttpRequest) { + var xhr = new XMLHttpRequest(); + xhr.open('get', '/'); // otherwise Gecko throws an exception + if ('responseType' in xhr) { + xhr.responseType = responseType; + // as of 23.0.1271.64, Chrome switched from throwing exception to merely logging it to the console (why? o why?) + if (xhr.responseType !== responseType) { + return false; + } + return true; + } + } + } catch (ex) {} + return false; + }, + + // ideas for this heavily come from Modernizr (http://modernizr.com/) + use_data_uri: (function() { + var du = new Image(); + + du.onload = function() { + caps.use_data_uri = (du.width === 1 && du.height === 1); + }; + + setTimeout(function() { + du.src = "data:image/gif;base64,R0lGODlhAQABAIAAAP8AAAAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw=="; + }, 1); + return false; + }()), + + use_data_uri_over32kb: function() { // IE8 + return caps.use_data_uri && (Env.browser !== 'IE' || Env.version >= 9); + }, + + use_data_uri_of: function(bytes) { + return (caps.use_data_uri && bytes < 33000 || caps.use_data_uri_over32kb()); + }, + + use_fileinput: function() { + var el = document.createElement('input'); + el.setAttribute('type', 'file'); + return !el.disabled; + } + }; + + return function(cap) { + var args = [].slice.call(arguments); + args.shift(); // shift of cap + return Basic.typeOf(caps[cap]) === 'function' ? caps[cap].apply(this, args) : !!caps[cap]; + }; + }()); + + + var Env = { + can: can, + + browser: UAParser.browser.name, + version: parseFloat(UAParser.browser.major), + os: UAParser.os.name, // everybody intuitively types it in a lowercase for some reason + osVersion: UAParser.os.version, + + verComp: version_compare, + + swf_url: "../flash/Moxie.swf", + xap_url: "../silverlight/Moxie.xap", + global_event_dispatcher: "moxie.core.EventTarget.instance.dispatchEvent" + }; + + // for backward compatibility + // @deprecated Use `Env.os` instead + Env.OS = Env.os; + + return Env; +}); + +// Included from: src/javascript/core/utils/Dom.js + +/** + * Dom.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define('moxie/core/utils/Dom', ['moxie/core/utils/Env'], function(Env) { + + /** + Get DOM Element by it's id. + + @method get + @for Utils + @param {String} id Identifier of the DOM Element + @return {DOMElement} + */ + var get = function(id) { + if (typeof id !== 'string') { + return id; + } + return document.getElementById(id); + }; + + /** + Checks if specified DOM element has specified class. + + @method hasClass + @static + @param {Object} obj DOM element like object to add handler to. + @param {String} name Class name + */ + var hasClass = function(obj, name) { + if (!obj.className) { + return false; + } + + var regExp = new RegExp("(^|\\s+)"+name+"(\\s+|$)"); + return regExp.test(obj.className); + }; + + /** + Adds specified className to specified DOM element. + + @method addClass + @static + @param {Object} obj DOM element like object to add handler to. + @param {String} name Class name + */ + var addClass = function(obj, name) { + if (!hasClass(obj, name)) { + obj.className = !obj.className ? name : obj.className.replace(/\s+$/, '') + ' ' + name; + } + }; + + /** + Removes specified className from specified DOM element. + + @method removeClass + @static + @param {Object} obj DOM element like object to add handler to. + @param {String} name Class name + */ + var removeClass = function(obj, name) { + if (obj.className) { + var regExp = new RegExp("(^|\\s+)"+name+"(\\s+|$)"); + obj.className = obj.className.replace(regExp, function($0, $1, $2) { + return $1 === ' ' && $2 === ' ' ? ' ' : ''; + }); + } + }; + + /** + Returns a given computed style of a DOM element. + + @method getStyle + @static + @param {Object} obj DOM element like object. + @param {String} name Style you want to get from the DOM element + */ + var getStyle = function(obj, name) { + if (obj.currentStyle) { + return obj.currentStyle[name]; + } else if (window.getComputedStyle) { + return window.getComputedStyle(obj, null)[name]; + } + }; + + + /** + Returns the absolute x, y position of an Element. The position will be returned in a object with x, y fields. + + @method getPos + @static + @param {Element} node HTML element or element id to get x, y position from. + @param {Element} root Optional root element to stop calculations at. + @return {object} Absolute position of the specified element object with x, y fields. + */ + var getPos = function(node, root) { + var x = 0, y = 0, parent, doc = document, nodeRect, rootRect; + + node = node; + root = root || doc.body; + + // Returns the x, y cordinate for an element on IE 6 and IE 7 + function getIEPos(node) { + var bodyElm, rect, x = 0, y = 0; + + if (node) { + rect = node.getBoundingClientRect(); + bodyElm = doc.compatMode === "CSS1Compat" ? doc.documentElement : doc.body; + x = rect.left + bodyElm.scrollLeft; + y = rect.top + bodyElm.scrollTop; + } + + return { + x : x, + y : y + }; + } + + // Use getBoundingClientRect on IE 6 and IE 7 but not on IE 8 in standards mode + if (node && node.getBoundingClientRect && Env.browser === 'IE' && (!doc.documentMode || doc.documentMode < 8)) { + nodeRect = getIEPos(node); + rootRect = getIEPos(root); + + return { + x : nodeRect.x - rootRect.x, + y : nodeRect.y - rootRect.y + }; + } + + parent = node; + while (parent && parent != root && parent.nodeType) { + x += parent.offsetLeft || 0; + y += parent.offsetTop || 0; + parent = parent.offsetParent; + } + + parent = node.parentNode; + while (parent && parent != root && parent.nodeType) { + x -= parent.scrollLeft || 0; + y -= parent.scrollTop || 0; + parent = parent.parentNode; + } + + return { + x : x, + y : y + }; + }; + + /** + Returns the size of the specified node in pixels. + + @method getSize + @static + @param {Node} node Node to get the size of. + @return {Object} Object with a w and h property. + */ + var getSize = function(node) { + return { + w : node.offsetWidth || node.clientWidth, + h : node.offsetHeight || node.clientHeight + }; + }; + + return { + get: get, + hasClass: hasClass, + addClass: addClass, + removeClass: removeClass, + getStyle: getStyle, + getPos: getPos, + getSize: getSize + }; +}); + +// Included from: src/javascript/core/Exceptions.js + +/** + * Exceptions.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define('moxie/core/Exceptions', [ + 'moxie/core/utils/Basic' +], function(Basic) { + function _findKey(obj, value) { + var key; + for (key in obj) { + if (obj[key] === value) { + return key; + } + } + return null; + } + + return { + RuntimeError: (function() { + var namecodes = { + NOT_INIT_ERR: 1, + NOT_SUPPORTED_ERR: 9, + JS_ERR: 4 + }; + + function RuntimeError(code) { + this.code = code; + this.name = _findKey(namecodes, code); + this.message = this.name + ": RuntimeError " + this.code; + } + + Basic.extend(RuntimeError, namecodes); + RuntimeError.prototype = Error.prototype; + return RuntimeError; + }()), + + OperationNotAllowedException: (function() { + + function OperationNotAllowedException(code) { + this.code = code; + this.name = 'OperationNotAllowedException'; + } + + Basic.extend(OperationNotAllowedException, { + NOT_ALLOWED_ERR: 1 + }); + + OperationNotAllowedException.prototype = Error.prototype; + + return OperationNotAllowedException; + }()), + + ImageError: (function() { + var namecodes = { + WRONG_FORMAT: 1, + MAX_RESOLUTION_ERR: 2 + }; + + function ImageError(code) { + this.code = code; + this.name = _findKey(namecodes, code); + this.message = this.name + ": ImageError " + this.code; + } + + Basic.extend(ImageError, namecodes); + ImageError.prototype = Error.prototype; + + return ImageError; + }()), + + FileException: (function() { + var namecodes = { + NOT_FOUND_ERR: 1, + SECURITY_ERR: 2, + ABORT_ERR: 3, + NOT_READABLE_ERR: 4, + ENCODING_ERR: 5, + NO_MODIFICATION_ALLOWED_ERR: 6, + INVALID_STATE_ERR: 7, + SYNTAX_ERR: 8 + }; + + function FileException(code) { + this.code = code; + this.name = _findKey(namecodes, code); + this.message = this.name + ": FileException " + this.code; + } + + Basic.extend(FileException, namecodes); + FileException.prototype = Error.prototype; + return FileException; + }()), + + DOMException: (function() { + var namecodes = { + INDEX_SIZE_ERR: 1, + DOMSTRING_SIZE_ERR: 2, + HIERARCHY_REQUEST_ERR: 3, + WRONG_DOCUMENT_ERR: 4, + INVALID_CHARACTER_ERR: 5, + NO_DATA_ALLOWED_ERR: 6, + NO_MODIFICATION_ALLOWED_ERR: 7, + NOT_FOUND_ERR: 8, + NOT_SUPPORTED_ERR: 9, + INUSE_ATTRIBUTE_ERR: 10, + INVALID_STATE_ERR: 11, + SYNTAX_ERR: 12, + INVALID_MODIFICATION_ERR: 13, + NAMESPACE_ERR: 14, + INVALID_ACCESS_ERR: 15, + VALIDATION_ERR: 16, + TYPE_MISMATCH_ERR: 17, + SECURITY_ERR: 18, + NETWORK_ERR: 19, + ABORT_ERR: 20, + URL_MISMATCH_ERR: 21, + QUOTA_EXCEEDED_ERR: 22, + TIMEOUT_ERR: 23, + INVALID_NODE_TYPE_ERR: 24, + DATA_CLONE_ERR: 25 + }; + + function DOMException(code) { + this.code = code; + this.name = _findKey(namecodes, code); + this.message = this.name + ": DOMException " + this.code; + } + + Basic.extend(DOMException, namecodes); + DOMException.prototype = Error.prototype; + return DOMException; + }()), + + EventException: (function() { + function EventException(code) { + this.code = code; + this.name = 'EventException'; + } + + Basic.extend(EventException, { + UNSPECIFIED_EVENT_TYPE_ERR: 0 + }); + + EventException.prototype = Error.prototype; + + return EventException; + }()) + }; +}); + +// Included from: src/javascript/core/EventTarget.js + +/** + * EventTarget.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define('moxie/core/EventTarget', [ + 'moxie/core/Exceptions', + 'moxie/core/utils/Basic' +], function(x, Basic) { + /** + Parent object for all event dispatching components and objects + + @class EventTarget + @constructor EventTarget + */ + function EventTarget() { + // hash of event listeners by object uid + var eventpool = {}; + + Basic.extend(this, { + + /** + Unique id of the event dispatcher, usually overriden by children + + @property uid + @type String + */ + uid: null, + + /** + Can be called from within a child in order to acquire uniqie id in automated manner + + @method init + */ + init: function() { + if (!this.uid) { + this.uid = Basic.guid('uid_'); + } + }, + + /** + Register a handler to a specific event dispatched by the object + + @method addEventListener + @param {String} type Type or basically a name of the event to subscribe to + @param {Function} fn Callback function that will be called when event happens + @param {Number} [priority=0] Priority of the event handler - handlers with higher priorities will be called first + @param {Object} [scope=this] A scope to invoke event handler in + */ + addEventListener: function(type, fn, priority, scope) { + var self = this, list; + + type = Basic.trim(type); + + if (/\s/.test(type)) { + // multiple event types were passed for one handler + Basic.each(type.split(/\s+/), function(type) { + self.addEventListener(type, fn, priority, scope); + }); + return; + } + + type = type.toLowerCase(); + priority = parseInt(priority, 10) || 0; + + list = eventpool[this.uid] && eventpool[this.uid][type] || []; + list.push({fn : fn, priority : priority, scope : scope || this}); + + if (!eventpool[this.uid]) { + eventpool[this.uid] = {}; + } + eventpool[this.uid][type] = list; + }, + + /** + Check if any handlers were registered to the specified event + + @method hasEventListener + @param {String} type Type or basically a name of the event to check + @return {Mixed} Returns a handler if it was found and false, if - not + */ + hasEventListener: function(type) { + return type ? !!(eventpool[this.uid] && eventpool[this.uid][type]) : !!eventpool[this.uid]; + }, + + /** + Unregister the handler from the event, or if former was not specified - unregister all handlers + + @method removeEventListener + @param {String} type Type or basically a name of the event + @param {Function} [fn] Handler to unregister + */ + removeEventListener: function(type, fn) { + type = type.toLowerCase(); + + var list = eventpool[this.uid] && eventpool[this.uid][type], i; + + if (list) { + if (fn) { + for (i = list.length - 1; i >= 0; i--) { + if (list[i].fn === fn) { + list.splice(i, 1); + break; + } + } + } else { + list = []; + } + + // delete event list if it has become empty + if (!list.length) { + delete eventpool[this.uid][type]; + + // and object specific entry in a hash if it has no more listeners attached + if (Basic.isEmptyObj(eventpool[this.uid])) { + delete eventpool[this.uid]; + } + } + } + }, + + /** + Remove all event handlers from the object + + @method removeAllEventListeners + */ + removeAllEventListeners: function() { + if (eventpool[this.uid]) { + delete eventpool[this.uid]; + } + }, + + /** + Dispatch the event + + @method dispatchEvent + @param {String/Object} Type of event or event object to dispatch + @param {Mixed} [...] Variable number of arguments to be passed to a handlers + @return {Boolean} true by default and false if any handler returned false + */ + dispatchEvent: function(type) { + var uid, list, args, tmpEvt, evt = {}, result = true, undef; + + if (Basic.typeOf(type) !== 'string') { + // we can't use original object directly (because of Silverlight) + tmpEvt = type; + + if (Basic.typeOf(tmpEvt.type) === 'string') { + type = tmpEvt.type; + + if (tmpEvt.total !== undef && tmpEvt.loaded !== undef) { // progress event + evt.total = tmpEvt.total; + evt.loaded = tmpEvt.loaded; + } + evt.async = tmpEvt.async || false; + } else { + throw new x.EventException(x.EventException.UNSPECIFIED_EVENT_TYPE_ERR); + } + } + + // check if event is meant to be dispatched on an object having specific uid + if (type.indexOf('::') !== -1) { + (function(arr) { + uid = arr[0]; + type = arr[1]; + }(type.split('::'))); + } else { + uid = this.uid; + } + + type = type.toLowerCase(); + + list = eventpool[uid] && eventpool[uid][type]; + + if (list) { + // sort event list by prority + list.sort(function(a, b) { return b.priority - a.priority; }); + + args = [].slice.call(arguments); + + // first argument will be pseudo-event object + args.shift(); + evt.type = type; + args.unshift(evt); + + // Dispatch event to all listeners + var queue = []; + Basic.each(list, function(handler) { + // explicitly set the target, otherwise events fired from shims do not get it + args[0].target = handler.scope; + // if event is marked as async, detach the handler + if (evt.async) { + queue.push(function(cb) { + setTimeout(function() { + cb(handler.fn.apply(handler.scope, args) === false); + }, 1); + }); + } else { + queue.push(function(cb) { + cb(handler.fn.apply(handler.scope, args) === false); // if handler returns false stop propagation + }); + } + }); + if (queue.length) { + Basic.inSeries(queue, function(err) { + result = !err; + }); + } + } + return result; + }, + + /** + Alias for addEventListener + + @method bind + @protected + */ + bind: function() { + this.addEventListener.apply(this, arguments); + }, + + /** + Alias for removeEventListener + + @method unbind + @protected + */ + unbind: function() { + this.removeEventListener.apply(this, arguments); + }, + + /** + Alias for removeAllEventListeners + + @method unbindAll + @protected + */ + unbindAll: function() { + this.removeAllEventListeners.apply(this, arguments); + }, + + /** + Alias for dispatchEvent + + @method trigger + @protected + */ + trigger: function() { + return this.dispatchEvent.apply(this, arguments); + }, + + + /** + Converts properties of on[event] type to corresponding event handlers, + is used to avoid extra hassle around the process of calling them back + + @method convertEventPropsToHandlers + @private + */ + convertEventPropsToHandlers: function(handlers) { + var h; + + if (Basic.typeOf(handlers) !== 'array') { + handlers = [handlers]; + } + + for (var i = 0; i < handlers.length; i++) { + h = 'on' + handlers[i]; + + if (Basic.typeOf(this[h]) === 'function') { + this.addEventListener(handlers[i], this[h]); + } else if (Basic.typeOf(this[h]) === 'undefined') { + this[h] = null; // object must have defined event properties, even if it doesn't make use of them + } + } + } + + }); + } + + EventTarget.instance = new EventTarget(); + + return EventTarget; +}); + +// Included from: src/javascript/core/utils/Encode.js + +/** + * Encode.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define('moxie/core/utils/Encode', [], function() { + + /** + Encode string with UTF-8 + + @method utf8_encode + @for Utils + @static + @param {String} str String to encode + @return {String} UTF-8 encoded string + */ + var utf8_encode = function(str) { + return unescape(encodeURIComponent(str)); + }; + + /** + Decode UTF-8 encoded string + + @method utf8_decode + @static + @param {String} str String to decode + @return {String} Decoded string + */ + var utf8_decode = function(str_data) { + return decodeURIComponent(escape(str_data)); + }; + + /** + Decode Base64 encoded string (uses browser's default method if available), + from: https://raw.github.com/kvz/phpjs/master/functions/url/base64_decode.js + + @method atob + @static + @param {String} data String to decode + @return {String} Decoded string + */ + var atob = function(data, utf8) { + if (typeof(window.atob) === 'function') { + return utf8 ? utf8_decode(window.atob(data)) : window.atob(data); + } + + // http://kevin.vanzonneveld.net + // + original by: Tyler Akins (http://rumkin.com) + // + improved by: Thunder.m + // + input by: Aman Gupta + // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // + bugfixed by: Onno Marsman + // + bugfixed by: Pellentesque Malesuada + // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // + input by: Brett Zamir (http://brett-zamir.me) + // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // * example 1: base64_decode('S2V2aW4gdmFuIFpvbm5ldmVsZA=='); + // * returns 1: 'Kevin van Zonneveld' + // mozilla has this native + // - but breaks in 2.0.0.12! + //if (typeof this.window.atob == 'function') { + // return atob(data); + //} + var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, + ac = 0, + dec = "", + tmp_arr = []; + + if (!data) { + return data; + } + + data += ''; + + do { // unpack four hexets into three octets using index points in b64 + h1 = b64.indexOf(data.charAt(i++)); + h2 = b64.indexOf(data.charAt(i++)); + h3 = b64.indexOf(data.charAt(i++)); + h4 = b64.indexOf(data.charAt(i++)); + + bits = h1 << 18 | h2 << 12 | h3 << 6 | h4; + + o1 = bits >> 16 & 0xff; + o2 = bits >> 8 & 0xff; + o3 = bits & 0xff; + + if (h3 == 64) { + tmp_arr[ac++] = String.fromCharCode(o1); + } else if (h4 == 64) { + tmp_arr[ac++] = String.fromCharCode(o1, o2); + } else { + tmp_arr[ac++] = String.fromCharCode(o1, o2, o3); + } + } while (i < data.length); + + dec = tmp_arr.join(''); + + return utf8 ? utf8_decode(dec) : dec; + }; + + /** + Base64 encode string (uses browser's default method if available), + from: https://raw.github.com/kvz/phpjs/master/functions/url/base64_encode.js + + @method btoa + @static + @param {String} data String to encode + @return {String} Base64 encoded string + */ + var btoa = function(data, utf8) { + if (utf8) { + utf8_encode(data); + } + + if (typeof(window.btoa) === 'function') { + return window.btoa(data); + } + + // http://kevin.vanzonneveld.net + // + original by: Tyler Akins (http://rumkin.com) + // + improved by: Bayron Guevara + // + improved by: Thunder.m + // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // + bugfixed by: Pellentesque Malesuada + // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // + improved by: Rafał Kukawski (http://kukawski.pl) + // * example 1: base64_encode('Kevin van Zonneveld'); + // * returns 1: 'S2V2aW4gdmFuIFpvbm5ldmVsZA==' + // mozilla has this native + // - but breaks in 2.0.0.12! + var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, + ac = 0, + enc = "", + tmp_arr = []; + + if (!data) { + return data; + } + + do { // pack three octets into four hexets + o1 = data.charCodeAt(i++); + o2 = data.charCodeAt(i++); + o3 = data.charCodeAt(i++); + + bits = o1 << 16 | o2 << 8 | o3; + + h1 = bits >> 18 & 0x3f; + h2 = bits >> 12 & 0x3f; + h3 = bits >> 6 & 0x3f; + h4 = bits & 0x3f; + + // use hexets to index into b64, and append result to encoded string + tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4); + } while (i < data.length); + + enc = tmp_arr.join(''); + + var r = data.length % 3; + + return (r ? enc.slice(0, r - 3) : enc) + '==='.slice(r || 3); + }; + + + return { + utf8_encode: utf8_encode, + utf8_decode: utf8_decode, + atob: atob, + btoa: btoa + }; +}); + +// Included from: src/javascript/runtime/Runtime.js + +/** + * Runtime.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define('moxie/runtime/Runtime', [ + "moxie/core/utils/Basic", + "moxie/core/utils/Dom", + "moxie/core/EventTarget" +], function(Basic, Dom, EventTarget) { + var runtimeConstructors = {}, runtimes = {}; + + /** + Common set of methods and properties for every runtime instance + + @class Runtime + + @param {Object} options + @param {String} type Sanitized name of the runtime + @param {Object} [caps] Set of capabilities that differentiate specified runtime + @param {Object} [modeCaps] Set of capabilities that do require specific operational mode + @param {String} [preferredMode='browser'] Preferred operational mode to choose if no required capabilities were requested + */ + function Runtime(options, type, caps, modeCaps, preferredMode) { + /** + Dispatched when runtime is initialized and ready. + Results in RuntimeInit on a connected component. + + @event Init + */ + + /** + Dispatched when runtime fails to initialize. + Results in RuntimeError on a connected component. + + @event Error + */ + + var self = this + , _shim + , _uid = Basic.guid(type + '_') + , defaultMode = preferredMode || 'browser' + ; + + options = options || {}; + + // register runtime in private hash + runtimes[_uid] = this; + + /** + Default set of capabilities, which can be redifined later by specific runtime + + @private + @property caps + @type Object + */ + caps = Basic.extend({ + // Runtime can: + // provide access to raw binary data of the file + access_binary: false, + // provide access to raw binary data of the image (image extension is optional) + access_image_binary: false, + // display binary data as thumbs for example + display_media: false, + // make cross-domain requests + do_cors: false, + // accept files dragged and dropped from the desktop + drag_and_drop: false, + // filter files in selection dialog by their extensions + filter_by_extension: true, + // resize image (and manipulate it raw data of any file in general) + resize_image: false, + // periodically report how many bytes of total in the file were uploaded (loaded) + report_upload_progress: false, + // provide access to the headers of http response + return_response_headers: false, + // support response of specific type, which should be passed as an argument + // e.g. runtime.can('return_response_type', 'blob') + return_response_type: false, + // return http status code of the response + return_status_code: true, + // send custom http header with the request + send_custom_headers: false, + // pick up the files from a dialog + select_file: false, + // select whole folder in file browse dialog + select_folder: false, + // select multiple files at once in file browse dialog + select_multiple: true, + // send raw binary data, that is generated after image resizing or manipulation of other kind + send_binary_string: false, + // send cookies with http request and therefore retain session + send_browser_cookies: true, + // send data formatted as multipart/form-data + send_multipart: true, + // slice the file or blob to smaller parts + slice_blob: false, + // upload file without preloading it to memory, stream it out directly from disk + stream_upload: false, + // programmatically trigger file browse dialog + summon_file_dialog: false, + // upload file of specific size, size should be passed as argument + // e.g. runtime.can('upload_filesize', '500mb') + upload_filesize: true, + // initiate http request with specific http method, method should be passed as argument + // e.g. runtime.can('use_http_method', 'put') + use_http_method: true + }, caps); + + + // default to the mode that is compatible with preferred caps + if (options.preferred_caps) { + defaultMode = Runtime.getMode(modeCaps, options.preferred_caps, defaultMode); + } + + // small extension factory here (is meant to be extended with actual extensions constructors) + _shim = (function() { + var objpool = {}; + return { + exec: function(uid, comp, fn, args) { + if (_shim[comp]) { + if (!objpool[uid]) { + objpool[uid] = { + context: this, + instance: new _shim[comp]() + }; + } + if (objpool[uid].instance[fn]) { + return objpool[uid].instance[fn].apply(this, args); + } + } + }, + + removeInstance: function(uid) { + delete objpool[uid]; + }, + + removeAllInstances: function() { + var self = this; + Basic.each(objpool, function(obj, uid) { + if (Basic.typeOf(obj.instance.destroy) === 'function') { + obj.instance.destroy.call(obj.context); + } + self.removeInstance(uid); + }); + } + }; + }()); + + + // public methods + Basic.extend(this, { + /** + Specifies whether runtime instance was initialized or not + + @property initialized + @type {Boolean} + @default false + */ + initialized: false, // shims require this flag to stop initialization retries + + /** + Unique ID of the runtime + + @property uid + @type {String} + */ + uid: _uid, + + /** + Runtime type (e.g. flash, html5, etc) + + @property type + @type {String} + */ + type: type, + + /** + Runtime (not native one) may operate in browser or client mode. + + @property mode + @private + @type {String|Boolean} current mode or false, if none possible + */ + mode: Runtime.getMode(modeCaps, (options.required_caps), defaultMode), + + /** + id of the DOM container for the runtime (if available) + + @property shimid + @type {String} + */ + shimid: _uid + '_container', + + /** + Number of connected clients. If equal to zero, runtime can be destroyed + + @property clients + @type {Number} + */ + clients: 0, + + /** + Runtime initialization options + + @property options + @type {Object} + */ + options: options, + + /** + Checks if the runtime has specific capability + + @method can + @param {String} cap Name of capability to check + @param {Mixed} [value] If passed, capability should somehow correlate to the value + @param {Object} [refCaps] Set of capabilities to check the specified cap against (defaults to internal set) + @return {Boolean} true if runtime has such capability and false, if - not + */ + can: function(cap, value) { + var refCaps = arguments[2] || caps; + + // if cap var is a comma-separated list of caps, convert it to object (key/value) + if (Basic.typeOf(cap) === 'string' && Basic.typeOf(value) === 'undefined') { + cap = Runtime.parseCaps(cap); + } + + if (Basic.typeOf(cap) === 'object') { + for (var key in cap) { + if (!this.can(key, cap[key], refCaps)) { + return false; + } + } + return true; + } + + // check the individual cap + if (Basic.typeOf(refCaps[cap]) === 'function') { + return refCaps[cap].call(this, value); + } else { + return (value === refCaps[cap]); + } + }, + + /** + Returns container for the runtime as DOM element + + @method getShimContainer + @return {DOMElement} + */ + getShimContainer: function() { + var container, shimContainer = Dom.get(this.shimid); + + // if no container for shim, create one + if (!shimContainer) { + container = this.options.container ? Dom.get(this.options.container) : document.body; + + // create shim container and insert it at an absolute position into the outer container + shimContainer = document.createElement('div'); + shimContainer.id = this.shimid; + shimContainer.className = 'moxie-shim moxie-shim-' + this.type; + + Basic.extend(shimContainer.style, { + position: 'absolute', + top: '0px', + left: '0px', + width: '1px', + height: '1px', + overflow: 'hidden' + }); + + container.appendChild(shimContainer); + container = null; + } + + return shimContainer; + }, + + /** + Returns runtime as DOM element (if appropriate) + + @method getShim + @return {DOMElement} + */ + getShim: function() { + return _shim; + }, + + /** + Invokes a method within the runtime itself (might differ across the runtimes) + + @method shimExec + @param {Mixed} [] + @protected + @return {Mixed} Depends on the action and component + */ + shimExec: function(component, action) { + var args = [].slice.call(arguments, 2); + return self.getShim().exec.call(this, this.uid, component, action, args); + }, + + /** + Operaional interface that is used by components to invoke specific actions on the runtime + (is invoked in the scope of component) + + @method exec + @param {Mixed} []* + @protected + @return {Mixed} Depends on the action and component + */ + exec: function(component, action) { // this is called in the context of component, not runtime + var args = [].slice.call(arguments, 2); + + if (self[component] && self[component][action]) { + return self[component][action].apply(this, args); + } + return self.shimExec.apply(this, arguments); + }, + + /** + Destroys the runtime (removes all events and deletes DOM structures) + + @method destroy + */ + destroy: function() { + if (!self) { + return; // obviously already destroyed + } + + var shimContainer = Dom.get(this.shimid); + if (shimContainer) { + shimContainer.parentNode.removeChild(shimContainer); + } + + if (_shim) { + _shim.removeAllInstances(); + } + + this.unbindAll(); + delete runtimes[this.uid]; + this.uid = null; // mark this runtime as destroyed + _uid = self = _shim = shimContainer = null; + } + }); + + // once we got the mode, test against all caps + if (this.mode && options.required_caps && !this.can(options.required_caps)) { + this.mode = false; + } + } + + + /** + Default order to try different runtime types + + @property order + @type String + @static + */ + Runtime.order = 'html5,flash,silverlight,html4'; + + + /** + Retrieves runtime from private hash by it's uid + + @method getRuntime + @private + @static + @param {String} uid Unique identifier of the runtime + @return {Runtime|Boolean} Returns runtime, if it exists and false, if - not + */ + Runtime.getRuntime = function(uid) { + return runtimes[uid] ? runtimes[uid] : false; + }; + + + /** + Register constructor for the Runtime of new (or perhaps modified) type + + @method addConstructor + @static + @param {String} type Runtime type (e.g. flash, html5, etc) + @param {Function} construct Constructor for the Runtime type + */ + Runtime.addConstructor = function(type, constructor) { + constructor.prototype = EventTarget.instance; + runtimeConstructors[type] = constructor; + }; + + + /** + Get the constructor for the specified type. + + method getConstructor + @static + @param {String} type Runtime type (e.g. flash, html5, etc) + @return {Function} Constructor for the Runtime type + */ + Runtime.getConstructor = function(type) { + return runtimeConstructors[type] || null; + }; + + + /** + Get info about the runtime (uid, type, capabilities) + + @method getInfo + @static + @param {String} uid Unique identifier of the runtime + @return {Mixed} Info object or null if runtime doesn't exist + */ + Runtime.getInfo = function(uid) { + var runtime = Runtime.getRuntime(uid); + + if (runtime) { + return { + uid: runtime.uid, + type: runtime.type, + mode: runtime.mode, + can: function() { + return runtime.can.apply(runtime, arguments); + } + }; + } + return null; + }; + + + /** + Convert caps represented by a comma-separated string to the object representation. + + @method parseCaps + @static + @param {String} capStr Comma-separated list of capabilities + @return {Object} + */ + Runtime.parseCaps = function(capStr) { + var capObj = {}; + + if (Basic.typeOf(capStr) !== 'string') { + return capStr || {}; + } + + Basic.each(capStr.split(','), function(key) { + capObj[key] = true; // we assume it to be - true + }); + + return capObj; + }; + + /** + Test the specified runtime for specific capabilities. + + @method can + @static + @param {String} type Runtime type (e.g. flash, html5, etc) + @param {String|Object} caps Set of capabilities to check + @return {Boolean} Result of the test + */ + Runtime.can = function(type, caps) { + var runtime + , constructor = Runtime.getConstructor(type) + , mode + ; + if (constructor) { + runtime = new constructor({ + required_caps: caps + }); + mode = runtime.mode; + runtime.destroy(); + return !!mode; + } + return false; + }; + + + /** + Figure out a runtime that supports specified capabilities. + + @method thatCan + @static + @param {String|Object} caps Set of capabilities to check + @param {String} [runtimeOrder] Comma-separated list of runtimes to check against + @return {String} Usable runtime identifier or null + */ + Runtime.thatCan = function(caps, runtimeOrder) { + var types = (runtimeOrder || Runtime.order).split(/\s*,\s*/); + for (var i in types) { + if (Runtime.can(types[i], caps)) { + return types[i]; + } + } + return null; + }; + + + /** + Figure out an operational mode for the specified set of capabilities. + + @method getMode + @static + @param {Object} modeCaps Set of capabilities that depend on particular runtime mode + @param {Object} [requiredCaps] Supplied set of capabilities to find operational mode for + @param {String|Boolean} [defaultMode='browser'] Default mode to use + @return {String|Boolean} Compatible operational mode + */ + Runtime.getMode = function(modeCaps, requiredCaps, defaultMode) { + var mode = null; + + if (Basic.typeOf(defaultMode) === 'undefined') { // only if not specified + defaultMode = 'browser'; + } + + if (requiredCaps && !Basic.isEmptyObj(modeCaps)) { + // loop over required caps and check if they do require the same mode + Basic.each(requiredCaps, function(value, cap) { + if (modeCaps.hasOwnProperty(cap)) { + var capMode = modeCaps[cap](value); + + // make sure we always have an array + if (typeof(capMode) === 'string') { + capMode = [capMode]; + } + + if (!mode) { + mode = capMode; + } else if (!(mode = Basic.arrayIntersect(mode, capMode))) { + // if cap requires conflicting mode - runtime cannot fulfill required caps + return (mode = false); + } + } + }); + + if (mode) { + return Basic.inArray(defaultMode, mode) !== -1 ? defaultMode : mode[0]; + } else if (mode === false) { + return false; + } + } + return defaultMode; + }; + + + /** + Capability check that always returns true + + @private + @static + @return {True} + */ + Runtime.capTrue = function() { + return true; + }; + + /** + Capability check that always returns false + + @private + @static + @return {False} + */ + Runtime.capFalse = function() { + return false; + }; + + /** + Evaluate the expression to boolean value and create a function that always returns it. + + @private + @static + @param {Mixed} expr Expression to evaluate + @return {Function} Function returning the result of evaluation + */ + Runtime.capTest = function(expr) { + return function() { + return !!expr; + }; + }; + + return Runtime; +}); + +// Included from: src/javascript/runtime/RuntimeClient.js + +/** + * RuntimeClient.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define('moxie/runtime/RuntimeClient', [ + 'moxie/core/Exceptions', + 'moxie/core/utils/Basic', + 'moxie/runtime/Runtime' +], function(x, Basic, Runtime) { + /** + Set of methods and properties, required by a component to acquire ability to connect to a runtime + + @class RuntimeClient + */ + return function RuntimeClient() { + var runtime; + + Basic.extend(this, { + /** + Connects to the runtime specified by the options. Will either connect to existing runtime or create a new one. + Increments number of clients connected to the specified runtime. + + @method connectRuntime + @param {Mixed} options Can be a runtme uid or a set of key-value pairs defining requirements and pre-requisites + */ + connectRuntime: function(options) { + var comp = this, ruid; + + function initialize(items) { + var type, constructor; + + // if we ran out of runtimes + if (!items.length) { + comp.trigger('RuntimeError', new x.RuntimeError(x.RuntimeError.NOT_INIT_ERR)); + runtime = null; + return; + } + + type = items.shift(); + constructor = Runtime.getConstructor(type); + if (!constructor) { + initialize(items); + return; + } + + // try initializing the runtime + runtime = new constructor(options); + + runtime.bind('Init', function() { + // mark runtime as initialized + runtime.initialized = true; + + // jailbreak ... + setTimeout(function() { + runtime.clients++; + // this will be triggered on component + comp.trigger('RuntimeInit', runtime); + }, 1); + }); + + runtime.bind('Error', function() { + runtime.destroy(); // runtime cannot destroy itself from inside at a right moment, thus we do it here + initialize(items); + }); + + /*runtime.bind('Exception', function() { });*/ + + // check if runtime managed to pick-up operational mode + if (!runtime.mode) { + runtime.trigger('Error'); + return; + } + + runtime.init(); + } + + // check if a particular runtime was requested + if (Basic.typeOf(options) === 'string') { + ruid = options; + } else if (Basic.typeOf(options.ruid) === 'string') { + ruid = options.ruid; + } + + if (ruid) { + runtime = Runtime.getRuntime(ruid); + if (runtime) { + runtime.clients++; + return runtime; + } else { + // there should be a runtime and there's none - weird case + throw new x.RuntimeError(x.RuntimeError.NOT_INIT_ERR); + } + } + + // initialize a fresh one, that fits runtime list and required features best + initialize((options.runtime_order || Runtime.order).split(/\s*,\s*/)); + }, + + /** + Returns the runtime to which the client is currently connected. + + @method getRuntime + @return {Runtime} Runtime or null if client is not connected + */ + getRuntime: function() { + if (runtime && runtime.uid) { + return runtime; + } + runtime = null; // make sure we do not leave zombies rambling around + return null; + }, + + /** + Disconnects from the runtime. Decrements number of clients connected to the specified runtime. + + @method disconnectRuntime + */ + disconnectRuntime: function() { + if (runtime && --runtime.clients <= 0) { + runtime.destroy(); + runtime = null; + } + } + + }); + }; + + +}); + +// Included from: src/javascript/file/Blob.js + +/** + * Blob.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define('moxie/file/Blob', [ + 'moxie/core/utils/Basic', + 'moxie/core/utils/Encode', + 'moxie/runtime/RuntimeClient' +], function(Basic, Encode, RuntimeClient) { + + var blobpool = {}; + + /** + @class Blob + @constructor + @param {String} ruid Unique id of the runtime, to which this blob belongs to + @param {Object} blob Object "Native" blob object, as it is represented in the runtime + */ + function Blob(ruid, blob) { + + function _sliceDetached(start, end, type) { + var blob, data = blobpool[this.uid]; + + if (Basic.typeOf(data) !== 'string' || !data.length) { + return null; // or throw exception + } + + blob = new Blob(null, { + type: type, + size: end - start + }); + blob.detach(data.substr(start, blob.size)); + + return blob; + } + + RuntimeClient.call(this); + + if (ruid) { + this.connectRuntime(ruid); + } + + if (!blob) { + blob = {}; + } else if (Basic.typeOf(blob) === 'string') { // dataUrl or binary string + blob = { data: blob }; + } + + Basic.extend(this, { + + /** + Unique id of the component + + @property uid + @type {String} + */ + uid: blob.uid || Basic.guid('uid_'), + + /** + Unique id of the connected runtime, if falsy, then runtime will have to be initialized + before this Blob can be used, modified or sent + + @property ruid + @type {String} + */ + ruid: ruid, + + /** + Size of blob + + @property size + @type {Number} + @default 0 + */ + size: blob.size || 0, + + /** + Mime type of blob + + @property type + @type {String} + @default '' + */ + type: blob.type || '', + + /** + @method slice + @param {Number} [start=0] + */ + slice: function(start, end, type) { + if (this.isDetached()) { + return _sliceDetached.apply(this, arguments); + } + return this.getRuntime().exec.call(this, 'Blob', 'slice', this.getSource(), start, end, type); + }, + + /** + Returns "native" blob object (as it is represented in connected runtime) or null if not found + + @method getSource + @return {Blob} Returns "native" blob object or null if not found + */ + getSource: function() { + if (!blobpool[this.uid]) { + return null; + } + return blobpool[this.uid]; + }, + + /** + Detaches blob from any runtime that it depends on and initialize with standalone value + + @method detach + @protected + @param {DOMString} [data=''] Standalone value + */ + detach: function(data) { + if (this.ruid) { + this.getRuntime().exec.call(this, 'Blob', 'destroy'); + this.disconnectRuntime(); + this.ruid = null; + } + + data = data || ''; + + // if dataUrl, convert to binary string + var matches = data.match(/^data:([^;]*);base64,/); + if (matches) { + this.type = matches[1]; + data = Encode.atob(data.substring(data.indexOf('base64,') + 7)); + } + + this.size = data.length; + + blobpool[this.uid] = data; + }, + + /** + Checks if blob is standalone (detached of any runtime) + + @method isDetached + @protected + @return {Boolean} + */ + isDetached: function() { + return !this.ruid && Basic.typeOf(blobpool[this.uid]) === 'string'; + }, + + /** + Destroy Blob and free any resources it was using + + @method destroy + */ + destroy: function() { + this.detach(); + delete blobpool[this.uid]; + } + }); + + + if (blob.data) { + this.detach(blob.data); // auto-detach if payload has been passed + } else { + blobpool[this.uid] = blob; + } + } + + return Blob; +}); + +// Included from: src/javascript/file/File.js + +/** + * File.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define('moxie/file/File', [ + 'moxie/core/utils/Basic', + 'moxie/core/utils/Mime', + 'moxie/file/Blob' +], function(Basic, Mime, Blob) { + /** + @class File + @extends Blob + @constructor + @param {String} ruid Unique id of the runtime, to which this blob belongs to + @param {Object} file Object "Native" file object, as it is represented in the runtime + */ + function File(ruid, file) { + var name, type; + + if (!file) { // avoid extra errors in case we overlooked something + file = {}; + } + + // figure out the type + if (file.type && file.type !== '') { + type = file.type; + } else { + type = Mime.getFileMime(file.name); + } + + // sanitize file name or generate new one + if (file.name) { + name = file.name.replace(/\\/g, '/'); + name = name.substr(name.lastIndexOf('/') + 1); + } else { + var prefix = type.split('/')[0]; + name = Basic.guid((prefix !== '' ? prefix : 'file') + '_'); + + if (Mime.extensions[type]) { + name += '.' + Mime.extensions[type][0]; // append proper extension if possible + } + } + + Blob.apply(this, arguments); + + Basic.extend(this, { + /** + File mime type + + @property type + @type {String} + @default '' + */ + type: type || '', + + /** + File name + + @property name + @type {String} + @default UID + */ + name: name || Basic.guid('file_'), + + /** + Date of last modification + + @property lastModifiedDate + @type {String} + @default now + */ + lastModifiedDate: file.lastModifiedDate || (new Date()).toLocaleString() // Thu Aug 23 2012 19:40:00 GMT+0400 (GET) + }); + } + + File.prototype = Blob.prototype; + + return File; +}); + +// Included from: src/javascript/file/FileInput.js + +/** + * FileInput.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define('moxie/file/FileInput', [ + 'moxie/core/utils/Basic', + 'moxie/core/utils/Mime', + 'moxie/core/utils/Dom', + 'moxie/core/Exceptions', + 'moxie/core/EventTarget', + 'moxie/core/I18n', + 'moxie/file/File', + 'moxie/runtime/Runtime', + 'moxie/runtime/RuntimeClient' +], function(Basic, Mime, Dom, x, EventTarget, I18n, File, Runtime, RuntimeClient) { + /** + Provides a convenient way to create cross-browser file-picker. Generates file selection dialog on click, + converts selected files to _File_ objects, to be used in conjunction with _Image_, preloaded in memory + with _FileReader_ or uploaded to a server through _XMLHttpRequest_. + + @class FileInput + @constructor + @extends EventTarget + @uses RuntimeClient + @param {Object|String|DOMElement} options If options is string or node, argument is considered as _browse\_button_. + @param {String|DOMElement} options.browse_button DOM Element to turn into file picker. + @param {Array} [options.accept] Array of mime types to accept. By default accepts all. + @param {String} [options.file='file'] Name of the file field (not the filename). + @param {Boolean} [options.multiple=false] Enable selection of multiple files. + @param {Boolean} [options.directory=false] Turn file input into the folder input (cannot be both at the same time). + @param {String|DOMElement} [options.container] DOM Element to use as a container for file-picker. Defaults to parentNode + for _browse\_button_. + @param {Object|String} [options.required_caps] Set of required capabilities, that chosen runtime must support. + + @example +
      + Browse... +
      + + + */ + var dispatches = [ + /** + Dispatched when runtime is connected and file-picker is ready to be used. + + @event ready + @param {Object} event + */ + 'ready', + + /** + Dispatched right after [ready](#event_ready) event, and whenever [refresh()](#method_refresh) is invoked. + Check [corresponding documentation entry](#method_refresh) for more info. + + @event refresh + @param {Object} event + */ + + /** + Dispatched when selection of files in the dialog is complete. + + @event change + @param {Object} event + */ + 'change', + + 'cancel', // TODO: might be useful + + /** + Dispatched when mouse cursor enters file-picker area. Can be used to style element + accordingly. + + @event mouseenter + @param {Object} event + */ + 'mouseenter', + + /** + Dispatched when mouse cursor leaves file-picker area. Can be used to style element + accordingly. + + @event mouseleave + @param {Object} event + */ + 'mouseleave', + + /** + Dispatched when functional mouse button is pressed on top of file-picker area. + + @event mousedown + @param {Object} event + */ + 'mousedown', + + /** + Dispatched when functional mouse button is released on top of file-picker area. + + @event mouseup + @param {Object} event + */ + 'mouseup' + ]; + + function FileInput(options) { + var self = this, + container, browseButton, defaults; + + // if flat argument passed it should be browse_button id + if (Basic.inArray(Basic.typeOf(options), ['string', 'node']) !== -1) { + options = { browse_button : options }; + } + + // this will help us to find proper default container + browseButton = Dom.get(options.browse_button); + if (!browseButton) { + // browse button is required + throw new x.DOMException(x.DOMException.NOT_FOUND_ERR); + } + + // figure out the options + defaults = { + accept: [{ + title: I18n.translate('All Files'), + extensions: '*' + }], + name: 'file', + multiple: false, + required_caps: false, + container: browseButton.parentNode || document.body + }; + + options = Basic.extend({}, defaults, options); + + // convert to object representation + if (typeof(options.required_caps) === 'string') { + options.required_caps = Runtime.parseCaps(options.required_caps); + } + + // normalize accept option (could be list of mime types or array of title/extensions pairs) + if (typeof(options.accept) === 'string') { + options.accept = Mime.mimes2extList(options.accept); + } + + container = Dom.get(options.container); + // make sure we have container + if (!container) { + container = document.body; + } + + // make container relative, if it's not + if (Dom.getStyle(container, 'position') === 'static') { + container.style.position = 'relative'; + } + + container = browseButton = null; // IE + + RuntimeClient.call(self); + + Basic.extend(self, { + /** + Unique id of the component + + @property uid + @protected + @readOnly + @type {String} + @default UID + */ + uid: Basic.guid('uid_'), + + /** + Unique id of the connected runtime, if any. + + @property ruid + @protected + @type {String} + */ + ruid: null, + + /** + Unique id of the runtime container. Useful to get hold of it for various manipulations. + + @property shimid + @protected + @type {String} + */ + shimid: null, + + /** + Array of selected mOxie.File objects + + @property files + @type {Array} + @default null + */ + files: null, + + /** + Initializes the file-picker, connects it to runtime and dispatches event ready when done. + + @method init + */ + init: function() { + self.convertEventPropsToHandlers(dispatches); + + self.bind('RuntimeInit', function(e, runtime) { + self.ruid = runtime.uid; + self.shimid = runtime.shimid; + + self.bind("Ready", function() { + self.trigger("Refresh"); + }, 999); + + self.bind("Change", function() { + var files = runtime.exec.call(self, 'FileInput', 'getFiles'); + + self.files = []; + + Basic.each(files, function(file) { + // ignore empty files (IE10 for example hangs if you try to send them via XHR) + if (file.size === 0) { + return true; + } + self.files.push(new File(self.ruid, file)); + }); + }, 999); + + // re-position and resize shim container + self.bind('Refresh', function() { + var pos, size, browseButton, shimContainer; + + browseButton = Dom.get(options.browse_button); + shimContainer = Dom.get(runtime.shimid); // do not use runtime.getShimContainer(), since it will create container if it doesn't exist + + if (browseButton) { + pos = Dom.getPos(browseButton, Dom.get(options.container)); + size = Dom.getSize(browseButton); + + if (shimContainer) { + Basic.extend(shimContainer.style, { + top : pos.y + 'px', + left : pos.x + 'px', + width : size.w + 'px', + height : size.h + 'px' + }); + } + } + shimContainer = browseButton = null; + }); + + runtime.exec.call(self, 'FileInput', 'init', options); + }); + + // runtime needs: options.required_features, options.runtime_order and options.container + self.connectRuntime(Basic.extend({}, options, { + required_caps: { + select_file: true + } + })); + }, + + /** + Disables file-picker element, so that it doesn't react to mouse clicks. + + @method disable + @param {Boolean} [state=true] Disable component if - true, enable if - false + */ + disable: function(state) { + var runtime = this.getRuntime(); + if (runtime) { + runtime.exec.call(this, 'FileInput', 'disable', Basic.typeOf(state) === 'undefined' ? true : state); + } + }, + + + /** + Reposition and resize dialog trigger to match the position and size of browse_button element. + + @method refresh + */ + refresh: function() { + self.trigger("Refresh"); + }, + + + /** + Destroy component. + + @method destroy + */ + destroy: function() { + var runtime = this.getRuntime(); + if (runtime) { + runtime.exec.call(this, 'FileInput', 'destroy'); + this.disconnectRuntime(); + } + + if (Basic.typeOf(this.files) === 'array') { + // no sense in leaving associated files behind + Basic.each(this.files, function(file) { + file.destroy(); + }); + } + this.files = null; + } + }); + } + + FileInput.prototype = EventTarget.instance; + + return FileInput; +}); + +// Included from: src/javascript/file/FileDrop.js + +/** + * FileDrop.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define('moxie/file/FileDrop', [ + 'moxie/core/I18n', + 'moxie/core/utils/Dom', + 'moxie/core/Exceptions', + 'moxie/core/utils/Basic', + 'moxie/file/File', + 'moxie/runtime/RuntimeClient', + 'moxie/core/EventTarget', + 'moxie/core/utils/Mime' +], function(I18n, Dom, x, Basic, File, RuntimeClient, EventTarget, Mime) { + /** + Turn arbitrary DOM element to a drop zone accepting files. Converts selected files to _File_ objects, to be used + in conjunction with _Image_, preloaded in memory with _FileReader_ or uploaded to a server through + _XMLHttpRequest_. + + @example +
      + Drop files here +
      +
      +
      + + + + @class FileDrop + @constructor + @extends EventTarget + @uses RuntimeClient + @param {Object|String} options If options has typeof string, argument is considered as options.drop_zone + @param {String|DOMElement} options.drop_zone DOM Element to turn into a drop zone + @param {Array} [options.accept] Array of mime types to accept. By default accepts all + @param {Object|String} [options.required_caps] Set of required capabilities, that chosen runtime must support + */ + var dispatches = [ + /** + Dispatched when runtime is connected and drop zone is ready to accept files. + + @event ready + @param {Object} event + */ + 'ready', + + /** + Dispatched when dragging cursor enters the drop zone. + + @event dragenter + @param {Object} event + */ + 'dragenter', + + /** + Dispatched when dragging cursor leaves the drop zone. + + @event dragleave + @param {Object} event + */ + 'dragleave', + + /** + Dispatched when file is dropped onto the drop zone. + + @event drop + @param {Object} event + */ + 'drop', + + /** + Dispatched if error occurs. + + @event error + @param {Object} event + */ + 'error' + ]; + + function FileDrop(options) { + var self = this, defaults; + + // if flat argument passed it should be drop_zone id + if (typeof(options) === 'string') { + options = { drop_zone : options }; + } + + // figure out the options + defaults = { + accept: [{ + title: I18n.translate('All Files'), + extensions: '*' + }], + required_caps: { + drag_and_drop: true + } + }; + + options = typeof(options) === 'object' ? Basic.extend({}, defaults, options) : defaults; + + // this will help us to find proper default container + options.container = Dom.get(options.drop_zone) || document.body; + + // make container relative, if it is not + if (Dom.getStyle(options.container, 'position') === 'static') { + options.container.style.position = 'relative'; + } + + // normalize accept option (could be list of mime types or array of title/extensions pairs) + if (typeof(options.accept) === 'string') { + options.accept = Mime.mimes2extList(options.accept); + } + + RuntimeClient.call(self); + + Basic.extend(self, { + uid: Basic.guid('uid_'), + + ruid: null, + + files: null, + + init: function() { + + self.convertEventPropsToHandlers(dispatches); + + self.bind('RuntimeInit', function(e, runtime) { + self.ruid = runtime.uid; + + self.bind("Drop", function() { + var files = runtime.exec.call(self, 'FileDrop', 'getFiles'); + + self.files = []; + + Basic.each(files, function(file) { + self.files.push(new File(self.ruid, file)); + }); + }, 999); + + runtime.exec.call(self, 'FileDrop', 'init', options); + + self.dispatchEvent('ready'); + }); + + // runtime needs: options.required_features, options.runtime_order and options.container + self.connectRuntime(options); // throws RuntimeError + }, + + destroy: function() { + var runtime = this.getRuntime(); + if (runtime) { + runtime.exec.call(this, 'FileDrop', 'destroy'); + this.disconnectRuntime(); + } + this.files = null; + } + }); + } + + FileDrop.prototype = EventTarget.instance; + + return FileDrop; +}); + +// Included from: src/javascript/runtime/RuntimeTarget.js + +/** + * RuntimeTarget.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define('moxie/runtime/RuntimeTarget', [ + 'moxie/core/utils/Basic', + 'moxie/runtime/RuntimeClient', + "moxie/core/EventTarget" +], function(Basic, RuntimeClient, EventTarget) { + /** + Instance of this class can be used as a target for the events dispatched by shims, + when allowing them onto components is for either reason inappropriate + + @class RuntimeTarget + @constructor + @protected + @extends EventTarget + */ + function RuntimeTarget() { + this.uid = Basic.guid('uid_'); + + RuntimeClient.call(this); + + this.destroy = function() { + this.disconnectRuntime(); + this.unbindAll(); + }; + } + + RuntimeTarget.prototype = EventTarget.instance; + + return RuntimeTarget; +}); + +// Included from: src/javascript/file/FileReader.js + +/** + * FileReader.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define('moxie/file/FileReader', [ + 'moxie/core/utils/Basic', + 'moxie/core/utils/Encode', + 'moxie/core/Exceptions', + 'moxie/core/EventTarget', + 'moxie/file/Blob', + 'moxie/file/File', + 'moxie/runtime/RuntimeTarget' +], function(Basic, Encode, x, EventTarget, Blob, File, RuntimeTarget) { + /** + Utility for preloading o.Blob/o.File objects in memory. By design closely follows [W3C FileReader](http://www.w3.org/TR/FileAPI/#dfn-filereader) + interface. Where possible uses native FileReader, where - not falls back to shims. + + @class FileReader + @constructor FileReader + @extends EventTarget + @uses RuntimeClient + */ + var dispatches = [ + + /** + Dispatched when the read starts. + + @event loadstart + @param {Object} event + */ + 'loadstart', + + /** + Dispatched while reading (and decoding) blob, and reporting partial Blob data (progess.loaded/progress.total). + + @event progress + @param {Object} event + */ + 'progress', + + /** + Dispatched when the read has successfully completed. + + @event load + @param {Object} event + */ + 'load', + + /** + Dispatched when the read has been aborted. For instance, by invoking the abort() method. + + @event abort + @param {Object} event + */ + 'abort', + + /** + Dispatched when the read has failed. + + @event error + @param {Object} event + */ + 'error', + + /** + Dispatched when the request has completed (either in success or failure). + + @event loadend + @param {Object} event + */ + 'loadend' + ]; + + function FileReader() { + var self = this, _fr; + + Basic.extend(this, { + /** + UID of the component instance. + + @property uid + @type {String} + */ + uid: Basic.guid('uid_'), + + /** + Contains current state of FileReader object. Can take values of FileReader.EMPTY, FileReader.LOADING + and FileReader.DONE. + + @property readyState + @type {Number} + @default FileReader.EMPTY + */ + readyState: FileReader.EMPTY, + + /** + Result of the successful read operation. + + @property result + @type {String} + */ + result: null, + + /** + Stores the error of failed asynchronous read operation. + + @property error + @type {DOMError} + */ + error: null, + + /** + Initiates reading of File/Blob object contents to binary string. + + @method readAsBinaryString + @param {Blob|File} blob Object to preload + */ + readAsBinaryString: function(blob) { + _read.call(this, 'readAsBinaryString', blob); + }, + + /** + Initiates reading of File/Blob object contents to dataURL string. + + @method readAsDataURL + @param {Blob|File} blob Object to preload + */ + readAsDataURL: function(blob) { + _read.call(this, 'readAsDataURL', blob); + }, + + /** + Initiates reading of File/Blob object contents to string. + + @method readAsText + @param {Blob|File} blob Object to preload + */ + readAsText: function(blob) { + _read.call(this, 'readAsText', blob); + }, + + /** + Aborts preloading process. + + @method abort + */ + abort: function() { + this.result = null; + + if (Basic.inArray(this.readyState, [FileReader.EMPTY, FileReader.DONE]) !== -1) { + return; + } else if (this.readyState === FileReader.LOADING) { + this.readyState = FileReader.DONE; + } + + if (_fr) { + _fr.getRuntime().exec.call(this, 'FileReader', 'abort'); + } + + this.trigger('abort'); + this.trigger('loadend'); + }, + + /** + Destroy component and release resources. + + @method destroy + */ + destroy: function() { + this.abort(); + + if (_fr) { + _fr.getRuntime().exec.call(this, 'FileReader', 'destroy'); + _fr.disconnectRuntime(); + } + + self = _fr = null; + } + }); + + + function _read(op, blob) { + _fr = new RuntimeTarget(); + + function error(err) { + self.readyState = FileReader.DONE; + self.error = err; + self.trigger('error'); + loadEnd(); + } + + function loadEnd() { + _fr.destroy(); + _fr = null; + self.trigger('loadend'); + } + + function exec(runtime) { + _fr.bind('Error', function(e, err) { + error(err); + }); + + _fr.bind('Progress', function(e) { + self.result = runtime.exec.call(_fr, 'FileReader', 'getResult'); + self.trigger(e); + }); + + _fr.bind('Load', function(e) { + self.readyState = FileReader.DONE; + self.result = runtime.exec.call(_fr, 'FileReader', 'getResult'); + self.trigger(e); + loadEnd(); + }); + + runtime.exec.call(_fr, 'FileReader', 'read', op, blob); + } + + this.convertEventPropsToHandlers(dispatches); + + if (this.readyState === FileReader.LOADING) { + return error(new x.DOMException(x.DOMException.INVALID_STATE_ERR)); + } + + this.readyState = FileReader.LOADING; + this.trigger('loadstart'); + + // if source is o.Blob/o.File + if (blob instanceof Blob) { + if (blob.isDetached()) { + var src = blob.getSource(); + switch (op) { + case 'readAsText': + case 'readAsBinaryString': + this.result = src; + break; + case 'readAsDataURL': + this.result = 'data:' + blob.type + ';base64,' + Encode.btoa(src); + break; + } + this.readyState = FileReader.DONE; + this.trigger('load'); + loadEnd(); + } else { + exec(_fr.connectRuntime(blob.ruid)); + } + } else { + error(new x.DOMException(x.DOMException.NOT_FOUND_ERR)); + } + } + } + + /** + Initial FileReader state + + @property EMPTY + @type {Number} + @final + @static + @default 0 + */ + FileReader.EMPTY = 0; + + /** + FileReader switches to this state when it is preloading the source + + @property LOADING + @type {Number} + @final + @static + @default 1 + */ + FileReader.LOADING = 1; + + /** + Preloading is complete, this is a final state + + @property DONE + @type {Number} + @final + @static + @default 2 + */ + FileReader.DONE = 2; + + FileReader.prototype = EventTarget.instance; + + return FileReader; +}); + +// Included from: src/javascript/core/utils/Url.js + +/** + * Url.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define('moxie/core/utils/Url', [], function() { + /** + Parse url into separate components and fill in absent parts with parts from current url, + based on https://raw.github.com/kvz/phpjs/master/functions/url/parse_url.js + + @method parseUrl + @for Utils + @static + @param {String} url Url to parse (defaults to empty string if undefined) + @return {Object} Hash containing extracted uri components + */ + var parseUrl = function(url, currentUrl) { + var key = ['source', 'scheme', 'authority', 'userInfo', 'user', 'pass', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'fragment'] + , i = key.length + , ports = { + http: 80, + https: 443 + } + , uri = {} + , regex = /^(?:([^:\/?#]+):)?(?:\/\/()(?:(?:()(?:([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?()(?:(()(?:(?:[^?#\/]*\/)*)()(?:[^?#]*))(?:\\?([^#]*))?(?:#(.*))?)/ + , m = regex.exec(url || '') + ; + + while (i--) { + if (m[i]) { + uri[key[i]] = m[i]; + } + } + + // when url is relative, we set the origin and the path ourselves + if (!uri.scheme) { + // come up with defaults + if (!currentUrl || typeof(currentUrl) === 'string') { + currentUrl = parseUrl(currentUrl || document.location.href); + } + + uri.scheme = currentUrl.scheme; + uri.host = currentUrl.host; + uri.port = currentUrl.port; + + var path = ''; + // for urls without trailing slash we need to figure out the path + if (/^[^\/]/.test(uri.path)) { + path = currentUrl.path; + // if path ends with a filename, strip it + if (!/(\/|\/[^\.]+)$/.test(path)) { + path = path.replace(/\/[^\/]+$/, '/'); + } else { + path += '/'; + } + } + uri.path = path + (uri.path || ''); // site may reside at domain.com or domain.com/subdir + } + + if (!uri.port) { + uri.port = ports[uri.scheme] || 80; + } + + uri.port = parseInt(uri.port, 10); + + if (!uri.path) { + uri.path = "/"; + } + + delete uri.source; + + return uri; + }; + + /** + Resolve url - among other things will turn relative url to absolute + + @method resolveUrl + @static + @param {String} url Either absolute or relative + @return {String} Resolved, absolute url + */ + var resolveUrl = function(url) { + var ports = { // we ignore default ports + http: 80, + https: 443 + } + , urlp = parseUrl(url) + ; + + return urlp.scheme + '://' + urlp.host + (urlp.port !== ports[urlp.scheme] ? ':' + urlp.port : '') + urlp.path + (urlp.query ? urlp.query : ''); + }; + + /** + Check if specified url has the same origin as the current document + + @method hasSameOrigin + @param {String|Object} url + @return {Boolean} + */ + var hasSameOrigin = function(url) { + function origin(url) { + return [url.scheme, url.host, url.port].join('/'); + } + + if (typeof url === 'string') { + url = parseUrl(url); + } + + return origin(parseUrl()) === origin(url); + }; + + return { + parseUrl: parseUrl, + resolveUrl: resolveUrl, + hasSameOrigin: hasSameOrigin + }; +}); + +// Included from: src/javascript/file/FileReaderSync.js + +/** + * FileReaderSync.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define('moxie/file/FileReaderSync', [ + 'moxie/core/utils/Basic', + 'moxie/runtime/RuntimeClient', + 'moxie/core/utils/Encode' +], function(Basic, RuntimeClient, Encode) { + /** + Synchronous FileReader implementation. Something like this is available in WebWorkers environment, here + it can be used to read only preloaded blobs/files and only below certain size (not yet sure what that'd be, + but probably < 1mb). Not meant to be used directly by user. + + @class FileReaderSync + @private + @constructor + */ + return function() { + RuntimeClient.call(this); + + Basic.extend(this, { + uid: Basic.guid('uid_'), + + readAsBinaryString: function(blob) { + return _read.call(this, 'readAsBinaryString', blob); + }, + + readAsDataURL: function(blob) { + return _read.call(this, 'readAsDataURL', blob); + }, + + /*readAsArrayBuffer: function(blob) { + return _read.call(this, 'readAsArrayBuffer', blob); + },*/ + + readAsText: function(blob) { + return _read.call(this, 'readAsText', blob); + } + }); + + function _read(op, blob) { + if (blob.isDetached()) { + var src = blob.getSource(); + switch (op) { + case 'readAsBinaryString': + return src; + case 'readAsDataURL': + return 'data:' + blob.type + ';base64,' + Encode.btoa(src); + case 'readAsText': + var txt = ''; + for (var i = 0, length = src.length; i < length; i++) { + txt += String.fromCharCode(src[i]); + } + return txt; + } + } else { + var result = this.connectRuntime(blob.ruid).exec.call(this, 'FileReaderSync', 'read', op, blob); + this.disconnectRuntime(); + return result; + } + } + }; +}); + +// Included from: src/javascript/xhr/FormData.js + +/** + * FormData.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define("moxie/xhr/FormData", [ + "moxie/core/Exceptions", + "moxie/core/utils/Basic", + "moxie/file/Blob" +], function(x, Basic, Blob) { + /** + FormData + + @class FormData + @constructor + */ + function FormData() { + var _blob, _fields = []; + + Basic.extend(this, { + /** + Append another key-value pair to the FormData object + + @method append + @param {String} name Name for the new field + @param {String|Blob|Array|Object} value Value for the field + */ + append: function(name, value) { + var self = this, valueType = Basic.typeOf(value); + + // according to specs value might be either Blob or String + if (value instanceof Blob) { + _blob = { + name: name, + value: value // unfortunately we can only send single Blob in one FormData + }; + } else if ('array' === valueType) { + name += '[]'; + + Basic.each(value, function(value) { + self.append(name, value); + }); + } else if ('object' === valueType) { + Basic.each(value, function(value, key) { + self.append(name + '[' + key + ']', value); + }); + } else if ('null' === valueType || 'undefined' === valueType || 'number' === valueType && isNaN(value)) { + self.append(name, "false"); + } else { + _fields.push({ + name: name, + value: value.toString() + }); + } + }, + + /** + Checks if FormData contains Blob. + + @method hasBlob + @return {Boolean} + */ + hasBlob: function() { + return !!this.getBlob(); + }, + + /** + Retrieves blob. + + @method getBlob + @return {Object} Either Blob if found or null + */ + getBlob: function() { + return _blob && _blob.value || null; + }, + + /** + Retrieves blob field name. + + @method getBlobName + @return {String} Either Blob field name or null + */ + getBlobName: function() { + return _blob && _blob.name || null; + }, + + /** + Loop over the fields in FormData and invoke the callback for each of them. + + @method each + @param {Function} cb Callback to call for each field + */ + each: function(cb) { + Basic.each(_fields, function(field) { + cb(field.value, field.name); + }); + + if (_blob) { + cb(_blob.value, _blob.name); + } + }, + + destroy: function() { + _blob = null; + _fields = []; + } + }); + } + + return FormData; +}); + +// Included from: src/javascript/xhr/XMLHttpRequest.js + +/** + * XMLHttpRequest.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define("moxie/xhr/XMLHttpRequest", [ + "moxie/core/utils/Basic", + "moxie/core/Exceptions", + "moxie/core/EventTarget", + "moxie/core/utils/Encode", + "moxie/core/utils/Url", + "moxie/runtime/Runtime", + "moxie/runtime/RuntimeTarget", + "moxie/file/Blob", + "moxie/file/FileReaderSync", + "moxie/xhr/FormData", + "moxie/core/utils/Env", + "moxie/core/utils/Mime" +], function(Basic, x, EventTarget, Encode, Url, Runtime, RuntimeTarget, Blob, FileReaderSync, FormData, Env, Mime) { + + var httpCode = { + 100: 'Continue', + 101: 'Switching Protocols', + 102: 'Processing', + + 200: 'OK', + 201: 'Created', + 202: 'Accepted', + 203: 'Non-Authoritative Information', + 204: 'No Content', + 205: 'Reset Content', + 206: 'Partial Content', + 207: 'Multi-Status', + 226: 'IM Used', + + 300: 'Multiple Choices', + 301: 'Moved Permanently', + 302: 'Found', + 303: 'See Other', + 304: 'Not Modified', + 305: 'Use Proxy', + 306: 'Reserved', + 307: 'Temporary Redirect', + + 400: 'Bad Request', + 401: 'Unauthorized', + 402: 'Payment Required', + 403: 'Forbidden', + 404: 'Not Found', + 405: 'Method Not Allowed', + 406: 'Not Acceptable', + 407: 'Proxy Authentication Required', + 408: 'Request Timeout', + 409: 'Conflict', + 410: 'Gone', + 411: 'Length Required', + 412: 'Precondition Failed', + 413: 'Request Entity Too Large', + 414: 'Request-URI Too Long', + 415: 'Unsupported Media Type', + 416: 'Requested Range Not Satisfiable', + 417: 'Expectation Failed', + 422: 'Unprocessable Entity', + 423: 'Locked', + 424: 'Failed Dependency', + 426: 'Upgrade Required', + + 500: 'Internal Server Error', + 501: 'Not Implemented', + 502: 'Bad Gateway', + 503: 'Service Unavailable', + 504: 'Gateway Timeout', + 505: 'HTTP Version Not Supported', + 506: 'Variant Also Negotiates', + 507: 'Insufficient Storage', + 510: 'Not Extended' + }; + + function XMLHttpRequestUpload() { + this.uid = Basic.guid('uid_'); + } + + XMLHttpRequestUpload.prototype = EventTarget.instance; + + /** + Implementation of XMLHttpRequest + + @class XMLHttpRequest + @constructor + @uses RuntimeClient + @extends EventTarget + */ + var dispatches = ['loadstart', 'progress', 'abort', 'error', 'load', 'timeout', 'loadend']; // & readystatechange (for historical reasons) + + var NATIVE = 1, RUNTIME = 2; + + function XMLHttpRequest() { + var self = this, + // this (together with _p() @see below) is here to gracefully upgrade to setter/getter syntax where possible + props = { + /** + The amount of milliseconds a request can take before being terminated. Initially zero. Zero means there is no timeout. + + @property timeout + @type Number + @default 0 + */ + timeout: 0, + + /** + Current state, can take following values: + UNSENT (numeric value 0) + The object has been constructed. + + OPENED (numeric value 1) + The open() method has been successfully invoked. During this state request headers can be set using setRequestHeader() and the request can be made using the send() method. + + HEADERS_RECEIVED (numeric value 2) + All redirects (if any) have been followed and all HTTP headers of the final response have been received. Several response members of the object are now available. + + LOADING (numeric value 3) + The response entity body is being received. + + DONE (numeric value 4) + + @property readyState + @type Number + @default 0 (UNSENT) + */ + readyState: XMLHttpRequest.UNSENT, + + /** + True when user credentials are to be included in a cross-origin request. False when they are to be excluded + in a cross-origin request and when cookies are to be ignored in its response. Initially false. + + @property withCredentials + @type Boolean + @default false + */ + withCredentials: false, + + /** + Returns the HTTP status code. + + @property status + @type Number + @default 0 + */ + status: 0, + + /** + Returns the HTTP status text. + + @property statusText + @type String + */ + statusText: "", + + /** + Returns the response type. Can be set to change the response type. Values are: + the empty string (default), "arraybuffer", "blob", "document", "json", and "text". + + @property responseType + @type String + */ + responseType: "", + + /** + Returns the document response entity body. + + Throws an "InvalidStateError" exception if responseType is not the empty string or "document". + + @property responseXML + @type Document + */ + responseXML: null, + + /** + Returns the text response entity body. + + Throws an "InvalidStateError" exception if responseType is not the empty string or "text". + + @property responseText + @type String + */ + responseText: null, + + /** + Returns the response entity body (http://www.w3.org/TR/XMLHttpRequest/#response-entity-body). + Can become: ArrayBuffer, Blob, Document, JSON, Text + + @property response + @type Mixed + */ + response: null + }, + + _async = true, + _url, + _method, + _headers = {}, + _user, + _password, + _encoding = null, + _mimeType = null, + + // flags + _sync_flag = false, + _send_flag = false, + _upload_events_flag = false, + _upload_complete_flag = false, + _error_flag = false, + _same_origin_flag = false, + + // times + _start_time, + _timeoutset_time, + + _finalMime = null, + _finalCharset = null, + + _options = {}, + _xhr, + _responseHeaders = '', + _responseHeadersBag + ; + + + Basic.extend(this, props, { + /** + Unique id of the component + + @property uid + @type String + */ + uid: Basic.guid('uid_'), + + /** + Target for Upload events + + @property upload + @type XMLHttpRequestUpload + */ + upload: new XMLHttpRequestUpload(), + + + /** + Sets the request method, request URL, synchronous flag, request username, and request password. + + Throws a "SyntaxError" exception if one of the following is true: + + method is not a valid HTTP method. + url cannot be resolved. + url contains the "user:password" format in the userinfo production. + Throws a "SecurityError" exception if method is a case-insensitive match for CONNECT, TRACE or TRACK. + + Throws an "InvalidAccessError" exception if one of the following is true: + + Either user or password is passed as argument and the origin of url does not match the XMLHttpRequest origin. + There is an associated XMLHttpRequest document and either the timeout attribute is not zero, + the withCredentials attribute is true, or the responseType attribute is not the empty string. + + + @method open + @param {String} method HTTP method to use on request + @param {String} url URL to request + @param {Boolean} [async=true] If false request will be done in synchronous manner. Asynchronous by default. + @param {String} [user] Username to use in HTTP authentication process on server-side + @param {String} [password] Password to use in HTTP authentication process on server-side + */ + open: function(method, url, async, user, password) { + var urlp; + + // first two arguments are required + if (!method || !url) { + throw new x.DOMException(x.DOMException.SYNTAX_ERR); + } + + // 2 - check if any code point in method is higher than U+00FF or after deflating method it does not match the method + if (/[\u0100-\uffff]/.test(method) || Encode.utf8_encode(method) !== method) { + throw new x.DOMException(x.DOMException.SYNTAX_ERR); + } + + // 3 + if (!!~Basic.inArray(method.toUpperCase(), ['CONNECT', 'DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT', 'TRACE', 'TRACK'])) { + _method = method.toUpperCase(); + } + + + // 4 - allowing these methods poses a security risk + if (!!~Basic.inArray(_method, ['CONNECT', 'TRACE', 'TRACK'])) { + throw new x.DOMException(x.DOMException.SECURITY_ERR); + } + + // 5 + url = Encode.utf8_encode(url); + + // 6 - Resolve url relative to the XMLHttpRequest base URL. If the algorithm returns an error, throw a "SyntaxError". + urlp = Url.parseUrl(url); + + _same_origin_flag = Url.hasSameOrigin(urlp); + + // 7 - manually build up absolute url + _url = Url.resolveUrl(url); + + // 9-10, 12-13 + if ((user || password) && !_same_origin_flag) { + throw new x.DOMException(x.DOMException.INVALID_ACCESS_ERR); + } + + _user = user || urlp.user; + _password = password || urlp.pass; + + // 11 + _async = async || true; + + if (_async === false && (_p('timeout') || _p('withCredentials') || _p('responseType') !== "")) { + throw new x.DOMException(x.DOMException.INVALID_ACCESS_ERR); + } + + // 14 - terminate abort() + + // 15 - terminate send() + + // 18 + _sync_flag = !_async; + _send_flag = false; + _headers = {}; + _reset.call(this); + + // 19 + _p('readyState', XMLHttpRequest.OPENED); + + // 20 + this.convertEventPropsToHandlers(['readystatechange']); // unify event handlers + this.dispatchEvent('readystatechange'); + }, + + /** + Appends an header to the list of author request headers, or if header is already + in the list of author request headers, combines its value with value. + + Throws an "InvalidStateError" exception if the state is not OPENED or if the send() flag is set. + Throws a "SyntaxError" exception if header is not a valid HTTP header field name or if value + is not a valid HTTP header field value. + + @method setRequestHeader + @param {String} header + @param {String|Number} value + */ + setRequestHeader: function(header, value) { + var uaHeaders = [ // these headers are controlled by the user agent + "accept-charset", + "accept-encoding", + "access-control-request-headers", + "access-control-request-method", + "connection", + "content-length", + "cookie", + "cookie2", + "content-transfer-encoding", + "date", + "expect", + "host", + "keep-alive", + "origin", + "referer", + "te", + "trailer", + "transfer-encoding", + "upgrade", + "user-agent", + "via" + ]; + + // 1-2 + if (_p('readyState') !== XMLHttpRequest.OPENED || _send_flag) { + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + + // 3 + if (/[\u0100-\uffff]/.test(header) || Encode.utf8_encode(header) !== header) { + throw new x.DOMException(x.DOMException.SYNTAX_ERR); + } + + // 4 + /* this step is seemingly bypassed in browsers, probably to allow various unicode characters in header values + if (/[\u0100-\uffff]/.test(value) || Encode.utf8_encode(value) !== value) { + throw new x.DOMException(x.DOMException.SYNTAX_ERR); + }*/ + + header = Basic.trim(header).toLowerCase(); + + // setting of proxy-* and sec-* headers is prohibited by spec + if (!!~Basic.inArray(header, uaHeaders) || /^(proxy\-|sec\-)/.test(header)) { + return false; + } + + // camelize + // browsers lowercase header names (at least for custom ones) + // header = header.replace(/\b\w/g, function($1) { return $1.toUpperCase(); }); + + if (!_headers[header]) { + _headers[header] = value; + } else { + // http://tools.ietf.org/html/rfc2616#section-4.2 (last paragraph) + _headers[header] += ', ' + value; + } + return true; + }, + + /** + Returns all headers from the response, with the exception of those whose field name is Set-Cookie or Set-Cookie2. + + @method getAllResponseHeaders + @return {String} reponse headers or empty string + */ + getAllResponseHeaders: function() { + return _responseHeaders || ''; + }, + + /** + Returns the header field value from the response of which the field name matches header, + unless the field name is Set-Cookie or Set-Cookie2. + + @method getResponseHeader + @param {String} header + @return {String} value(s) for the specified header or null + */ + getResponseHeader: function(header) { + header = header.toLowerCase(); + + if (_error_flag || !!~Basic.inArray(header, ['set-cookie', 'set-cookie2'])) { + return null; + } + + if (_responseHeaders && _responseHeaders !== '') { + // if we didn't parse response headers until now, do it and keep for later + if (!_responseHeadersBag) { + _responseHeadersBag = {}; + Basic.each(_responseHeaders.split(/\r\n/), function(line) { + var pair = line.split(/:\s+/); + if (pair.length === 2) { // last line might be empty, omit + pair[0] = Basic.trim(pair[0]); // just in case + _responseHeadersBag[pair[0].toLowerCase()] = { // simply to retain header name in original form + header: pair[0], + value: Basic.trim(pair[1]) + }; + } + }); + } + if (_responseHeadersBag.hasOwnProperty(header)) { + return _responseHeadersBag[header].header + ': ' + _responseHeadersBag[header].value; + } + } + return null; + }, + + /** + Sets the Content-Type header for the response to mime. + Throws an "InvalidStateError" exception if the state is LOADING or DONE. + Throws a "SyntaxError" exception if mime is not a valid media type. + + @method overrideMimeType + @param String mime Mime type to set + */ + overrideMimeType: function(mime) { + var matches, charset; + + // 1 + if (!!~Basic.inArray(_p('readyState'), [XMLHttpRequest.LOADING, XMLHttpRequest.DONE])) { + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + + // 2 + mime = Basic.trim(mime.toLowerCase()); + + if (/;/.test(mime) && (matches = mime.match(/^([^;]+)(?:;\scharset\=)?(.*)$/))) { + mime = matches[1]; + if (matches[2]) { + charset = matches[2]; + } + } + + if (!Mime.mimes[mime]) { + throw new x.DOMException(x.DOMException.SYNTAX_ERR); + } + + // 3-4 + _finalMime = mime; + _finalCharset = charset; + }, + + /** + Initiates the request. The optional argument provides the request entity body. + The argument is ignored if request method is GET or HEAD. + + Throws an "InvalidStateError" exception if the state is not OPENED or if the send() flag is set. + + @method send + @param {Blob|Document|String|FormData} [data] Request entity body + @param {Object} [options] Set of requirements and pre-requisities for runtime initialization + */ + send: function(data, options) { + if (Basic.typeOf(options) === 'string') { + _options = { ruid: options }; + } else if (!options) { + _options = {}; + } else { + _options = options; + } + + this.convertEventPropsToHandlers(dispatches); + this.upload.convertEventPropsToHandlers(dispatches); + + // 1-2 + if (this.readyState !== XMLHttpRequest.OPENED || _send_flag) { + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + + // 3 + // sending Blob + if (data instanceof Blob) { + _options.ruid = data.ruid; + _mimeType = data.type || 'application/octet-stream'; + } + + // FormData + else if (data instanceof FormData) { + if (data.hasBlob()) { + var blob = data.getBlob(); + _options.ruid = blob.ruid; + _mimeType = blob.type || 'application/octet-stream'; + } + } + + // DOMString + else if (typeof data === 'string') { + _encoding = 'UTF-8'; + _mimeType = 'text/plain;charset=UTF-8'; + + // data should be converted to Unicode and encoded as UTF-8 + data = Encode.utf8_encode(data); + } + + // if withCredentials not set, but requested, set it automatically + if (!this.withCredentials) { + this.withCredentials = (_options.required_caps && _options.required_caps.send_browser_cookies) && !_same_origin_flag; + } + + // 4 - storage mutex + // 5 + _upload_events_flag = (!_sync_flag && this.upload.hasEventListener()); // DSAP + // 6 + _error_flag = false; + // 7 + _upload_complete_flag = !data; + // 8 - Asynchronous steps + if (!_sync_flag) { + // 8.1 + _send_flag = true; + // 8.2 + // this.dispatchEvent('loadstart'); // will be dispatched either by native or runtime xhr + // 8.3 + //if (!_upload_complete_flag) { + // this.upload.dispatchEvent('loadstart'); // will be dispatched either by native or runtime xhr + //} + } + // 8.5 - Return the send() method call, but continue running the steps in this algorithm. + _doXHR.call(this, data); + }, + + /** + Cancels any network activity. + + @method abort + */ + abort: function() { + _error_flag = true; + _sync_flag = false; + + if (!~Basic.inArray(_p('readyState'), [XMLHttpRequest.UNSENT, XMLHttpRequest.OPENED, XMLHttpRequest.DONE])) { + _p('readyState', XMLHttpRequest.DONE); + _send_flag = false; + + if (_xhr) { + _xhr.getRuntime().exec.call(_xhr, 'XMLHttpRequest', 'abort', _upload_complete_flag); + } else { + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + + _upload_complete_flag = true; + } else { + _p('readyState', XMLHttpRequest.UNSENT); + } + }, + + destroy: function() { + if (_xhr) { + if (Basic.typeOf(_xhr.destroy) === 'function') { + _xhr.destroy(); + } + _xhr = null; + } + + this.unbindAll(); + + if (this.upload) { + this.upload.unbindAll(); + this.upload = null; + } + } + }); + + /* this is nice, but maybe too lengthy + + // if supported by JS version, set getters/setters for specific properties + o.defineProperty(this, 'readyState', { + configurable: false, + + get: function() { + return _p('readyState'); + } + }); + + o.defineProperty(this, 'timeout', { + configurable: false, + + get: function() { + return _p('timeout'); + }, + + set: function(value) { + + if (_sync_flag) { + throw new x.DOMException(x.DOMException.INVALID_ACCESS_ERR); + } + + // timeout still should be measured relative to the start time of request + _timeoutset_time = (new Date).getTime(); + + _p('timeout', value); + } + }); + + // the withCredentials attribute has no effect when fetching same-origin resources + o.defineProperty(this, 'withCredentials', { + configurable: false, + + get: function() { + return _p('withCredentials'); + }, + + set: function(value) { + // 1-2 + if (!~o.inArray(_p('readyState'), [XMLHttpRequest.UNSENT, XMLHttpRequest.OPENED]) || _send_flag) { + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + + // 3-4 + if (_anonymous_flag || _sync_flag) { + throw new x.DOMException(x.DOMException.INVALID_ACCESS_ERR); + } + + // 5 + _p('withCredentials', value); + } + }); + + o.defineProperty(this, 'status', { + configurable: false, + + get: function() { + return _p('status'); + } + }); + + o.defineProperty(this, 'statusText', { + configurable: false, + + get: function() { + return _p('statusText'); + } + }); + + o.defineProperty(this, 'responseType', { + configurable: false, + + get: function() { + return _p('responseType'); + }, + + set: function(value) { + // 1 + if (!!~o.inArray(_p('readyState'), [XMLHttpRequest.LOADING, XMLHttpRequest.DONE])) { + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + + // 2 + if (_sync_flag) { + throw new x.DOMException(x.DOMException.INVALID_ACCESS_ERR); + } + + // 3 + _p('responseType', value.toLowerCase()); + } + }); + + o.defineProperty(this, 'responseText', { + configurable: false, + + get: function() { + // 1 + if (!~o.inArray(_p('responseType'), ['', 'text'])) { + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + + // 2-3 + if (_p('readyState') !== XMLHttpRequest.DONE && _p('readyState') !== XMLHttpRequest.LOADING || _error_flag) { + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + + return _p('responseText'); + } + }); + + o.defineProperty(this, 'responseXML', { + configurable: false, + + get: function() { + // 1 + if (!~o.inArray(_p('responseType'), ['', 'document'])) { + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + + // 2-3 + if (_p('readyState') !== XMLHttpRequest.DONE || _error_flag) { + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + + return _p('responseXML'); + } + }); + + o.defineProperty(this, 'response', { + configurable: false, + + get: function() { + if (!!~o.inArray(_p('responseType'), ['', 'text'])) { + if (_p('readyState') !== XMLHttpRequest.DONE && _p('readyState') !== XMLHttpRequest.LOADING || _error_flag) { + return ''; + } + } + + if (_p('readyState') !== XMLHttpRequest.DONE || _error_flag) { + return null; + } + + return _p('response'); + } + }); + + */ + + function _p(prop, value) { + if (!props.hasOwnProperty(prop)) { + return; + } + if (arguments.length === 1) { // get + return Env.can('define_property') ? props[prop] : self[prop]; + } else { // set + if (Env.can('define_property')) { + props[prop] = value; + } else { + self[prop] = value; + } + } + } + + /* + function _toASCII(str, AllowUnassigned, UseSTD3ASCIIRules) { + // TODO: http://tools.ietf.org/html/rfc3490#section-4.1 + return str.toLowerCase(); + } + */ + + + function _doXHR(data) { + var self = this; + + _start_time = new Date().getTime(); + + _xhr = new RuntimeTarget(); + + function loadEnd() { + if (_xhr) { // it could have been destroyed by now + _xhr.destroy(); + _xhr = null; + } + self.dispatchEvent('loadend'); + self = null; + } + + function exec(runtime) { + _xhr.bind('LoadStart', function(e) { + _p('readyState', XMLHttpRequest.LOADING); + self.dispatchEvent('readystatechange'); + + self.dispatchEvent(e); + + if (_upload_events_flag) { + self.upload.dispatchEvent(e); + } + }); + + _xhr.bind('Progress', function(e) { + if (_p('readyState') !== XMLHttpRequest.LOADING) { + _p('readyState', XMLHttpRequest.LOADING); // LoadStart unreliable (in Flash for example) + self.dispatchEvent('readystatechange'); + } + self.dispatchEvent(e); + }); + + _xhr.bind('UploadProgress', function(e) { + if (_upload_events_flag) { + self.upload.dispatchEvent({ + type: 'progress', + lengthComputable: false, + total: e.total, + loaded: e.loaded + }); + } + }); + + _xhr.bind('Load', function(e) { + _p('readyState', XMLHttpRequest.DONE); + _p('status', Number(runtime.exec.call(_xhr, 'XMLHttpRequest', 'getStatus') || 0)); + _p('statusText', httpCode[_p('status')] || ""); + + _p('response', runtime.exec.call(_xhr, 'XMLHttpRequest', 'getResponse', _p('responseType'))); + + if (!!~Basic.inArray(_p('responseType'), ['text', ''])) { + _p('responseText', _p('response')); + } else if (_p('responseType') === 'document') { + _p('responseXML', _p('response')); + } + + _responseHeaders = runtime.exec.call(_xhr, 'XMLHttpRequest', 'getAllResponseHeaders'); + + self.dispatchEvent('readystatechange'); + + if (_p('status') > 0) { // status 0 usually means that server is unreachable + if (_upload_events_flag) { + self.upload.dispatchEvent(e); + } + self.dispatchEvent(e); + } else { + _error_flag = true; + self.dispatchEvent('error'); + } + loadEnd(); + }); + + _xhr.bind('Abort', function(e) { + self.dispatchEvent(e); + loadEnd(); + }); + + _xhr.bind('Error', function(e) { + _error_flag = true; + _p('readyState', XMLHttpRequest.DONE); + self.dispatchEvent('readystatechange'); + _upload_complete_flag = true; + self.dispatchEvent(e); + loadEnd(); + }); + + runtime.exec.call(_xhr, 'XMLHttpRequest', 'send', { + url: _url, + method: _method, + async: _async, + user: _user, + password: _password, + headers: _headers, + mimeType: _mimeType, + encoding: _encoding, + responseType: self.responseType, + withCredentials: self.withCredentials, + options: _options + }, data); + } + + // clarify our requirements + if (typeof(_options.required_caps) === 'string') { + _options.required_caps = Runtime.parseCaps(_options.required_caps); + } + + _options.required_caps = Basic.extend({}, _options.required_caps, { + return_response_type: self.responseType + }); + + if (data instanceof FormData) { + _options.required_caps.send_multipart = true; + } + + if (!_same_origin_flag) { + _options.required_caps.do_cors = true; + } + + + if (_options.ruid) { // we do not need to wait if we can connect directly + exec(_xhr.connectRuntime(_options)); + } else { + _xhr.bind('RuntimeInit', function(e, runtime) { + exec(runtime); + }); + _xhr.bind('RuntimeError', function(e, err) { + self.dispatchEvent('RuntimeError', err); + }); + _xhr.connectRuntime(_options); + } + } + + + function _reset() { + _p('responseText', ""); + _p('responseXML', null); + _p('response', null); + _p('status', 0); + _p('statusText', ""); + _start_time = _timeoutset_time = null; + } + } + + XMLHttpRequest.UNSENT = 0; + XMLHttpRequest.OPENED = 1; + XMLHttpRequest.HEADERS_RECEIVED = 2; + XMLHttpRequest.LOADING = 3; + XMLHttpRequest.DONE = 4; + + XMLHttpRequest.prototype = EventTarget.instance; + + return XMLHttpRequest; +}); + +// Included from: src/javascript/runtime/Transporter.js + +/** + * Transporter.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define("moxie/runtime/Transporter", [ + "moxie/core/utils/Basic", + "moxie/core/utils/Encode", + "moxie/runtime/RuntimeClient", + "moxie/core/EventTarget" +], function(Basic, Encode, RuntimeClient, EventTarget) { + function Transporter() { + var mod, _runtime, _data, _size, _pos, _chunk_size; + + RuntimeClient.call(this); + + Basic.extend(this, { + uid: Basic.guid('uid_'), + + state: Transporter.IDLE, + + result: null, + + transport: function(data, type, options) { + var self = this; + + options = Basic.extend({ + chunk_size: 204798 + }, options); + + // should divide by three, base64 requires this + if ((mod = options.chunk_size % 3)) { + options.chunk_size += 3 - mod; + } + + _chunk_size = options.chunk_size; + + _reset.call(this); + _data = data; + _size = data.length; + + if (Basic.typeOf(options) === 'string' || options.ruid) { + _run.call(self, type, this.connectRuntime(options)); + } else { + // we require this to run only once + var cb = function(e, runtime) { + self.unbind("RuntimeInit", cb); + _run.call(self, type, runtime); + }; + this.bind("RuntimeInit", cb); + this.connectRuntime(options); + } + }, + + abort: function() { + var self = this; + + self.state = Transporter.IDLE; + if (_runtime) { + _runtime.exec.call(self, 'Transporter', 'clear'); + self.trigger("TransportingAborted"); + } + + _reset.call(self); + }, + + + destroy: function() { + this.unbindAll(); + _runtime = null; + this.disconnectRuntime(); + _reset.call(this); + } + }); + + function _reset() { + _size = _pos = 0; + _data = this.result = null; + } + + function _run(type, runtime) { + var self = this; + + _runtime = runtime; + + //self.unbind("RuntimeInit"); + + self.bind("TransportingProgress", function(e) { + _pos = e.loaded; + + if (_pos < _size && Basic.inArray(self.state, [Transporter.IDLE, Transporter.DONE]) === -1) { + _transport.call(self); + } + }, 999); + + self.bind("TransportingComplete", function() { + _pos = _size; + self.state = Transporter.DONE; + _data = null; // clean a bit + self.result = _runtime.exec.call(self, 'Transporter', 'getAsBlob', type || ''); + }, 999); + + self.state = Transporter.BUSY; + self.trigger("TransportingStarted"); + _transport.call(self); + } + + function _transport() { + var self = this, + chunk, + bytesLeft = _size - _pos; + + if (_chunk_size > bytesLeft) { + _chunk_size = bytesLeft; + } + + chunk = Encode.btoa(_data.substr(_pos, _chunk_size)); + _runtime.exec.call(self, 'Transporter', 'receive', chunk, _size); + } + } + + Transporter.IDLE = 0; + Transporter.BUSY = 1; + Transporter.DONE = 2; + + Transporter.prototype = EventTarget.instance; + + return Transporter; +}); + +// Included from: src/javascript/image/Image.js + +/** + * Image.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define("moxie/image/Image", [ + "moxie/core/utils/Basic", + "moxie/core/utils/Dom", + "moxie/core/Exceptions", + "moxie/file/FileReaderSync", + "moxie/xhr/XMLHttpRequest", + "moxie/runtime/Runtime", + "moxie/runtime/RuntimeClient", + "moxie/runtime/Transporter", + "moxie/core/utils/Env", + "moxie/core/EventTarget", + "moxie/file/Blob", + "moxie/file/File", + "moxie/core/utils/Encode" +], function(Basic, Dom, x, FileReaderSync, XMLHttpRequest, Runtime, RuntimeClient, Transporter, Env, EventTarget, Blob, File, Encode) { + /** + Image preloading and manipulation utility. Additionally it provides access to image meta info (Exif, GPS) and raw binary data. + + @class Image + @constructor + @extends EventTarget + */ + var dispatches = [ + 'progress', + + /** + Dispatched when loading is complete. + + @event load + @param {Object} event + */ + 'load', + + 'error', + + /** + Dispatched when resize operation is complete. + + @event resize + @param {Object} event + */ + 'resize', + + /** + Dispatched when visual representation of the image is successfully embedded + into the corresponsing container. + + @event embedded + @param {Object} event + */ + 'embedded' + ]; + + function Image() { + RuntimeClient.call(this); + + Basic.extend(this, { + /** + Unique id of the component + + @property uid + @type {String} + */ + uid: Basic.guid('uid_'), + + /** + Unique id of the connected runtime, if any. + + @property ruid + @type {String} + */ + ruid: null, + + /** + Name of the file, that was used to create an image, if available. If not equals to empty string. + + @property name + @type {String} + @default "" + */ + name: "", + + /** + Size of the image in bytes. Actual value is set only after image is preloaded. + + @property size + @type {Number} + @default 0 + */ + size: 0, + + /** + Width of the image. Actual value is set only after image is preloaded. + + @property width + @type {Number} + @default 0 + */ + width: 0, + + /** + Height of the image. Actual value is set only after image is preloaded. + + @property height + @type {Number} + @default 0 + */ + height: 0, + + /** + Mime type of the image. Currently only image/jpeg and image/png are supported. Actual value is set only after image is preloaded. + + @property type + @type {String} + @default "" + */ + type: "", + + /** + Holds meta info (Exif, GPS). Is populated only for image/jpeg. Actual value is set only after image is preloaded. + + @property meta + @type {Object} + @default {} + */ + meta: {}, + + /** + Alias for load method, that takes another mOxie.Image object as a source (see load). + + @method clone + @param {Image} src Source for the image + @param {Boolean} [exact=false] Whether to activate in-depth clone mode + */ + clone: function() { + this.load.apply(this, arguments); + }, + + /** + Loads image from various sources. Currently the source for new image can be: mOxie.Image, mOxie.Blob/mOxie.File, + native Blob/File, dataUrl or URL. Depending on the type of the source, arguments - differ. When source is URL, + Image will be downloaded from remote destination and loaded in memory. + + @example + var img = new mOxie.Image(); + img.onload = function() { + var blob = img.getAsBlob(); + + var formData = new mOxie.FormData(); + formData.append('file', blob); + + var xhr = new mOxie.XMLHttpRequest(); + xhr.onload = function() { + // upload complete + }; + xhr.open('post', 'upload.php'); + xhr.send(formData); + }; + img.load("http://www.moxiecode.com/images/mox-logo.jpg"); // notice file extension (.jpg) + + + @method load + @param {Image|Blob|File|String} src Source for the image + @param {Boolean|Object} [mixed] + */ + load: function() { + // this is here because to bind properly we need an uid first, which is created above + this.bind('Load Resize', function() { + _updateInfo.call(this); + }, 999); + + this.convertEventPropsToHandlers(dispatches); + + _load.apply(this, arguments); + }, + + /** + Downsizes the image to fit the specified width/height. If crop is supplied, image will be cropped to exact dimensions. + + @method downsize + @param {Number} width Resulting width + @param {Number} [height=width] Resulting height (optional, if not supplied will default to width) + @param {Boolean} [crop=false] Whether to crop the image to exact dimensions + @param {Boolean} [preserveHeaders=true] Whether to preserve meta headers (on JPEGs after resize) + */ + downsize: function(opts) { + var defaults = { + width: this.width, + height: this.height, + crop: false, + preserveHeaders: true + }; + + if (typeof(opts) === 'object') { + opts = Basic.extend(defaults, opts); + } else { + opts = Basic.extend(defaults, { + width: arguments[0], + height: arguments[1], + crop: arguments[2], + preserveHeaders: arguments[3] + }); + } + + try { + if (!this.size) { // only preloaded image objects can be used as source + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + + // no way to reliably intercept the crash due to high resolution, so we simply avoid it + if (this.width > Image.MAX_RESIZE_WIDTH || this.height > Image.MAX_RESIZE_HEIGHT) { + throw new x.ImageError(x.ImageError.MAX_RESOLUTION_ERR); + } + + this.getRuntime().exec.call(this, 'Image', 'downsize', opts.width, opts.height, opts.crop, opts.preserveHeaders); + } catch(ex) { + // for now simply trigger error event + this.trigger('error', ex.code); + } + }, + + /** + Alias for downsize(width, height, true). (see downsize) + + @method crop + @param {Number} width Resulting width + @param {Number} [height=width] Resulting height (optional, if not supplied will default to width) + @param {Boolean} [preserveHeaders=true] Whether to preserve meta headers (on JPEGs after resize) + */ + crop: function(width, height, preserveHeaders) { + this.downsize(width, height, true, preserveHeaders); + }, + + getAsCanvas: function() { + if (!Env.can('create_canvas')) { + throw new x.RuntimeError(x.RuntimeError.NOT_SUPPORTED_ERR); + } + + var runtime = this.connectRuntime(this.ruid); + return runtime.exec.call(this, 'Image', 'getAsCanvas'); + }, + + /** + Retrieves image in it's current state as mOxie.Blob object. Cannot be run on empty or image in progress (throws + DOMException.INVALID_STATE_ERR). + + @method getAsBlob + @param {String} [type="image/jpeg"] Mime type of resulting blob. Can either be image/jpeg or image/png + @param {Number} [quality=90] Applicable only together with mime type image/jpeg + @return {Blob} Image as Blob + */ + getAsBlob: function(type, quality) { + if (!this.size) { + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + + if (!type) { + type = 'image/jpeg'; + } + + if (type === 'image/jpeg' && !quality) { + quality = 90; + } + + return this.getRuntime().exec.call(this, 'Image', 'getAsBlob', type, quality); + }, + + /** + Retrieves image in it's current state as dataURL string. Cannot be run on empty or image in progress (throws + DOMException.INVALID_STATE_ERR). + + @method getAsDataURL + @param {String} [type="image/jpeg"] Mime type of resulting blob. Can either be image/jpeg or image/png + @param {Number} [quality=90] Applicable only together with mime type image/jpeg + @return {String} Image as dataURL string + */ + getAsDataURL: function(type, quality) { + if (!this.size) { + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + return this.getRuntime().exec.call(this, 'Image', 'getAsDataURL', type, quality); + }, + + /** + Retrieves image in it's current state as binary string. Cannot be run on empty or image in progress (throws + DOMException.INVALID_STATE_ERR). + + @method getAsBinaryString + @param {String} [type="image/jpeg"] Mime type of resulting blob. Can either be image/jpeg or image/png + @param {Number} [quality=90] Applicable only together with mime type image/jpeg + @return {String} Image as binary string + */ + getAsBinaryString: function(type, quality) { + var dataUrl = this.getAsDataURL(type, quality); + return Encode.atob(dataUrl.substring(dataUrl.indexOf('base64,') + 7)); + }, + + /** + Embeds a visual representation of the image into the specified node. Depending on the runtime, + it might be a canvas, an img node or a thrid party shim object (Flash or SilverLight - very rare, + can be used in legacy browsers that do not have canvas or proper dataURI support). + + @method embed + @param {DOMElement} el DOM element to insert the image object into + @param {Object} [options] + @param {Number} [options.width] The width of an embed (defaults to the image width) + @param {Number} [options.height] The height of an embed (defaults to the image height) + @param {String} [type="image/jpeg"] Mime type + @param {Number} [quality=90] Quality of an embed, if mime type is image/jpeg + @param {Boolean} [crop=false] Whether to crop an embed to the specified dimensions + */ + embed: function(el) { + var self = this + , imgCopy + , type, quality, crop + , options = arguments[1] || {} + , width = this.width + , height = this.height + , runtime // this has to be outside of all the closures to contain proper runtime + ; + + function onResize() { + // if possible, embed a canvas element directly + if (Env.can('create_canvas')) { + var canvas = imgCopy.getAsCanvas(); + if (canvas) { + el.appendChild(canvas); + canvas = null; + imgCopy.destroy(); + self.trigger('embedded'); + return; + } + } + + var dataUrl = imgCopy.getAsDataURL(type, quality); + if (!dataUrl) { + throw new x.ImageError(x.ImageError.WRONG_FORMAT); + } + + if (Env.can('use_data_uri_of', dataUrl.length)) { + el.innerHTML = ''; + imgCopy.destroy(); + self.trigger('embedded'); + } else { + var tr = new Transporter(); + + tr.bind("TransportingComplete", function() { + runtime = self.connectRuntime(this.result.ruid); + + self.bind("Embedded", function() { + // position and size properly + Basic.extend(runtime.getShimContainer().style, { + //position: 'relative', + top: '0px', + left: '0px', + width: imgCopy.width + 'px', + height: imgCopy.height + 'px' + }); + + // some shims (Flash/SilverLight) reinitialize, if parent element is hidden, reordered or it's + // position type changes (in Gecko), but since we basically need this only in IEs 6/7 and + // sometimes 8 and they do not have this problem, we can comment this for now + /*tr.bind("RuntimeInit", function(e, runtime) { + tr.destroy(); + runtime.destroy(); + onResize.call(self); // re-feed our image data + });*/ + + runtime = null; + }, 999); + + runtime.exec.call(self, "ImageView", "display", this.result.uid, width, height); + imgCopy.destroy(); + }); + + tr.transport(Encode.atob(dataUrl.substring(dataUrl.indexOf('base64,') + 7)), type, Basic.extend({}, options, { + required_caps: { + display_media: true + }, + runtime_order: 'flash,silverlight', + container: el + })); + } + } + + try { + if (!(el = Dom.get(el))) { + throw new x.DOMException(x.DOMException.INVALID_NODE_TYPE_ERR); + } + + if (!this.size) { // only preloaded image objects can be used as source + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + + if (this.width > Image.MAX_RESIZE_WIDTH || this.height > Image.MAX_RESIZE_HEIGHT) { + throw new x.ImageError(x.ImageError.MAX_RESOLUTION_ERR); + } + + type = options.type || this.type || 'image/jpeg'; + quality = options.quality || 90; + crop = Basic.typeOf(options.crop) !== 'undefined' ? options.crop : false; + + // figure out dimensions for the thumb + if (options.width) { + width = options.width; + height = options.height || width; + } else { + // if container element has measurable dimensions, use them + var dimensions = Dom.getSize(el); + if (dimensions.w && dimensions.h) { // both should be > 0 + width = dimensions.w; + height = dimensions.h; + } + } + + imgCopy = new Image(); + + imgCopy.bind("Resize", function() { + onResize.call(self); + }); + + imgCopy.bind("Load", function() { + imgCopy.downsize(width, height, crop, false); + }); + + imgCopy.clone(this, false); + + return imgCopy; + } catch(ex) { + // for now simply trigger error event + this.trigger('error', ex.code); + } + }, + + /** + Properly destroys the image and frees resources in use. If any. Recommended way to dispose mOxie.Image object. + + @method destroy + */ + destroy: function() { + if (this.ruid) { + this.getRuntime().exec.call(this, 'Image', 'destroy'); + this.disconnectRuntime(); + } + this.unbindAll(); + } + }); + + + function _updateInfo(info) { + if (!info) { + info = this.getRuntime().exec.call(this, 'Image', 'getInfo'); + } + + this.size = info.size; + this.width = info.width; + this.height = info.height; + this.type = info.type; + this.meta = info.meta; + + // update file name, only if empty + if (this.name === '') { + this.name = info.name; + } + } + + + function _load(src) { + var srcType = Basic.typeOf(src); + + try { + // if source is Image + if (src instanceof Image) { + if (!src.size) { // only preloaded image objects can be used as source + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + _loadFromImage.apply(this, arguments); + } + // if source is o.Blob/o.File + else if (src instanceof Blob) { + if (!~Basic.inArray(src.type, ['image/jpeg', 'image/png'])) { + throw new x.ImageError(x.ImageError.WRONG_FORMAT); + } + _loadFromBlob.apply(this, arguments); + } + // if native blob/file + else if (Basic.inArray(srcType, ['blob', 'file']) !== -1) { + _load.call(this, new File(null, src), arguments[1]); + } + // if String + else if (srcType === 'string') { + // if dataUrl String + if (/^data:[^;]*;base64,/.test(src)) { + _load.call(this, new Blob(null, { data: src }), arguments[1]); + } + // else assume Url, either relative or absolute + else { + _loadFromUrl.apply(this, arguments); + } + } + // if source seems to be an img node + else if (srcType === 'node' && src.nodeName.toLowerCase() === 'img') { + _load.call(this, src.src, arguments[1]); + } + else { + throw new x.DOMException(x.DOMException.TYPE_MISMATCH_ERR); + } + } catch(ex) { + // for now simply trigger error event + this.trigger('error', ex.code); + } + } + + + function _loadFromImage(img, exact) { + var runtime = this.connectRuntime(img.ruid); + this.ruid = runtime.uid; + runtime.exec.call(this, 'Image', 'loadFromImage', img, (Basic.typeOf(exact) === 'undefined' ? true : exact)); + } + + + function _loadFromBlob(blob, options) { + var self = this; + + self.name = blob.name || ''; + + function exec(runtime) { + self.ruid = runtime.uid; + runtime.exec.call(self, 'Image', 'loadFromBlob', blob); + } + + if (blob.isDetached()) { + this.bind('RuntimeInit', function(e, runtime) { + exec(runtime); + }); + + // convert to object representation + if (options && typeof(options.required_caps) === 'string') { + options.required_caps = Runtime.parseCaps(options.required_caps); + } + + this.connectRuntime(Basic.extend({ + required_caps: { + access_image_binary: true, + resize_image: true + } + }, options)); + } else { + exec(this.connectRuntime(blob.ruid)); + } + } + + + function _loadFromUrl(url, options) { + var self = this, xhr; + + xhr = new XMLHttpRequest(); + + xhr.open('get', url); + xhr.responseType = 'blob'; + + xhr.onprogress = function(e) { + self.trigger(e); + }; + + xhr.onload = function() { + _loadFromBlob.call(self, xhr.response, true); + }; + + xhr.onerror = function(e) { + self.trigger(e); + }; + + xhr.onloadend = function() { + xhr.destroy(); + }; + + xhr.bind('RuntimeError', function(e, err) { + self.trigger('RuntimeError', err); + }); + + xhr.send(null, options); + } + } + + // virtual world will crash on you if image has a resolution higher than this: + Image.MAX_RESIZE_WIDTH = 6500; + Image.MAX_RESIZE_HEIGHT = 6500; + + Image.prototype = EventTarget.instance; + + return Image; +}); + +// Included from: src/javascript/runtime/html5/Runtime.js + +/** + * Runtime.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/*global File:true */ + +/** +Defines constructor for HTML5 runtime. + +@class moxie/runtime/html5/Runtime +@private +*/ +define("moxie/runtime/html5/Runtime", [ + "moxie/core/utils/Basic", + "moxie/core/Exceptions", + "moxie/runtime/Runtime", + "moxie/core/utils/Env" +], function(Basic, x, Runtime, Env) { + + var type = "html5", extensions = {}; + + function Html5Runtime(options) { + var I = this + , Test = Runtime.capTest + , True = Runtime.capTrue + ; + + var caps = Basic.extend({ + access_binary: Test(window.FileReader || window.File && window.File.getAsDataURL), + access_image_binary: function() { + return I.can('access_binary') && !!extensions.Image; + }, + display_media: Test(Env.can('create_canvas') || Env.can('use_data_uri_over32kb')), + do_cors: Test(window.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest()), + drag_and_drop: Test(function() { + // this comes directly from Modernizr: http://www.modernizr.com/ + var div = document.createElement('div'); + // IE has support for drag and drop since version 5, but doesn't support dropping files from desktop + return (('draggable' in div) || ('ondragstart' in div && 'ondrop' in div)) && (Env.browser !== 'IE' || Env.version > 9); + }()), + filter_by_extension: Test(function() { // if you know how to feature-detect this, please suggest + return (Env.browser === 'Chrome' && Env.version >= 28) || (Env.browser === 'IE' && Env.version >= 10); + }()), + return_response_headers: True, + return_response_type: function(responseType) { + if (responseType === 'json' && !!window.JSON) { // we can fake this one even if it's not supported + return true; + } + return Env.can('return_response_type', responseType); + }, + return_status_code: True, + report_upload_progress: Test(window.XMLHttpRequest && new XMLHttpRequest().upload), + resize_image: function() { + return I.can('access_binary') && Env.can('create_canvas'); + }, + select_file: function() { + return Env.can('use_fileinput') && window.File; + }, + select_folder: function() { + return I.can('select_file') && Env.browser === 'Chrome' && Env.version >= 21; + }, + select_multiple: function() { + // it is buggy on Safari Windows and iOS + return I.can('select_file') && + !(Env.browser === 'Safari' && Env.os === 'Windows') && + !(Env.os === 'iOS' && Env.verComp(Env.osVersion, "7.0.4", '<')); + }, + send_binary_string: Test(window.XMLHttpRequest && (new XMLHttpRequest().sendAsBinary || (window.Uint8Array && window.ArrayBuffer))), + send_custom_headers: Test(window.XMLHttpRequest), + send_multipart: function() { + return !!(window.XMLHttpRequest && new XMLHttpRequest().upload && window.FormData) || I.can('send_binary_string'); + }, + slice_blob: Test(window.File && (File.prototype.mozSlice || File.prototype.webkitSlice || File.prototype.slice)), + stream_upload: function(){ + return I.can('slice_blob') && I.can('send_multipart'); + }, + summon_file_dialog: Test(function() { // yeah... some dirty sniffing here... + return (Env.browser === 'Firefox' && Env.version >= 4) || + (Env.browser === 'Opera' && Env.version >= 12) || + (Env.browser === 'IE' && Env.version >= 10) || + !!~Basic.inArray(Env.browser, ['Chrome', 'Safari']); + }()), + upload_filesize: True + }, + arguments[2] + ); + + Runtime.call(this, options, (arguments[1] || type), caps); + + + Basic.extend(this, { + + init : function() { + this.trigger("Init"); + }, + + destroy: (function(destroy) { // extend default destroy method + return function() { + destroy.call(I); + destroy = I = null; + }; + }(this.destroy)) + }); + + Basic.extend(this.getShim(), extensions); + } + + Runtime.addConstructor(type, Html5Runtime); + + return extensions; +}); + +// Included from: src/javascript/runtime/html5/file/Blob.js + +/** + * Blob.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html5/file/Blob +@private +*/ +define("moxie/runtime/html5/file/Blob", [ + "moxie/runtime/html5/Runtime", + "moxie/file/Blob" +], function(extensions, Blob) { + + function HTML5Blob() { + function w3cBlobSlice(blob, start, end) { + var blobSlice; + + if (window.File.prototype.slice) { + try { + blob.slice(); // depricated version will throw WRONG_ARGUMENTS_ERR exception + return blob.slice(start, end); + } catch (e) { + // depricated slice method + return blob.slice(start, end - start); + } + // slice method got prefixed: https://bugzilla.mozilla.org/show_bug.cgi?id=649672 + } else if ((blobSlice = window.File.prototype.webkitSlice || window.File.prototype.mozSlice)) { + return blobSlice.call(blob, start, end); + } else { + return null; // or throw some exception + } + } + + this.slice = function() { + return new Blob(this.getRuntime().uid, w3cBlobSlice.apply(this, arguments)); + }; + } + + return (extensions.Blob = HTML5Blob); +}); + +// Included from: src/javascript/core/utils/Events.js + +/** + * Events.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define('moxie/core/utils/Events', [ + 'moxie/core/utils/Basic' +], function(Basic) { + var eventhash = {}, uid = 'moxie_' + Basic.guid(); + + // IE W3C like event funcs + function preventDefault() { + this.returnValue = false; + } + + function stopPropagation() { + this.cancelBubble = true; + } + + /** + Adds an event handler to the specified object and store reference to the handler + in objects internal Plupload registry (@see removeEvent). + + @method addEvent + @for Utils + @static + @param {Object} obj DOM element like object to add handler to. + @param {String} name Name to add event listener to. + @param {Function} callback Function to call when event occurs. + @param {String} [key] that might be used to add specifity to the event record. + */ + var addEvent = function(obj, name, callback, key) { + var func, events; + + name = name.toLowerCase(); + + // Add event listener + if (obj.addEventListener) { + func = callback; + + obj.addEventListener(name, func, false); + } else if (obj.attachEvent) { + func = function() { + var evt = window.event; + + if (!evt.target) { + evt.target = evt.srcElement; + } + + evt.preventDefault = preventDefault; + evt.stopPropagation = stopPropagation; + + callback(evt); + }; + + obj.attachEvent('on' + name, func); + } + + // Log event handler to objects internal mOxie registry + if (!obj[uid]) { + obj[uid] = Basic.guid(); + } + + if (!eventhash.hasOwnProperty(obj[uid])) { + eventhash[obj[uid]] = {}; + } + + events = eventhash[obj[uid]]; + + if (!events.hasOwnProperty(name)) { + events[name] = []; + } + + events[name].push({ + func: func, + orig: callback, // store original callback for IE + key: key + }); + }; + + + /** + Remove event handler from the specified object. If third argument (callback) + is not specified remove all events with the specified name. + + @method removeEvent + @static + @param {Object} obj DOM element to remove event listener(s) from. + @param {String} name Name of event listener to remove. + @param {Function|String} [callback] might be a callback or unique key to match. + */ + var removeEvent = function(obj, name, callback) { + var type, undef; + + name = name.toLowerCase(); + + if (obj[uid] && eventhash[obj[uid]] && eventhash[obj[uid]][name]) { + type = eventhash[obj[uid]][name]; + } else { + return; + } + + for (var i = type.length - 1; i >= 0; i--) { + // undefined or not, key should match + if (type[i].orig === callback || type[i].key === callback) { + if (obj.removeEventListener) { + obj.removeEventListener(name, type[i].func, false); + } else if (obj.detachEvent) { + obj.detachEvent('on'+name, type[i].func); + } + + type[i].orig = null; + type[i].func = null; + type.splice(i, 1); + + // If callback was passed we are done here, otherwise proceed + if (callback !== undef) { + break; + } + } + } + + // If event array got empty, remove it + if (!type.length) { + delete eventhash[obj[uid]][name]; + } + + // If mOxie registry has become empty, remove it + if (Basic.isEmptyObj(eventhash[obj[uid]])) { + delete eventhash[obj[uid]]; + + // IE doesn't let you remove DOM object property with - delete + try { + delete obj[uid]; + } catch(e) { + obj[uid] = undef; + } + } + }; + + + /** + Remove all kind of events from the specified object + + @method removeAllEvents + @static + @param {Object} obj DOM element to remove event listeners from. + @param {String} [key] unique key to match, when removing events. + */ + var removeAllEvents = function(obj, key) { + if (!obj || !obj[uid]) { + return; + } + + Basic.each(eventhash[obj[uid]], function(events, name) { + removeEvent(obj, name, key); + }); + }; + + return { + addEvent: addEvent, + removeEvent: removeEvent, + removeAllEvents: removeAllEvents + }; +}); + +// Included from: src/javascript/runtime/html5/file/FileInput.js + +/** + * FileInput.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html5/file/FileInput +@private +*/ +define("moxie/runtime/html5/file/FileInput", [ + "moxie/runtime/html5/Runtime", + "moxie/core/utils/Basic", + "moxie/core/utils/Dom", + "moxie/core/utils/Events", + "moxie/core/utils/Mime", + "moxie/core/utils/Env" +], function(extensions, Basic, Dom, Events, Mime, Env) { + + function FileInput() { + var _files = [], _options; + + Basic.extend(this, { + init: function(options) { + var comp = this, I = comp.getRuntime(), input, shimContainer, mimes, browseButton, zIndex, top; + + _options = options; + _files = []; + + // figure out accept string + mimes = _options.accept.mimes || Mime.extList2mimes(_options.accept, I.can('filter_by_extension')); + + shimContainer = I.getShimContainer(); + + shimContainer.innerHTML = ''; + + input = Dom.get(I.uid); + + // prepare file input to be placed underneath the browse_button element + Basic.extend(input.style, { + position: 'absolute', + top: 0, + left: 0, + width: '100%', + height: '100%' + }); + + + browseButton = Dom.get(_options.browse_button); + + // Route click event to the input[type=file] element for browsers that support such behavior + if (I.can('summon_file_dialog')) { + if (Dom.getStyle(browseButton, 'position') === 'static') { + browseButton.style.position = 'relative'; + } + + zIndex = parseInt(Dom.getStyle(browseButton, 'z-index'), 10) || 1; + + browseButton.style.zIndex = zIndex; + shimContainer.style.zIndex = zIndex - 1; + + Events.addEvent(browseButton, 'click', function(e) { + var input = Dom.get(I.uid); + if (input && !input.disabled) { // for some reason FF (up to 8.0.1 so far) lets to click disabled input[type=file] + input.click(); + } + e.preventDefault(); + }, comp.uid); + } + + /* Since we have to place input[type=file] on top of the browse_button for some browsers, + browse_button loses interactivity, so we restore it here */ + top = I.can('summon_file_dialog') ? browseButton : shimContainer; + + Events.addEvent(top, 'mouseover', function() { + comp.trigger('mouseenter'); + }, comp.uid); + + Events.addEvent(top, 'mouseout', function() { + comp.trigger('mouseleave'); + }, comp.uid); + + Events.addEvent(top, 'mousedown', function() { + comp.trigger('mousedown'); + }, comp.uid); + + Events.addEvent(Dom.get(_options.container), 'mouseup', function() { + comp.trigger('mouseup'); + }, comp.uid); + + + input.onchange = function onChange() { // there should be only one handler for this + _files = []; + + if (_options.directory) { + // folders are represented by dots, filter them out (Chrome 11+) + Basic.each(this.files, function(file) { + if (file.name !== ".") { // if it doesn't looks like a folder + _files.push(file); + } + }); + } else { + _files = [].slice.call(this.files); + } + + // clearing the value enables the user to select the same file again if they want to + if (Env.browser !== 'IE' && Env.browser !== 'IEMobile') { + this.value = ''; + } else { + // in IE input[type="file"] is read-only so the only way to reset it is to re-insert it + var clone = this.cloneNode(true); + this.parentNode.replaceChild(clone, this); + clone.onchange = onChange; + } + comp.trigger('change'); + }; + + // ready event is perfectly asynchronous + comp.trigger({ + type: 'ready', + async: true + }); + + shimContainer = null; + }, + + getFiles: function() { + return _files; + }, + + disable: function(state) { + var I = this.getRuntime(), input; + + if ((input = Dom.get(I.uid))) { + input.disabled = !!state; + } + }, + + destroy: function() { + var I = this.getRuntime() + , shim = I.getShim() + , shimContainer = I.getShimContainer() + ; + + Events.removeAllEvents(shimContainer, this.uid); + Events.removeAllEvents(_options && Dom.get(_options.container), this.uid); + Events.removeAllEvents(_options && Dom.get(_options.browse_button), this.uid); + + if (shimContainer) { + shimContainer.innerHTML = ''; + } + + shim.removeInstance(this.uid); + + _files = _options = shimContainer = shim = null; + } + }); + } + + return (extensions.FileInput = FileInput); +}); + +// Included from: src/javascript/runtime/html5/file/FileDrop.js + +/** + * FileDrop.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html5/file/FileDrop +@private +*/ +define("moxie/runtime/html5/file/FileDrop", [ + "moxie/runtime/html5/Runtime", + "moxie/core/utils/Basic", + "moxie/core/utils/Dom", + "moxie/core/utils/Events", + "moxie/core/utils/Mime" +], function(extensions, Basic, Dom, Events, Mime) { + + function FileDrop() { + var _files = [], _allowedExts = [], _options; + + Basic.extend(this, { + init: function(options) { + var comp = this, dropZone; + + _options = options; + _allowedExts = _extractExts(_options.accept); + dropZone = _options.container; + + Events.addEvent(dropZone, 'dragover', function(e) { + if (!_hasFiles(e)) { + return; + } + e.preventDefault(); + e.dataTransfer.dropEffect = 'copy'; + }, comp.uid); + + Events.addEvent(dropZone, 'drop', function(e) { + if (!_hasFiles(e)) { + return; + } + e.preventDefault(); + + _files = []; + + // Chrome 21+ accepts folders via Drag'n'Drop + if (e.dataTransfer.items && e.dataTransfer.items[0].webkitGetAsEntry) { + _readItems(e.dataTransfer.items, function() { + comp.trigger("drop"); + }); + } else { + Basic.each(e.dataTransfer.files, function(file) { + if (_isAcceptable(file)) { + _files.push(file); + } + }); + comp.trigger("drop"); + } + }, comp.uid); + + Events.addEvent(dropZone, 'dragenter', function(e) { + comp.trigger("dragenter"); + }, comp.uid); + + Events.addEvent(dropZone, 'dragleave', function(e) { + comp.trigger("dragleave"); + }, comp.uid); + }, + + getFiles: function() { + return _files; + }, + + destroy: function() { + Events.removeAllEvents(_options && Dom.get(_options.container), this.uid); + _files = _allowedExts = _options = null; + } + }); + + + function _hasFiles(e) { + if (!e.dataTransfer || !e.dataTransfer.types) { // e.dataTransfer.files is not available in Gecko during dragover + return false; + } + + var types = Basic.toArray(e.dataTransfer.types || []); + + return Basic.inArray("Files", types) !== -1 || + Basic.inArray("public.file-url", types) !== -1 || // Safari < 5 + Basic.inArray("application/x-moz-file", types) !== -1 // Gecko < 1.9.2 (< Firefox 3.6) + ; + } + + + function _extractExts(accept) { + var exts = []; + for (var i = 0; i < accept.length; i++) { + [].push.apply(exts, accept[i].extensions.split(/\s*,\s*/)); + } + return Basic.inArray('*', exts) === -1 ? exts : []; + } + + + function _isAcceptable(file) { + if (!_allowedExts.length) { + return true; + } + var ext = Mime.getFileExtension(file.name); + return !ext || Basic.inArray(ext, _allowedExts) !== -1; + } + + + function _readItems(items, cb) { + var entries = []; + Basic.each(items, function(item) { + var entry = item.webkitGetAsEntry(); + // Address #998 (https://code.google.com/p/chromium/issues/detail?id=332579) + if (entry) { + // file() fails on OSX when the filename contains a special character (e.g. umlaut): see #61 + if (entry.isFile) { + var file = item.getAsFile(); + if (_isAcceptable(file)) { + _files.push(file); + } + } else { + entries.push(entry); + } + } + }); + + if (entries.length) { + _readEntries(entries, cb); + } else { + cb(); + } + } + + + function _readEntries(entries, cb) { + var queue = []; + Basic.each(entries, function(entry) { + queue.push(function(cbcb) { + _readEntry(entry, cbcb); + }); + }); + Basic.inSeries(queue, function() { + cb(); + }); + } + + + function _readEntry(entry, cb) { + if (entry.isFile) { + entry.file(function(file) { + if (_isAcceptable(file)) { + _files.push(file); + } + cb(); + }, function() { + // fire an error event maybe + cb(); + }); + } else if (entry.isDirectory) { + _readDirEntry(entry, cb); + } else { + cb(); // not file, not directory? what then?.. + } + } + + + function _readDirEntry(dirEntry, cb) { + var entries = [], dirReader = dirEntry.createReader(); + + // keep quering recursively till no more entries + function getEntries(cbcb) { + dirReader.readEntries(function(moreEntries) { + if (moreEntries.length) { + [].push.apply(entries, moreEntries); + getEntries(cbcb); + } else { + cbcb(); + } + }, cbcb); + } + + // ...and you thought FileReader was crazy... + getEntries(function() { + _readEntries(entries, cb); + }); + } + } + + return (extensions.FileDrop = FileDrop); +}); + +// Included from: src/javascript/runtime/html5/file/FileReader.js + +/** + * FileReader.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html5/file/FileReader +@private +*/ +define("moxie/runtime/html5/file/FileReader", [ + "moxie/runtime/html5/Runtime", + "moxie/core/utils/Encode", + "moxie/core/utils/Basic" +], function(extensions, Encode, Basic) { + + function FileReader() { + var _fr, _convertToBinary = false; + + Basic.extend(this, { + + read: function(op, blob) { + var target = this; + + _fr = new window.FileReader(); + + _fr.addEventListener('progress', function(e) { + target.trigger(e); + }); + + _fr.addEventListener('load', function(e) { + target.trigger(e); + }); + + _fr.addEventListener('error', function(e) { + target.trigger(e, _fr.error); + }); + + _fr.addEventListener('loadend', function() { + _fr = null; + }); + + if (Basic.typeOf(_fr[op]) === 'function') { + _convertToBinary = false; + _fr[op](blob.getSource()); + } else if (op === 'readAsBinaryString') { // readAsBinaryString is depricated in general and never existed in IE10+ + _convertToBinary = true; + _fr.readAsDataURL(blob.getSource()); + } + }, + + getResult: function() { + return _fr && _fr.result ? (_convertToBinary ? _toBinary(_fr.result) : _fr.result) : null; + }, + + abort: function() { + if (_fr) { + _fr.abort(); + } + }, + + destroy: function() { + _fr = null; + } + }); + + function _toBinary(str) { + return Encode.atob(str.substring(str.indexOf('base64,') + 7)); + } + } + + return (extensions.FileReader = FileReader); +}); + +// Included from: src/javascript/runtime/html5/xhr/XMLHttpRequest.js + +/** + * XMLHttpRequest.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/*global ActiveXObject:true */ + +/** +@class moxie/runtime/html5/xhr/XMLHttpRequest +@private +*/ +define("moxie/runtime/html5/xhr/XMLHttpRequest", [ + "moxie/runtime/html5/Runtime", + "moxie/core/utils/Basic", + "moxie/core/utils/Mime", + "moxie/core/utils/Url", + "moxie/file/File", + "moxie/file/Blob", + "moxie/xhr/FormData", + "moxie/core/Exceptions", + "moxie/core/utils/Env" +], function(extensions, Basic, Mime, Url, File, Blob, FormData, x, Env) { + + function XMLHttpRequest() { + var self = this + , _xhr + , _filename + ; + + Basic.extend(this, { + send: function(meta, data) { + var target = this + , isGecko2_5_6 = (Env.browser === 'Mozilla' && Env.version >= 4 && Env.version < 7) + , isAndroidBrowser = Env.browser === 'Android Browser' + , mustSendAsBinary = false + ; + + // extract file name + _filename = meta.url.replace(/^.+?\/([\w\-\.]+)$/, '$1').toLowerCase(); + + _xhr = _getNativeXHR(); + _xhr.open(meta.method, meta.url, meta.async, meta.user, meta.password); + + + // prepare data to be sent + if (data instanceof Blob) { + if (data.isDetached()) { + mustSendAsBinary = true; + } + data = data.getSource(); + } else if (data instanceof FormData) { + + if (data.hasBlob()) { + if (data.getBlob().isDetached()) { + data = _prepareMultipart.call(target, data); // _xhr must be instantiated and be in OPENED state + mustSendAsBinary = true; + } else if ((isGecko2_5_6 || isAndroidBrowser) && Basic.typeOf(data.getBlob().getSource()) === 'blob' && window.FileReader) { + // Gecko 2/5/6 can't send blob in FormData: https://bugzilla.mozilla.org/show_bug.cgi?id=649150 + // Android browsers (default one and Dolphin) seem to have the same issue, see: #613 + _preloadAndSend.call(target, meta, data); + return; // _preloadAndSend will reinvoke send() with transmutated FormData =%D + } + } + + // transfer fields to real FormData + if (data instanceof FormData) { // if still a FormData, e.g. not mangled by _prepareMultipart() + var fd = new window.FormData(); + data.each(function(value, name) { + if (value instanceof Blob) { + fd.append(name, value.getSource()); + } else { + fd.append(name, value); + } + }); + data = fd; + } + } + + + // if XHR L2 + if (_xhr.upload) { + if (meta.withCredentials) { + _xhr.withCredentials = true; + } + + _xhr.addEventListener('load', function(e) { + target.trigger(e); + }); + + _xhr.addEventListener('error', function(e) { + target.trigger(e); + }); + + // additionally listen to progress events + _xhr.addEventListener('progress', function(e) { + target.trigger(e); + }); + + _xhr.upload.addEventListener('progress', function(e) { + target.trigger({ + type: 'UploadProgress', + loaded: e.loaded, + total: e.total + }); + }); + // ... otherwise simulate XHR L2 + } else { + _xhr.onreadystatechange = function onReadyStateChange() { + + // fake Level 2 events + switch (_xhr.readyState) { + + case 1: // XMLHttpRequest.OPENED + // readystatechanged is fired twice for OPENED state (in IE and Mozilla) - neu + break; + + // looks like HEADERS_RECEIVED (state 2) is not reported in Opera (or it's old versions) - neu + case 2: // XMLHttpRequest.HEADERS_RECEIVED + break; + + case 3: // XMLHttpRequest.LOADING + // try to fire progress event for not XHR L2 + var total, loaded; + + try { + if (Url.hasSameOrigin(meta.url)) { // Content-Length not accessible for cross-domain on some browsers + total = _xhr.getResponseHeader('Content-Length') || 0; // old Safari throws an exception here + } + + if (_xhr.responseText) { // responseText was introduced in IE7 + loaded = _xhr.responseText.length; + } + } catch(ex) { + total = loaded = 0; + } + + target.trigger({ + type: 'progress', + lengthComputable: !!total, + total: parseInt(total, 10), + loaded: loaded + }); + break; + + case 4: // XMLHttpRequest.DONE + // release readystatechange handler (mostly for IE) + _xhr.onreadystatechange = function() {}; + + // usually status 0 is returned when server is unreachable, but FF also fails to status 0 for 408 timeout + if (_xhr.status === 0) { + target.trigger('error'); + } else { + target.trigger('load'); + } + break; + } + }; + } + + + // set request headers + if (!Basic.isEmptyObj(meta.headers)) { + Basic.each(meta.headers, function(value, header) { + _xhr.setRequestHeader(header, value); + }); + } + + // request response type + if ("" !== meta.responseType && 'responseType' in _xhr) { + if ('json' === meta.responseType && !Env.can('return_response_type', 'json')) { // we can fake this one + _xhr.responseType = 'text'; + } else { + _xhr.responseType = meta.responseType; + } + } + + // send ... + if (!mustSendAsBinary) { + _xhr.send(data); + } else { + if (_xhr.sendAsBinary) { // Gecko + _xhr.sendAsBinary(data); + } else { // other browsers having support for typed arrays + (function() { + // mimic Gecko's sendAsBinary + var ui8a = new Uint8Array(data.length); + for (var i = 0; i < data.length; i++) { + ui8a[i] = (data.charCodeAt(i) & 0xff); + } + _xhr.send(ui8a.buffer); + }()); + } + } + + target.trigger('loadstart'); + }, + + getStatus: function() { + // according to W3C spec it should return 0 for readyState < 3, but instead it throws an exception + try { + if (_xhr) { + return _xhr.status; + } + } catch(ex) {} + return 0; + }, + + getResponse: function(responseType) { + var I = this.getRuntime(); + + try { + switch (responseType) { + case 'blob': + var file = new File(I.uid, _xhr.response); + + // try to extract file name from content-disposition if possible (might be - not, if CORS for example) + var disposition = _xhr.getResponseHeader('Content-Disposition'); + if (disposition) { + // extract filename from response header if available + var match = disposition.match(/filename=([\'\"'])([^\1]+)\1/); + if (match) { + _filename = match[2]; + } + } + file.name = _filename; + + // pre-webkit Opera doesn't set type property on the blob response + if (!file.type) { + file.type = Mime.getFileMime(_filename); + } + return file; + + case 'json': + if (!Env.can('return_response_type', 'json')) { + return _xhr.status === 200 && !!window.JSON ? JSON.parse(_xhr.responseText) : null; + } + return _xhr.response; + + case 'document': + return _getDocument(_xhr); + + default: + return _xhr.responseText !== '' ? _xhr.responseText : null; // against the specs, but for consistency across the runtimes + } + } catch(ex) { + return null; + } + }, + + getAllResponseHeaders: function() { + try { + return _xhr.getAllResponseHeaders(); + } catch(ex) {} + return ''; + }, + + abort: function() { + if (_xhr) { + _xhr.abort(); + } + }, + + destroy: function() { + self = _filename = null; + } + }); + + + // here we go... ugly fix for ugly bug + function _preloadAndSend(meta, data) { + var target = this, blob, fr; + + // get original blob + blob = data.getBlob().getSource(); + + // preload blob in memory to be sent as binary string + fr = new window.FileReader(); + fr.onload = function() { + // overwrite original blob + data.append(data.getBlobName(), new Blob(null, { + type: blob.type, + data: fr.result + })); + // invoke send operation again + self.send.call(target, meta, data); + }; + fr.readAsBinaryString(blob); + } + + + function _getNativeXHR() { + if (window.XMLHttpRequest && !(Env.browser === 'IE' && Env.version < 8)) { // IE7 has native XHR but it's buggy + return new window.XMLHttpRequest(); + } else { + return (function() { + var progIDs = ['Msxml2.XMLHTTP.6.0', 'Microsoft.XMLHTTP']; // if 6.0 available, use it, otherwise failback to default 3.0 + for (var i = 0; i < progIDs.length; i++) { + try { + return new ActiveXObject(progIDs[i]); + } catch (ex) {} + } + })(); + } + } + + // @credits Sergey Ilinsky (http://www.ilinsky.com/) + function _getDocument(xhr) { + var rXML = xhr.responseXML; + var rText = xhr.responseText; + + // Try parsing responseText (@see: http://www.ilinsky.com/articles/XMLHttpRequest/#bugs-ie-responseXML-content-type) + if (Env.browser === 'IE' && rText && rXML && !rXML.documentElement && /[^\/]+\/[^\+]+\+xml/.test(xhr.getResponseHeader("Content-Type"))) { + rXML = new window.ActiveXObject("Microsoft.XMLDOM"); + rXML.async = false; + rXML.validateOnParse = false; + rXML.loadXML(rText); + } + + // Check if there is no error in document + if (rXML) { + if ((Env.browser === 'IE' && rXML.parseError !== 0) || !rXML.documentElement || rXML.documentElement.tagName === "parsererror") { + return null; + } + } + return rXML; + } + + + function _prepareMultipart(fd) { + var boundary = '----moxieboundary' + new Date().getTime() + , dashdash = '--' + , crlf = '\r\n' + , multipart = '' + , I = this.getRuntime() + ; + + if (!I.can('send_binary_string')) { + throw new x.RuntimeError(x.RuntimeError.NOT_SUPPORTED_ERR); + } + + _xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + boundary); + + // append multipart parameters + fd.each(function(value, name) { + // Firefox 3.6 failed to convert multibyte characters to UTF-8 in sendAsBinary(), + // so we try it here ourselves with: unescape(encodeURIComponent(value)) + if (value instanceof Blob) { + // Build RFC2388 blob + multipart += dashdash + boundary + crlf + + 'Content-Disposition: form-data; name="' + name + '"; filename="' + unescape(encodeURIComponent(value.name || 'blob')) + '"' + crlf + + 'Content-Type: ' + (value.type || 'application/octet-stream') + crlf + crlf + + value.getSource() + crlf; + } else { + multipart += dashdash + boundary + crlf + + 'Content-Disposition: form-data; name="' + name + '"' + crlf + crlf + + unescape(encodeURIComponent(value)) + crlf; + } + }); + + multipart += dashdash + boundary + dashdash + crlf; + + return multipart; + } + } + + return (extensions.XMLHttpRequest = XMLHttpRequest); +}); + +// Included from: src/javascript/runtime/html5/utils/BinaryReader.js + +/** + * BinaryReader.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html5/utils/BinaryReader +@private +*/ +define("moxie/runtime/html5/utils/BinaryReader", [], function() { + return function() { + var II = false, bin; + + // Private functions + function read(idx, size) { + var mv = II ? 0 : -8 * (size - 1), sum = 0, i; + + for (i = 0; i < size; i++) { + sum |= (bin.charCodeAt(idx + i) << Math.abs(mv + i*8)); + } + + return sum; + } + + function putstr(segment, idx, length) { + length = arguments.length === 3 ? length : bin.length - idx - 1; + bin = bin.substr(0, idx) + segment + bin.substr(length + idx); + } + + function write(idx, num, size) { + var str = '', mv = II ? 0 : -8 * (size - 1), i; + + for (i = 0; i < size; i++) { + str += String.fromCharCode((num >> Math.abs(mv + i*8)) & 255); + } + + putstr(str, idx, size); + } + + // Public functions + return { + II: function(order) { + if (order === undefined) { + return II; + } else { + II = order; + } + }, + + init: function(binData) { + II = false; + bin = binData; + }, + + SEGMENT: function(idx, length, segment) { + switch (arguments.length) { + case 1: + return bin.substr(idx, bin.length - idx - 1); + case 2: + return bin.substr(idx, length); + case 3: + putstr(segment, idx, length); + break; + default: return bin; + } + }, + + BYTE: function(idx) { + return read(idx, 1); + }, + + SHORT: function(idx) { + return read(idx, 2); + }, + + LONG: function(idx, num) { + if (num === undefined) { + return read(idx, 4); + } else { + write(idx, num, 4); + } + }, + + SLONG: function(idx) { // 2's complement notation + var num = read(idx, 4); + + return (num > 2147483647 ? num - 4294967296 : num); + }, + + STRING: function(idx, size) { + var str = ''; + + for (size += idx; idx < size; idx++) { + str += String.fromCharCode(read(idx, 1)); + } + + return str; + } + }; + }; +}); + +// Included from: src/javascript/runtime/html5/image/JPEGHeaders.js + +/** + * JPEGHeaders.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html5/image/JPEGHeaders +@private +*/ +define("moxie/runtime/html5/image/JPEGHeaders", [ + "moxie/runtime/html5/utils/BinaryReader" +], function(BinaryReader) { + + return function JPEGHeaders(data) { + var headers = [], read, idx, marker, length = 0; + + read = new BinaryReader(); + read.init(data); + + // Check if data is jpeg + if (read.SHORT(0) !== 0xFFD8) { + return; + } + + idx = 2; + + while (idx <= data.length) { + marker = read.SHORT(idx); + + // omit RST (restart) markers + if (marker >= 0xFFD0 && marker <= 0xFFD7) { + idx += 2; + continue; + } + + // no headers allowed after SOS marker + if (marker === 0xFFDA || marker === 0xFFD9) { + break; + } + + length = read.SHORT(idx + 2) + 2; + + // APPn marker detected + if (marker >= 0xFFE1 && marker <= 0xFFEF) { + headers.push({ + hex: marker, + name: 'APP' + (marker & 0x000F), + start: idx, + length: length, + segment: read.SEGMENT(idx, length) + }); + } + + idx += length; + } + + read.init(null); // free memory + + return { + headers: headers, + + restore: function(data) { + var max, i; + + read.init(data); + + idx = read.SHORT(2) == 0xFFE0 ? 4 + read.SHORT(4) : 2; + + for (i = 0, max = headers.length; i < max; i++) { + read.SEGMENT(idx, 0, headers[i].segment); + idx += headers[i].length; + } + + data = read.SEGMENT(); + read.init(null); + return data; + }, + + strip: function(data) { + var headers, jpegHeaders, i; + + jpegHeaders = new JPEGHeaders(data); + headers = jpegHeaders.headers; + jpegHeaders.purge(); + + read.init(data); + + i = headers.length; + while (i--) { + read.SEGMENT(headers[i].start, headers[i].length, ''); + } + + data = read.SEGMENT(); + read.init(null); + return data; + }, + + get: function(name) { + var array = []; + + for (var i = 0, max = headers.length; i < max; i++) { + if (headers[i].name === name.toUpperCase()) { + array.push(headers[i].segment); + } + } + return array; + }, + + set: function(name, segment) { + var array = [], i, ii, max; + + if (typeof(segment) === 'string') { + array.push(segment); + } else { + array = segment; + } + + for (i = ii = 0, max = headers.length; i < max; i++) { + if (headers[i].name === name.toUpperCase()) { + headers[i].segment = array[ii]; + headers[i].length = array[ii].length; + ii++; + } + if (ii >= array.length) { + break; + } + } + }, + + purge: function() { + headers = []; + read.init(null); + read = null; + } + }; + }; +}); + +// Included from: src/javascript/runtime/html5/image/ExifParser.js + +/** + * ExifParser.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html5/image/ExifParser +@private +*/ +define("moxie/runtime/html5/image/ExifParser", [ + "moxie/core/utils/Basic", + "moxie/runtime/html5/utils/BinaryReader" +], function(Basic, BinaryReader) { + + return function ExifParser() { + // Private ExifParser fields + var data, tags, Tiff, offsets = {}, tagDescs; + + data = new BinaryReader(); + + tags = { + tiff : { + /* + The image orientation viewed in terms of rows and columns. + + 1 = The 0th row is at the visual top of the image, and the 0th column is the visual left-hand side. + 2 = The 0th row is at the visual top of the image, and the 0th column is the visual right-hand side. + 3 = The 0th row is at the visual bottom of the image, and the 0th column is the visual right-hand side. + 4 = The 0th row is at the visual bottom of the image, and the 0th column is the visual left-hand side. + 5 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual top. + 6 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual top. + 7 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual bottom. + 8 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual bottom. + */ + 0x0112: 'Orientation', + 0x010E: 'ImageDescription', + 0x010F: 'Make', + 0x0110: 'Model', + 0x0131: 'Software', + 0x8769: 'ExifIFDPointer', + 0x8825: 'GPSInfoIFDPointer' + }, + exif : { + 0x9000: 'ExifVersion', + 0xA001: 'ColorSpace', + 0xA002: 'PixelXDimension', + 0xA003: 'PixelYDimension', + 0x9003: 'DateTimeOriginal', + 0x829A: 'ExposureTime', + 0x829D: 'FNumber', + 0x8827: 'ISOSpeedRatings', + 0x9201: 'ShutterSpeedValue', + 0x9202: 'ApertureValue' , + 0x9207: 'MeteringMode', + 0x9208: 'LightSource', + 0x9209: 'Flash', + 0x920A: 'FocalLength', + 0xA402: 'ExposureMode', + 0xA403: 'WhiteBalance', + 0xA406: 'SceneCaptureType', + 0xA404: 'DigitalZoomRatio', + 0xA408: 'Contrast', + 0xA409: 'Saturation', + 0xA40A: 'Sharpness' + }, + gps : { + 0x0000: 'GPSVersionID', + 0x0001: 'GPSLatitudeRef', + 0x0002: 'GPSLatitude', + 0x0003: 'GPSLongitudeRef', + 0x0004: 'GPSLongitude' + } + }; + + tagDescs = { + 'ColorSpace': { + 1: 'sRGB', + 0: 'Uncalibrated' + }, + + 'MeteringMode': { + 0: 'Unknown', + 1: 'Average', + 2: 'CenterWeightedAverage', + 3: 'Spot', + 4: 'MultiSpot', + 5: 'Pattern', + 6: 'Partial', + 255: 'Other' + }, + + 'LightSource': { + 1: 'Daylight', + 2: 'Fliorescent', + 3: 'Tungsten', + 4: 'Flash', + 9: 'Fine weather', + 10: 'Cloudy weather', + 11: 'Shade', + 12: 'Daylight fluorescent (D 5700 - 7100K)', + 13: 'Day white fluorescent (N 4600 -5400K)', + 14: 'Cool white fluorescent (W 3900 - 4500K)', + 15: 'White fluorescent (WW 3200 - 3700K)', + 17: 'Standard light A', + 18: 'Standard light B', + 19: 'Standard light C', + 20: 'D55', + 21: 'D65', + 22: 'D75', + 23: 'D50', + 24: 'ISO studio tungsten', + 255: 'Other' + }, + + 'Flash': { + 0x0000: 'Flash did not fire.', + 0x0001: 'Flash fired.', + 0x0005: 'Strobe return light not detected.', + 0x0007: 'Strobe return light detected.', + 0x0009: 'Flash fired, compulsory flash mode', + 0x000D: 'Flash fired, compulsory flash mode, return light not detected', + 0x000F: 'Flash fired, compulsory flash mode, return light detected', + 0x0010: 'Flash did not fire, compulsory flash mode', + 0x0018: 'Flash did not fire, auto mode', + 0x0019: 'Flash fired, auto mode', + 0x001D: 'Flash fired, auto mode, return light not detected', + 0x001F: 'Flash fired, auto mode, return light detected', + 0x0020: 'No flash function', + 0x0041: 'Flash fired, red-eye reduction mode', + 0x0045: 'Flash fired, red-eye reduction mode, return light not detected', + 0x0047: 'Flash fired, red-eye reduction mode, return light detected', + 0x0049: 'Flash fired, compulsory flash mode, red-eye reduction mode', + 0x004D: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected', + 0x004F: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light detected', + 0x0059: 'Flash fired, auto mode, red-eye reduction mode', + 0x005D: 'Flash fired, auto mode, return light not detected, red-eye reduction mode', + 0x005F: 'Flash fired, auto mode, return light detected, red-eye reduction mode' + }, + + 'ExposureMode': { + 0: 'Auto exposure', + 1: 'Manual exposure', + 2: 'Auto bracket' + }, + + 'WhiteBalance': { + 0: 'Auto white balance', + 1: 'Manual white balance' + }, + + 'SceneCaptureType': { + 0: 'Standard', + 1: 'Landscape', + 2: 'Portrait', + 3: 'Night scene' + }, + + 'Contrast': { + 0: 'Normal', + 1: 'Soft', + 2: 'Hard' + }, + + 'Saturation': { + 0: 'Normal', + 1: 'Low saturation', + 2: 'High saturation' + }, + + 'Sharpness': { + 0: 'Normal', + 1: 'Soft', + 2: 'Hard' + }, + + // GPS related + 'GPSLatitudeRef': { + N: 'North latitude', + S: 'South latitude' + }, + + 'GPSLongitudeRef': { + E: 'East longitude', + W: 'West longitude' + } + }; + + function extractTags(IFD_offset, tags2extract) { + var length = data.SHORT(IFD_offset), i, ii, + tag, type, count, tagOffset, offset, value, values = [], hash = {}; + + for (i = 0; i < length; i++) { + // Set binary reader pointer to beginning of the next tag + offset = tagOffset = IFD_offset + 12 * i + 2; + + tag = tags2extract[data.SHORT(offset)]; + + if (tag === undefined) { + continue; // Not the tag we requested + } + + type = data.SHORT(offset+=2); + count = data.LONG(offset+=2); + + offset += 4; + values = []; + + switch (type) { + case 1: // BYTE + case 7: // UNDEFINED + if (count > 4) { + offset = data.LONG(offset) + offsets.tiffHeader; + } + + for (ii = 0; ii < count; ii++) { + values[ii] = data.BYTE(offset + ii); + } + + break; + + case 2: // STRING + if (count > 4) { + offset = data.LONG(offset) + offsets.tiffHeader; + } + + hash[tag] = data.STRING(offset, count - 1); + + continue; + + case 3: // SHORT + if (count > 2) { + offset = data.LONG(offset) + offsets.tiffHeader; + } + + for (ii = 0; ii < count; ii++) { + values[ii] = data.SHORT(offset + ii*2); + } + + break; + + case 4: // LONG + if (count > 1) { + offset = data.LONG(offset) + offsets.tiffHeader; + } + + for (ii = 0; ii < count; ii++) { + values[ii] = data.LONG(offset + ii*4); + } + + break; + + case 5: // RATIONAL + offset = data.LONG(offset) + offsets.tiffHeader; + + for (ii = 0; ii < count; ii++) { + values[ii] = data.LONG(offset + ii*4) / data.LONG(offset + ii*4 + 4); + } + + break; + + case 9: // SLONG + offset = data.LONG(offset) + offsets.tiffHeader; + + for (ii = 0; ii < count; ii++) { + values[ii] = data.SLONG(offset + ii*4); + } + + break; + + case 10: // SRATIONAL + offset = data.LONG(offset) + offsets.tiffHeader; + + for (ii = 0; ii < count; ii++) { + values[ii] = data.SLONG(offset + ii*4) / data.SLONG(offset + ii*4 + 4); + } + + break; + + default: + continue; + } + + value = (count == 1 ? values[0] : values); + + if (tagDescs.hasOwnProperty(tag) && typeof value != 'object') { + hash[tag] = tagDescs[tag][value]; + } else { + hash[tag] = value; + } + } + + return hash; + } + + function getIFDOffsets() { + var idx = offsets.tiffHeader; + + // Set read order of multi-byte data + data.II(data.SHORT(idx) == 0x4949); + + // Check if always present bytes are indeed present + if (data.SHORT(idx+=2) !== 0x002A) { + return false; + } + + offsets.IFD0 = offsets.tiffHeader + data.LONG(idx += 2); + Tiff = extractTags(offsets.IFD0, tags.tiff); + + if ('ExifIFDPointer' in Tiff) { + offsets.exifIFD = offsets.tiffHeader + Tiff.ExifIFDPointer; + delete Tiff.ExifIFDPointer; + } + + if ('GPSInfoIFDPointer' in Tiff) { + offsets.gpsIFD = offsets.tiffHeader + Tiff.GPSInfoIFDPointer; + delete Tiff.GPSInfoIFDPointer; + } + return true; + } + + // At the moment only setting of simple (LONG) values, that do not require offset recalculation, is supported + function setTag(ifd, tag, value) { + var offset, length, tagOffset, valueOffset = 0; + + // If tag name passed translate into hex key + if (typeof(tag) === 'string') { + var tmpTags = tags[ifd.toLowerCase()]; + for (var hex in tmpTags) { + if (tmpTags[hex] === tag) { + tag = hex; + break; + } + } + } + offset = offsets[ifd.toLowerCase() + 'IFD']; + length = data.SHORT(offset); + + for (var i = 0; i < length; i++) { + tagOffset = offset + 12 * i + 2; + + if (data.SHORT(tagOffset) == tag) { + valueOffset = tagOffset + 8; + break; + } + } + + if (!valueOffset) { + return false; + } + + data.LONG(valueOffset, value); + return true; + } + + + // Public functions + return { + init: function(segment) { + // Reset internal data + offsets = { + tiffHeader: 10 + }; + + if (segment === undefined || !segment.length) { + return false; + } + + data.init(segment); + + // Check if that's APP1 and that it has EXIF + if (data.SHORT(0) === 0xFFE1 && data.STRING(4, 5).toUpperCase() === "EXIF\0") { + return getIFDOffsets(); + } + return false; + }, + + TIFF: function() { + return Tiff; + }, + + EXIF: function() { + var Exif; + + // Populate EXIF hash + Exif = extractTags(offsets.exifIFD, tags.exif); + + // Fix formatting of some tags + if (Exif.ExifVersion && Basic.typeOf(Exif.ExifVersion) === 'array') { + for (var i = 0, exifVersion = ''; i < Exif.ExifVersion.length; i++) { + exifVersion += String.fromCharCode(Exif.ExifVersion[i]); + } + Exif.ExifVersion = exifVersion; + } + + return Exif; + }, + + GPS: function() { + var GPS; + + GPS = extractTags(offsets.gpsIFD, tags.gps); + + // iOS devices (and probably some others) do not put in GPSVersionID tag (why?..) + if (GPS.GPSVersionID && Basic.typeOf(GPS.GPSVersionID) === 'array') { + GPS.GPSVersionID = GPS.GPSVersionID.join('.'); + } + + return GPS; + }, + + setExif: function(tag, value) { + // Right now only setting of width/height is possible + if (tag !== 'PixelXDimension' && tag !== 'PixelYDimension') {return false;} + + return setTag('exif', tag, value); + }, + + + getBinary: function() { + return data.SEGMENT(); + }, + + purge: function() { + data.init(null); + data = Tiff = null; + offsets = {}; + } + }; + }; +}); + +// Included from: src/javascript/runtime/html5/image/JPEG.js + +/** + * JPEG.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html5/image/JPEG +@private +*/ +define("moxie/runtime/html5/image/JPEG", [ + "moxie/core/utils/Basic", + "moxie/core/Exceptions", + "moxie/runtime/html5/image/JPEGHeaders", + "moxie/runtime/html5/utils/BinaryReader", + "moxie/runtime/html5/image/ExifParser" +], function(Basic, x, JPEGHeaders, BinaryReader, ExifParser) { + + function JPEG(binstr) { + var _binstr, _br, _hm, _ep, _info, hasExif; + + function _getDimensions() { + var idx = 0, marker, length; + + // examine all through the end, since some images might have very large APP segments + while (idx <= _binstr.length) { + marker = _br.SHORT(idx += 2); + + if (marker >= 0xFFC0 && marker <= 0xFFC3) { // SOFn + idx += 5; // marker (2 bytes) + length (2 bytes) + Sample precision (1 byte) + return { + height: _br.SHORT(idx), + width: _br.SHORT(idx += 2) + }; + } + length = _br.SHORT(idx += 2); + idx += length - 2; + } + return null; + } + + _binstr = binstr; + + _br = new BinaryReader(); + _br.init(_binstr); + + // check if it is jpeg + if (_br.SHORT(0) !== 0xFFD8) { + throw new x.ImageError(x.ImageError.WRONG_FORMAT); + } + + // backup headers + _hm = new JPEGHeaders(binstr); + + // extract exif info + _ep = new ExifParser(); + hasExif = !!_ep.init(_hm.get('app1')[0]); + + // get dimensions + _info = _getDimensions.call(this); + + Basic.extend(this, { + type: 'image/jpeg', + + size: _binstr.length, + + width: _info && _info.width || 0, + + height: _info && _info.height || 0, + + setExif: function(tag, value) { + if (!hasExif) { + return false; // or throw an exception + } + + if (Basic.typeOf(tag) === 'object') { + Basic.each(tag, function(value, tag) { + _ep.setExif(tag, value); + }); + } else { + _ep.setExif(tag, value); + } + + // update internal headers + _hm.set('app1', _ep.getBinary()); + }, + + writeHeaders: function() { + if (!arguments.length) { + // if no arguments passed, update headers internally + return (_binstr = _hm.restore(_binstr)); + } + return _hm.restore(arguments[0]); + }, + + stripHeaders: function(binstr) { + return _hm.strip(binstr); + }, + + purge: function() { + _purge.call(this); + } + }); + + if (hasExif) { + this.meta = { + tiff: _ep.TIFF(), + exif: _ep.EXIF(), + gps: _ep.GPS() + }; + } + + function _purge() { + if (!_ep || !_hm || !_br) { + return; // ignore any repeating purge requests + } + _ep.purge(); + _hm.purge(); + _br.init(null); + _binstr = _info = _hm = _ep = _br = null; + } + } + + return JPEG; +}); + +// Included from: src/javascript/runtime/html5/image/PNG.js + +/** + * PNG.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html5/image/PNG +@private +*/ +define("moxie/runtime/html5/image/PNG", [ + "moxie/core/Exceptions", + "moxie/core/utils/Basic", + "moxie/runtime/html5/utils/BinaryReader" +], function(x, Basic, BinaryReader) { + + function PNG(binstr) { + var _binstr, _br, _hm, _ep, _info; + + _binstr = binstr; + + _br = new BinaryReader(); + _br.init(_binstr); + + // check if it's png + (function() { + var idx = 0, i = 0 + , signature = [0x8950, 0x4E47, 0x0D0A, 0x1A0A] + ; + + for (i = 0; i < signature.length; i++, idx += 2) { + if (signature[i] != _br.SHORT(idx)) { + throw new x.ImageError(x.ImageError.WRONG_FORMAT); + } + } + }()); + + function _getDimensions() { + var chunk, idx; + + chunk = _getChunkAt.call(this, 8); + + if (chunk.type == 'IHDR') { + idx = chunk.start; + return { + width: _br.LONG(idx), + height: _br.LONG(idx += 4) + }; + } + return null; + } + + function _purge() { + if (!_br) { + return; // ignore any repeating purge requests + } + _br.init(null); + _binstr = _info = _hm = _ep = _br = null; + } + + _info = _getDimensions.call(this); + + Basic.extend(this, { + type: 'image/png', + + size: _binstr.length, + + width: _info.width, + + height: _info.height, + + purge: function() { + _purge.call(this); + } + }); + + // for PNG we can safely trigger purge automatically, as we do not keep any data for later + _purge.call(this); + + function _getChunkAt(idx) { + var length, type, start, CRC; + + length = _br.LONG(idx); + type = _br.STRING(idx += 4, 4); + start = idx += 4; + CRC = _br.LONG(idx + length); + + return { + length: length, + type: type, + start: start, + CRC: CRC + }; + } + } + + return PNG; +}); + +// Included from: src/javascript/runtime/html5/image/ImageInfo.js + +/** + * ImageInfo.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html5/image/ImageInfo +@private +*/ +define("moxie/runtime/html5/image/ImageInfo", [ + "moxie/core/utils/Basic", + "moxie/core/Exceptions", + "moxie/runtime/html5/image/JPEG", + "moxie/runtime/html5/image/PNG" +], function(Basic, x, JPEG, PNG) { + /** + Optional image investigation tool for HTML5 runtime. Provides the following features: + - ability to distinguish image type (JPEG or PNG) by signature + - ability to extract image width/height directly from it's internals, without preloading in memory (fast) + - ability to extract APP headers from JPEGs (Exif, GPS, etc) + - ability to replace width/height tags in extracted JPEG headers + - ability to restore APP headers, that were for example stripped during image manipulation + + @class ImageInfo + @constructor + @param {String} binstr Image source as binary string + */ + return function(binstr) { + var _cs = [JPEG, PNG], _img; + + // figure out the format, throw: ImageError.WRONG_FORMAT if not supported + _img = (function() { + for (var i = 0; i < _cs.length; i++) { + try { + return new _cs[i](binstr); + } catch (ex) { + // console.info(ex); + } + } + throw new x.ImageError(x.ImageError.WRONG_FORMAT); + }()); + + Basic.extend(this, { + /** + Image Mime Type extracted from it's depths + + @property type + @type {String} + @default '' + */ + type: '', + + /** + Image size in bytes + + @property size + @type {Number} + @default 0 + */ + size: 0, + + /** + Image width extracted from image source + + @property width + @type {Number} + @default 0 + */ + width: 0, + + /** + Image height extracted from image source + + @property height + @type {Number} + @default 0 + */ + height: 0, + + /** + Sets Exif tag. Currently applicable only for width and height tags. Obviously works only with JPEGs. + + @method setExif + @param {String} tag Tag to set + @param {Mixed} value Value to assign to the tag + */ + setExif: function() {}, + + /** + Restores headers to the source. + + @method writeHeaders + @param {String} data Image source as binary string + @return {String} Updated binary string + */ + writeHeaders: function(data) { + return data; + }, + + /** + Strip all headers from the source. + + @method stripHeaders + @param {String} data Image source as binary string + @return {String} Updated binary string + */ + stripHeaders: function(data) { + return data; + }, + + /** + Dispose resources. + + @method purge + */ + purge: function() {} + }); + + Basic.extend(this, _img); + + this.purge = function() { + _img.purge(); + _img = null; + }; + }; +}); + +// Included from: src/javascript/runtime/html5/image/MegaPixel.js + +/** +(The MIT License) + +Copyright (c) 2012 Shinichi Tomita ; + +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. +*/ + +/** + * Mega pixel image rendering library for iOS6 Safari + * + * Fixes iOS6 Safari's image file rendering issue for large size image (over mega-pixel), + * which causes unexpected subsampling when drawing it in canvas. + * By using this library, you can safely render the image with proper stretching. + * + * Copyright (c) 2012 Shinichi Tomita + * Released under the MIT license + */ + +/** +@class moxie/runtime/html5/image/MegaPixel +@private +*/ +define("moxie/runtime/html5/image/MegaPixel", [], function() { + + /** + * Rendering image element (with resizing) into the canvas element + */ + function renderImageToCanvas(img, canvas, options) { + var iw = img.naturalWidth, ih = img.naturalHeight; + var width = options.width, height = options.height; + var x = options.x || 0, y = options.y || 0; + var ctx = canvas.getContext('2d'); + if (detectSubsampling(img)) { + iw /= 2; + ih /= 2; + } + var d = 1024; // size of tiling canvas + var tmpCanvas = document.createElement('canvas'); + tmpCanvas.width = tmpCanvas.height = d; + var tmpCtx = tmpCanvas.getContext('2d'); + var vertSquashRatio = detectVerticalSquash(img, iw, ih); + var sy = 0; + while (sy < ih) { + var sh = sy + d > ih ? ih - sy : d; + var sx = 0; + while (sx < iw) { + var sw = sx + d > iw ? iw - sx : d; + tmpCtx.clearRect(0, 0, d, d); + tmpCtx.drawImage(img, -sx, -sy); + var dx = (sx * width / iw + x) << 0; + var dw = Math.ceil(sw * width / iw); + var dy = (sy * height / ih / vertSquashRatio + y) << 0; + var dh = Math.ceil(sh * height / ih / vertSquashRatio); + ctx.drawImage(tmpCanvas, 0, 0, sw, sh, dx, dy, dw, dh); + sx += d; + } + sy += d; + } + tmpCanvas = tmpCtx = null; + } + + /** + * Detect subsampling in loaded image. + * In iOS, larger images than 2M pixels may be subsampled in rendering. + */ + function detectSubsampling(img) { + var iw = img.naturalWidth, ih = img.naturalHeight; + if (iw * ih > 1024 * 1024) { // subsampling may happen over megapixel image + var canvas = document.createElement('canvas'); + canvas.width = canvas.height = 1; + var ctx = canvas.getContext('2d'); + ctx.drawImage(img, -iw + 1, 0); + // subsampled image becomes half smaller in rendering size. + // check alpha channel value to confirm image is covering edge pixel or not. + // if alpha value is 0 image is not covering, hence subsampled. + return ctx.getImageData(0, 0, 1, 1).data[3] === 0; + } else { + return false; + } + } + + + /** + * Detecting vertical squash in loaded image. + * Fixes a bug which squash image vertically while drawing into canvas for some images. + */ + function detectVerticalSquash(img, iw, ih) { + var canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = ih; + var ctx = canvas.getContext('2d'); + ctx.drawImage(img, 0, 0); + var data = ctx.getImageData(0, 0, 1, ih).data; + // search image edge pixel position in case it is squashed vertically. + var sy = 0; + var ey = ih; + var py = ih; + while (py > sy) { + var alpha = data[(py - 1) * 4 + 3]; + if (alpha === 0) { + ey = py; + } else { + sy = py; + } + py = (ey + sy) >> 1; + } + canvas = null; + var ratio = (py / ih); + return (ratio === 0) ? 1 : ratio; + } + + return { + isSubsampled: detectSubsampling, + renderTo: renderImageToCanvas + }; +}); + +// Included from: src/javascript/runtime/html5/image/Image.js + +/** + * Image.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html5/image/Image +@private +*/ +define("moxie/runtime/html5/image/Image", [ + "moxie/runtime/html5/Runtime", + "moxie/core/utils/Basic", + "moxie/core/Exceptions", + "moxie/core/utils/Encode", + "moxie/file/File", + "moxie/runtime/html5/image/ImageInfo", + "moxie/runtime/html5/image/MegaPixel", + "moxie/core/utils/Mime", + "moxie/core/utils/Env" +], function(extensions, Basic, x, Encode, File, ImageInfo, MegaPixel, Mime, Env) { + + function HTML5Image() { + var me = this + , _img, _imgInfo, _canvas, _binStr, _blob + , _modified = false // is set true whenever image is modified + , _preserveHeaders = true + ; + + Basic.extend(this, { + loadFromBlob: function(blob) { + var comp = this, I = comp.getRuntime() + , asBinary = arguments.length > 1 ? arguments[1] : true + ; + + if (!I.can('access_binary')) { + throw new x.RuntimeError(x.RuntimeError.NOT_SUPPORTED_ERR); + } + + _blob = blob; + + if (blob.isDetached()) { + _binStr = blob.getSource(); + _preload.call(this, _binStr); + return; + } else { + _readAsDataUrl.call(this, blob.getSource(), function(dataUrl) { + if (asBinary) { + _binStr = _toBinary(dataUrl); + } + _preload.call(comp, dataUrl); + }); + } + }, + + loadFromImage: function(img, exact) { + this.meta = img.meta; + + _blob = new File(null, { + name: img.name, + size: img.size, + type: img.type + }); + + _preload.call(this, exact ? (_binStr = img.getAsBinaryString()) : img.getAsDataURL()); + }, + + getInfo: function() { + var I = this.getRuntime(), info; + + if (!_imgInfo && _binStr && I.can('access_image_binary')) { + _imgInfo = new ImageInfo(_binStr); + } + + info = { + width: _getImg().width || 0, + height: _getImg().height || 0, + type: _blob.type || Mime.getFileMime(_blob.name), + size: _binStr && _binStr.length || _blob.size || 0, + name: _blob.name || '', + meta: _imgInfo && _imgInfo.meta || this.meta || {} + }; + + return info; + }, + + downsize: function() { + _downsize.apply(this, arguments); + }, + + getAsCanvas: function() { + if (_canvas) { + _canvas.id = this.uid + '_canvas'; + } + return _canvas; + }, + + getAsBlob: function(type, quality) { + if (type !== this.type) { + // if different mime type requested prepare image for conversion + _downsize.call(this, this.width, this.height, false); + } + return new File(null, { + name: _blob.name || '', + type: type, + data: me.getAsBinaryString.call(this, type, quality) + }); + }, + + getAsDataURL: function(type) { + var quality = arguments[1] || 90; + + // if image has not been modified, return the source right away + if (!_modified) { + return _img.src; + } + + if ('image/jpeg' !== type) { + return _canvas.toDataURL('image/png'); + } else { + try { + // older Geckos used to result in an exception on quality argument + return _canvas.toDataURL('image/jpeg', quality/100); + } catch (ex) { + return _canvas.toDataURL('image/jpeg'); + } + } + }, + + getAsBinaryString: function(type, quality) { + // if image has not been modified, return the source right away + if (!_modified) { + // if image was not loaded from binary string + if (!_binStr) { + _binStr = _toBinary(me.getAsDataURL(type, quality)); + } + return _binStr; + } + + if ('image/jpeg' !== type) { + _binStr = _toBinary(me.getAsDataURL(type, quality)); + } else { + var dataUrl; + + // if jpeg + if (!quality) { + quality = 90; + } + + try { + // older Geckos used to result in an exception on quality argument + dataUrl = _canvas.toDataURL('image/jpeg', quality/100); + } catch (ex) { + dataUrl = _canvas.toDataURL('image/jpeg'); + } + + _binStr = _toBinary(dataUrl); + + if (_imgInfo) { + _binStr = _imgInfo.stripHeaders(_binStr); + + if (_preserveHeaders) { + // update dimensions info in exif + if (_imgInfo.meta && _imgInfo.meta.exif) { + _imgInfo.setExif({ + PixelXDimension: this.width, + PixelYDimension: this.height + }); + } + + // re-inject the headers + _binStr = _imgInfo.writeHeaders(_binStr); + } + + // will be re-created from fresh on next getInfo call + _imgInfo.purge(); + _imgInfo = null; + } + } + + _modified = false; + + return _binStr; + }, + + destroy: function() { + me = null; + _purge.call(this); + this.getRuntime().getShim().removeInstance(this.uid); + } + }); + + + function _getImg() { + if (!_canvas && !_img) { + throw new x.ImageError(x.DOMException.INVALID_STATE_ERR); + } + return _canvas || _img; + } + + + function _toBinary(str) { + return Encode.atob(str.substring(str.indexOf('base64,') + 7)); + } + + + function _toDataUrl(str, type) { + return 'data:' + (type || '') + ';base64,' + Encode.btoa(str); + } + + + function _preload(str) { + var comp = this; + + _img = new Image(); + _img.onerror = function() { + _purge.call(this); + comp.trigger('error', x.ImageError.WRONG_FORMAT); + }; + _img.onload = function() { + comp.trigger('load'); + }; + + _img.src = /^data:[^;]*;base64,/.test(str) ? str : _toDataUrl(str, _blob.type); + } + + + function _readAsDataUrl(file, callback) { + var comp = this, fr; + + // use FileReader if it's available + if (window.FileReader) { + fr = new FileReader(); + fr.onload = function() { + callback(this.result); + }; + fr.onerror = function() { + comp.trigger('error', x.ImageError.WRONG_FORMAT); + }; + fr.readAsDataURL(file); + } else { + return callback(file.getAsDataURL()); + } + } + + function _downsize(width, height, crop, preserveHeaders) { + var self = this + , scale + , mathFn + , x = 0 + , y = 0 + , img + , destWidth + , destHeight + , orientation + ; + + _preserveHeaders = preserveHeaders; // we will need to check this on export (see getAsBinaryString()) + + // take into account orientation tag + orientation = (this.meta && this.meta.tiff && this.meta.tiff.Orientation) || 1; + + if (Basic.inArray(orientation, [5,6,7,8]) !== -1) { // values that require 90 degree rotation + // swap dimensions + var tmp = width; + width = height; + height = tmp; + } + + img = _getImg(); + + // unify dimensions + if (!crop) { + scale = Math.min(width/img.width, height/img.height); + } else { + // one of the dimensions may exceed the actual image dimensions - we need to take the smallest value + width = Math.min(width, img.width); + height = Math.min(height, img.height); + + scale = Math.max(width/img.width, height/img.height); + } + + // we only downsize here + if (scale > 1 && !crop && preserveHeaders) { + this.trigger('Resize'); + return; + } + + // prepare canvas if necessary + if (!_canvas) { + _canvas = document.createElement("canvas"); + } + + // calculate dimensions of proportionally resized image + destWidth = Math.round(img.width * scale); + destHeight = Math.round(img.height * scale); + + // scale image and canvas + if (crop) { + _canvas.width = width; + _canvas.height = height; + + // if dimensions of the resulting image still larger than canvas, center it + if (destWidth > width) { + x = Math.round((destWidth - width) / 2); + } + + if (destHeight > height) { + y = Math.round((destHeight - height) / 2); + } + } else { + _canvas.width = destWidth; + _canvas.height = destHeight; + } + + // rotate if required, according to orientation tag + if (!_preserveHeaders) { + _rotateToOrientaion(_canvas.width, _canvas.height, orientation); + } + + _drawToCanvas.call(this, img, _canvas, -x, -y, destWidth, destHeight); + + this.width = _canvas.width; + this.height = _canvas.height; + + _modified = true; + self.trigger('Resize'); + } + + + function _drawToCanvas(img, canvas, x, y, w, h) { + if (Env.OS === 'iOS') { + // avoid squish bug in iOS6 + MegaPixel.renderTo(img, canvas, { width: w, height: h, x: x, y: y }); + } else { + var ctx = canvas.getContext('2d'); + ctx.drawImage(img, x, y, w, h); + } + } + + + /** + * Transform canvas coordination according to specified frame size and orientation + * Orientation value is from EXIF tag + * @author Shinichi Tomita + */ + function _rotateToOrientaion(width, height, orientation) { + switch (orientation) { + case 5: + case 6: + case 7: + case 8: + _canvas.width = height; + _canvas.height = width; + break; + default: + _canvas.width = width; + _canvas.height = height; + } + + /** + 1 = The 0th row is at the visual top of the image, and the 0th column is the visual left-hand side. + 2 = The 0th row is at the visual top of the image, and the 0th column is the visual right-hand side. + 3 = The 0th row is at the visual bottom of the image, and the 0th column is the visual right-hand side. + 4 = The 0th row is at the visual bottom of the image, and the 0th column is the visual left-hand side. + 5 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual top. + 6 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual top. + 7 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual bottom. + 8 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual bottom. + */ + + var ctx = _canvas.getContext('2d'); + switch (orientation) { + case 2: + // horizontal flip + ctx.translate(width, 0); + ctx.scale(-1, 1); + break; + case 3: + // 180 rotate left + ctx.translate(width, height); + ctx.rotate(Math.PI); + break; + case 4: + // vertical flip + ctx.translate(0, height); + ctx.scale(1, -1); + break; + case 5: + // vertical flip + 90 rotate right + ctx.rotate(0.5 * Math.PI); + ctx.scale(1, -1); + break; + case 6: + // 90 rotate right + ctx.rotate(0.5 * Math.PI); + ctx.translate(0, -height); + break; + case 7: + // horizontal flip + 90 rotate right + ctx.rotate(0.5 * Math.PI); + ctx.translate(width, -height); + ctx.scale(-1, 1); + break; + case 8: + // 90 rotate left + ctx.rotate(-0.5 * Math.PI); + ctx.translate(-width, 0); + break; + } + } + + + function _purge() { + if (_imgInfo) { + _imgInfo.purge(); + _imgInfo = null; + } + _binStr = _img = _canvas = _blob = null; + _modified = false; + } + } + + return (extensions.Image = HTML5Image); +}); + +// Included from: src/javascript/runtime/flash/Runtime.js + +/** + * Runtime.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/*global ActiveXObject:true */ + +/** +Defines constructor for Flash runtime. + +@class moxie/runtime/flash/Runtime +@private +*/ +define("moxie/runtime/flash/Runtime", [ + "moxie/core/utils/Basic", + "moxie/core/utils/Env", + "moxie/core/utils/Dom", + "moxie/core/Exceptions", + "moxie/runtime/Runtime" +], function(Basic, Env, Dom, x, Runtime) { + + var type = 'flash', extensions = {}; + + /** + Get the version of the Flash Player + + @method getShimVersion + @private + @return {Number} Flash Player version + */ + function getShimVersion() { + var version; + + try { + version = navigator.plugins['Shockwave Flash']; + version = version.description; + } catch (e1) { + try { + version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version'); + } catch (e2) { + version = '0.0'; + } + } + version = version.match(/\d+/g); + return parseFloat(version[0] + '.' + version[1]); + } + + /** + Constructor for the Flash Runtime + + @class FlashRuntime + @extends Runtime + */ + function FlashRuntime(options) { + var I = this, initTimer; + + options = Basic.extend({ swf_url: Env.swf_url }, options); + + Runtime.call(this, options, type, { + access_binary: function(value) { + return value && I.mode === 'browser'; + }, + access_image_binary: function(value) { + return value && I.mode === 'browser'; + }, + display_media: Runtime.capTrue, + do_cors: Runtime.capTrue, + drag_and_drop: false, + report_upload_progress: function() { + return I.mode === 'client'; + }, + resize_image: Runtime.capTrue, + return_response_headers: false, + return_response_type: function(responseType) { + if (responseType === 'json' && !!window.JSON) { + return true; + } + return !Basic.arrayDiff(responseType, ['', 'text', 'document']) || I.mode === 'browser'; + }, + return_status_code: function(code) { + return I.mode === 'browser' || !Basic.arrayDiff(code, [200, 404]); + }, + select_file: Runtime.capTrue, + select_multiple: Runtime.capTrue, + send_binary_string: function(value) { + return value && I.mode === 'browser'; + }, + send_browser_cookies: function(value) { + return value && I.mode === 'browser'; + }, + send_custom_headers: function(value) { + return value && I.mode === 'browser'; + }, + send_multipart: Runtime.capTrue, + slice_blob: function(value) { + return value && I.mode === 'browser'; + }, + stream_upload: function(value) { + return value && I.mode === 'browser'; + }, + summon_file_dialog: false, + upload_filesize: function(size) { + return Basic.parseSizeStr(size) <= 2097152 || I.mode === 'client'; + }, + use_http_method: function(methods) { + return !Basic.arrayDiff(methods, ['GET', 'POST']); + } + }, { + // capabilities that require specific mode + access_binary: function(value) { + return value ? 'browser' : 'client'; + }, + access_image_binary: function(value) { + return value ? 'browser' : 'client'; + }, + report_upload_progress: function(value) { + return value ? 'browser' : 'client'; + }, + return_response_type: function(responseType) { + return Basic.arrayDiff(responseType, ['', 'text', 'json', 'document']) ? 'browser' : ['client', 'browser']; + }, + return_status_code: function(code) { + return Basic.arrayDiff(code, [200, 404]) ? 'browser' : ['client', 'browser']; + }, + send_binary_string: function(value) { + return value ? 'browser' : 'client'; + }, + send_browser_cookies: function(value) { + return value ? 'browser' : 'client'; + }, + send_custom_headers: function(value) { + return value ? 'browser' : 'client'; + }, + stream_upload: function(value) { + return value ? 'client' : 'browser'; + }, + upload_filesize: function(size) { + return Basic.parseSizeStr(size) >= 2097152 ? 'client' : 'browser'; + } + }, 'client'); + + + // minimal requirement for Flash Player version + if (getShimVersion() < 10) { + this.mode = false; // with falsy mode, runtime won't operable, no matter what the mode was before + } + + + Basic.extend(this, { + + getShim: function() { + return Dom.get(this.uid); + }, + + shimExec: function(component, action) { + var args = [].slice.call(arguments, 2); + return I.getShim().exec(this.uid, component, action, args); + }, + + init: function() { + var html, el, container; + + container = this.getShimContainer(); + + // if not the minimal height, shims are not initialized in older browsers (e.g FF3.6, IE6,7,8, Safari 4.0,5.0, etc) + Basic.extend(container.style, { + position: 'absolute', + top: '-8px', + left: '-8px', + width: '9px', + height: '9px', + overflow: 'hidden' + }); + + // insert flash object + html = '' + + '' + + '' + + '' + + ''; + + if (Env.browser === 'IE') { + el = document.createElement('div'); + container.appendChild(el); + el.outerHTML = html; + el = container = null; // just in case + } else { + container.innerHTML = html; + } + + // Init is dispatched by the shim + initTimer = setTimeout(function() { + if (I && !I.initialized) { // runtime might be already destroyed by this moment + I.trigger("Error", new x.RuntimeError(x.RuntimeError.NOT_INIT_ERR)); + } + }, 5000); + }, + + destroy: (function(destroy) { // extend default destroy method + return function() { + destroy.call(I); + clearTimeout(initTimer); // initialization check might be still onwait + options = initTimer = destroy = I = null; + }; + }(this.destroy)) + + }, extensions); + } + + Runtime.addConstructor(type, FlashRuntime); + + return extensions; +}); + +// Included from: src/javascript/runtime/flash/file/Blob.js + +/** + * Blob.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/flash/file/Blob +@private +*/ +define("moxie/runtime/flash/file/Blob", [ + "moxie/runtime/flash/Runtime", + "moxie/file/Blob" +], function(extensions, Blob) { + + var FlashBlob = { + slice: function(blob, start, end, type) { + var self = this.getRuntime(); + + if (start < 0) { + start = Math.max(blob.size + start, 0); + } else if (start > 0) { + start = Math.min(start, blob.size); + } + + if (end < 0) { + end = Math.max(blob.size + end, 0); + } else if (end > 0) { + end = Math.min(end, blob.size); + } + + blob = self.shimExec.call(this, 'Blob', 'slice', start, end, type || ''); + + if (blob) { + blob = new Blob(self.uid, blob); + } + return blob; + } + }; + + return (extensions.Blob = FlashBlob); +}); + +// Included from: src/javascript/runtime/flash/file/FileInput.js + +/** + * FileInput.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/flash/file/FileInput +@private +*/ +define("moxie/runtime/flash/file/FileInput", [ + "moxie/runtime/flash/Runtime" +], function(extensions) { + + var FileInput = { + init: function(options) { + this.getRuntime().shimExec.call(this, 'FileInput', 'init', { + name: options.name, + accept: options.accept, + multiple: options.multiple + }); + this.trigger('ready'); + } + }; + + return (extensions.FileInput = FileInput); +}); + +// Included from: src/javascript/runtime/flash/file/FileReader.js + +/** + * FileReader.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/flash/file/FileReader +@private +*/ +define("moxie/runtime/flash/file/FileReader", [ + "moxie/runtime/flash/Runtime", + "moxie/core/utils/Encode" +], function(extensions, Encode) { + + var _result = ''; + + function _formatData(data, op) { + switch (op) { + case 'readAsText': + return Encode.atob(data, 'utf8'); + case 'readAsBinaryString': + return Encode.atob(data); + case 'readAsDataURL': + return data; + } + return null; + } + + var FileReader = { + read: function(op, blob) { + var target = this, self = target.getRuntime(); + + // special prefix for DataURL read mode + if (op === 'readAsDataURL') { + _result = 'data:' + (blob.type || '') + ';base64,'; + } + + target.bind('Progress', function(e, data) { + if (data) { + _result += _formatData(data, op); + } + }); + + return self.shimExec.call(this, 'FileReader', 'readAsBase64', blob.uid); + }, + + getResult: function() { + return _result; + }, + + destroy: function() { + _result = null; + } + }; + + return (extensions.FileReader = FileReader); +}); + +// Included from: src/javascript/runtime/flash/file/FileReaderSync.js + +/** + * FileReaderSync.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/flash/file/FileReaderSync +@private +*/ +define("moxie/runtime/flash/file/FileReaderSync", [ + "moxie/runtime/flash/Runtime", + "moxie/core/utils/Encode" +], function(extensions, Encode) { + + function _formatData(data, op) { + switch (op) { + case 'readAsText': + return Encode.atob(data, 'utf8'); + case 'readAsBinaryString': + return Encode.atob(data); + case 'readAsDataURL': + return data; + } + return null; + } + + var FileReaderSync = { + read: function(op, blob) { + var result, self = this.getRuntime(); + + result = self.shimExec.call(this, 'FileReaderSync', 'readAsBase64', blob.uid); + if (!result) { + return null; // or throw ex + } + + // special prefix for DataURL read mode + if (op === 'readAsDataURL') { + result = 'data:' + (blob.type || '') + ';base64,' + result; + } + + return _formatData(result, op, blob.type); + } + }; + + return (extensions.FileReaderSync = FileReaderSync); +}); + +// Included from: src/javascript/runtime/flash/xhr/XMLHttpRequest.js + +/** + * XMLHttpRequest.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/flash/xhr/XMLHttpRequest +@private +*/ +define("moxie/runtime/flash/xhr/XMLHttpRequest", [ + "moxie/runtime/flash/Runtime", + "moxie/core/utils/Basic", + "moxie/file/Blob", + "moxie/file/File", + "moxie/file/FileReaderSync", + "moxie/xhr/FormData", + "moxie/runtime/Transporter" +], function(extensions, Basic, Blob, File, FileReaderSync, FormData, Transporter) { + + var XMLHttpRequest = { + + send: function(meta, data) { + var target = this, self = target.getRuntime(); + + function send() { + meta.transport = self.mode; + self.shimExec.call(target, 'XMLHttpRequest', 'send', meta, data); + } + + + function appendBlob(name, blob) { + self.shimExec.call(target, 'XMLHttpRequest', 'appendBlob', name, blob.uid); + data = null; + send(); + } + + + function attachBlob(blob, cb) { + var tr = new Transporter(); + + tr.bind("TransportingComplete", function() { + cb(this.result); + }); + + tr.transport(blob.getSource(), blob.type, { + ruid: self.uid + }); + } + + // copy over the headers if any + if (!Basic.isEmptyObj(meta.headers)) { + Basic.each(meta.headers, function(value, header) { + self.shimExec.call(target, 'XMLHttpRequest', 'setRequestHeader', header, value.toString()); // Silverlight doesn't accept integers into the arguments of type object + }); + } + + // transfer over multipart params and blob itself + if (data instanceof FormData) { + var blobField; + data.each(function(value, name) { + if (value instanceof Blob) { + blobField = name; + } else { + self.shimExec.call(target, 'XMLHttpRequest', 'append', name, value); + } + }); + + if (!data.hasBlob()) { + data = null; + send(); + } else { + var blob = data.getBlob(); + if (blob.isDetached()) { + attachBlob(blob, function(attachedBlob) { + blob.destroy(); + appendBlob(blobField, attachedBlob); + }); + } else { + appendBlob(blobField, blob); + } + } + } else if (data instanceof Blob) { + if (data.isDetached()) { + attachBlob(data, function(attachedBlob) { + data.destroy(); + data = attachedBlob.uid; + send(); + }); + } else { + data = data.uid; + send(); + } + } else { + send(); + } + }, + + getResponse: function(responseType) { + var frs, blob, self = this.getRuntime(); + + blob = self.shimExec.call(this, 'XMLHttpRequest', 'getResponseAsBlob'); + + if (blob) { + blob = new File(self.uid, blob); + + if ('blob' === responseType) { + return blob; + } + + try { + frs = new FileReaderSync(); + + if (!!~Basic.inArray(responseType, ["", "text"])) { + return frs.readAsText(blob); + } else if ('json' === responseType && !!window.JSON) { + return JSON.parse(frs.readAsText(blob)); + } + } finally { + blob.destroy(); + } + } + return null; + }, + + abort: function(upload_complete_flag) { + var self = this.getRuntime(); + + self.shimExec.call(this, 'XMLHttpRequest', 'abort'); + + this.dispatchEvent('readystatechange'); + // this.dispatchEvent('progress'); + this.dispatchEvent('abort'); + + //if (!upload_complete_flag) { + // this.dispatchEvent('uploadprogress'); + //} + } + }; + + return (extensions.XMLHttpRequest = XMLHttpRequest); +}); + +// Included from: src/javascript/runtime/flash/runtime/Transporter.js + +/** + * Transporter.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/flash/runtime/Transporter +@private +*/ +define("moxie/runtime/flash/runtime/Transporter", [ + "moxie/runtime/flash/Runtime", + "moxie/file/Blob" +], function(extensions, Blob) { + + var Transporter = { + getAsBlob: function(type) { + var self = this.getRuntime() + , blob = self.shimExec.call(this, 'Transporter', 'getAsBlob', type) + ; + if (blob) { + return new Blob(self.uid, blob); + } + return null; + } + }; + + return (extensions.Transporter = Transporter); +}); + +// Included from: src/javascript/runtime/flash/image/Image.js + +/** + * Image.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/flash/image/Image +@private +*/ +define("moxie/runtime/flash/image/Image", [ + "moxie/runtime/flash/Runtime", + "moxie/core/utils/Basic", + "moxie/runtime/Transporter", + "moxie/file/Blob", + "moxie/file/FileReaderSync" +], function(extensions, Basic, Transporter, Blob, FileReaderSync) { + + var Image = { + loadFromBlob: function(blob) { + var comp = this, self = comp.getRuntime(); + + function exec(srcBlob) { + self.shimExec.call(comp, 'Image', 'loadFromBlob', srcBlob.uid); + comp = self = null; + } + + if (blob.isDetached()) { // binary string + var tr = new Transporter(); + tr.bind("TransportingComplete", function() { + exec(tr.result.getSource()); + }); + tr.transport(blob.getSource(), blob.type, { ruid: self.uid }); + } else { + exec(blob.getSource()); + } + }, + + loadFromImage: function(img) { + var self = this.getRuntime(); + return self.shimExec.call(this, 'Image', 'loadFromImage', img.uid); + }, + + getAsBlob: function(type, quality) { + var self = this.getRuntime() + , blob = self.shimExec.call(this, 'Image', 'getAsBlob', type, quality) + ; + if (blob) { + return new Blob(self.uid, blob); + } + return null; + }, + + getAsDataURL: function() { + var self = this.getRuntime() + , blob = self.Image.getAsBlob.apply(this, arguments) + , frs + ; + if (!blob) { + return null; + } + frs = new FileReaderSync(); + return frs.readAsDataURL(blob); + } + }; + + return (extensions.Image = Image); +}); + +// Included from: src/javascript/runtime/silverlight/Runtime.js + +/** + * RunTime.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/*global ActiveXObject:true */ + +/** +Defines constructor for Silverlight runtime. + +@class moxie/runtime/silverlight/Runtime +@private +*/ +define("moxie/runtime/silverlight/Runtime", [ + "moxie/core/utils/Basic", + "moxie/core/utils/Env", + "moxie/core/utils/Dom", + "moxie/core/Exceptions", + "moxie/runtime/Runtime" +], function(Basic, Env, Dom, x, Runtime) { + + var type = "silverlight", extensions = {}; + + function isInstalled(version) { + var isVersionSupported = false, control = null, actualVer, + actualVerArray, reqVerArray, requiredVersionPart, actualVersionPart, index = 0; + + try { + try { + control = new ActiveXObject('AgControl.AgControl'); + + if (control.IsVersionSupported(version)) { + isVersionSupported = true; + } + + control = null; + } catch (e) { + var plugin = navigator.plugins["Silverlight Plug-In"]; + + if (plugin) { + actualVer = plugin.description; + + if (actualVer === "1.0.30226.2") { + actualVer = "2.0.30226.2"; + } + + actualVerArray = actualVer.split("."); + + while (actualVerArray.length > 3) { + actualVerArray.pop(); + } + + while ( actualVerArray.length < 4) { + actualVerArray.push(0); + } + + reqVerArray = version.split("."); + + while (reqVerArray.length > 4) { + reqVerArray.pop(); + } + + do { + requiredVersionPart = parseInt(reqVerArray[index], 10); + actualVersionPart = parseInt(actualVerArray[index], 10); + index++; + } while (index < reqVerArray.length && requiredVersionPart === actualVersionPart); + + if (requiredVersionPart <= actualVersionPart && !isNaN(requiredVersionPart)) { + isVersionSupported = true; + } + } + } + } catch (e2) { + isVersionSupported = false; + } + + return isVersionSupported; + } + + /** + Constructor for the Silverlight Runtime + + @class SilverlightRuntime + @extends Runtime + */ + function SilverlightRuntime(options) { + var I = this, initTimer; + + options = Basic.extend({ xap_url: Env.xap_url }, options); + + Runtime.call(this, options, type, { + access_binary: Runtime.capTrue, + access_image_binary: Runtime.capTrue, + display_media: Runtime.capTrue, + do_cors: Runtime.capTrue, + drag_and_drop: false, + report_upload_progress: Runtime.capTrue, + resize_image: Runtime.capTrue, + return_response_headers: function(value) { + return value && I.mode === 'client'; + }, + return_response_type: function(responseType) { + if (responseType !== 'json') { + return true; + } else { + return !!window.JSON; + } + }, + return_status_code: function(code) { + return I.mode === 'client' || !Basic.arrayDiff(code, [200, 404]); + }, + select_file: Runtime.capTrue, + select_multiple: Runtime.capTrue, + send_binary_string: Runtime.capTrue, + send_browser_cookies: function(value) { + return value && I.mode === 'browser'; + }, + send_custom_headers: function(value) { + return value && I.mode === 'client'; + }, + send_multipart: Runtime.capTrue, + slice_blob: Runtime.capTrue, + stream_upload: true, + summon_file_dialog: false, + upload_filesize: Runtime.capTrue, + use_http_method: function(methods) { + return I.mode === 'client' || !Basic.arrayDiff(methods, ['GET', 'POST']); + } + }, { + // capabilities that require specific mode + return_response_headers: function(value) { + return value ? 'client' : 'browser'; + }, + return_status_code: function(code) { + return Basic.arrayDiff(code, [200, 404]) ? 'client' : ['client', 'browser']; + }, + send_browser_cookies: function(value) { + return value ? 'browser' : 'client'; + }, + send_custom_headers: function(value) { + return value ? 'client' : 'browser'; + }, + use_http_method: function(methods) { + return Basic.arrayDiff(methods, ['GET', 'POST']) ? 'client' : ['client', 'browser']; + } + }); + + + // minimal requirement + if (!isInstalled('2.0.31005.0') || Env.browser === 'Opera') { + this.mode = false; + } + + + Basic.extend(this, { + getShim: function() { + return Dom.get(this.uid).content.Moxie; + }, + + shimExec: function(component, action) { + var args = [].slice.call(arguments, 2); + return I.getShim().exec(this.uid, component, action, args); + }, + + init : function() { + var container; + + container = this.getShimContainer(); + + container.innerHTML = '' + + '' + + '' + + '' + + '' + + '' + + ''; + + // Init is dispatched by the shim + initTimer = setTimeout(function() { + if (I && !I.initialized) { // runtime might be already destroyed by this moment + I.trigger("Error", new x.RuntimeError(x.RuntimeError.NOT_INIT_ERR)); + } + }, Env.OS !== 'Windows'? 10000 : 5000); // give it more time to initialize in non Windows OS (like Mac) + }, + + destroy: (function(destroy) { // extend default destroy method + return function() { + destroy.call(I); + clearTimeout(initTimer); // initialization check might be still onwait + options = initTimer = destroy = I = null; + }; + }(this.destroy)) + + }, extensions); + } + + Runtime.addConstructor(type, SilverlightRuntime); + + return extensions; +}); + +// Included from: src/javascript/runtime/silverlight/file/Blob.js + +/** + * Blob.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/silverlight/file/Blob +@private +*/ +define("moxie/runtime/silverlight/file/Blob", [ + "moxie/runtime/silverlight/Runtime", + "moxie/core/utils/Basic", + "moxie/runtime/flash/file/Blob" +], function(extensions, Basic, Blob) { + return (extensions.Blob = Basic.extend({}, Blob)); +}); + +// Included from: src/javascript/runtime/silverlight/file/FileInput.js + +/** + * FileInput.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/silverlight/file/FileInput +@private +*/ +define("moxie/runtime/silverlight/file/FileInput", [ + "moxie/runtime/silverlight/Runtime" +], function(extensions) { + + var FileInput = { + init: function(options) { + + function toFilters(accept) { + var filter = ''; + for (var i = 0; i < accept.length; i++) { + filter += (filter !== '' ? '|' : '') + accept[i].title + " | *." + accept[i].extensions.replace(/,/g, ';*.'); + } + return filter; + } + + this.getRuntime().shimExec.call(this, 'FileInput', 'init', toFilters(options.accept), options.name, options.multiple); + this.trigger('ready'); + } + }; + + return (extensions.FileInput = FileInput); +}); + +// Included from: src/javascript/runtime/silverlight/file/FileDrop.js + +/** + * FileDrop.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/silverlight/file/FileDrop +@private +*/ +define("moxie/runtime/silverlight/file/FileDrop", [ + "moxie/runtime/silverlight/Runtime", + "moxie/core/utils/Dom", + "moxie/core/utils/Events" +], function(extensions, Dom, Events) { + + // not exactly useful, since works only in safari (...crickets...) + var FileDrop = { + init: function() { + var comp = this, self = comp.getRuntime(), dropZone; + + dropZone = self.getShimContainer(); + + Events.addEvent(dropZone, 'dragover', function(e) { + e.preventDefault(); + e.stopPropagation(); + e.dataTransfer.dropEffect = 'copy'; + }, comp.uid); + + Events.addEvent(dropZone, 'dragenter', function(e) { + e.preventDefault(); + var flag = Dom.get(self.uid).dragEnter(e); + // If handled, then stop propagation of event in DOM + if (flag) { + e.stopPropagation(); + } + }, comp.uid); + + Events.addEvent(dropZone, 'drop', function(e) { + e.preventDefault(); + var flag = Dom.get(self.uid).dragDrop(e); + // If handled, then stop propagation of event in DOM + if (flag) { + e.stopPropagation(); + } + }, comp.uid); + + return self.shimExec.call(this, 'FileDrop', 'init'); + } + }; + + return (extensions.FileDrop = FileDrop); +}); + +// Included from: src/javascript/runtime/silverlight/file/FileReader.js + +/** + * FileReader.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/silverlight/file/FileReader +@private +*/ +define("moxie/runtime/silverlight/file/FileReader", [ + "moxie/runtime/silverlight/Runtime", + "moxie/core/utils/Basic", + "moxie/runtime/flash/file/FileReader" +], function(extensions, Basic, FileReader) { + return (extensions.FileReader = Basic.extend({}, FileReader)); +}); + +// Included from: src/javascript/runtime/silverlight/file/FileReaderSync.js + +/** + * FileReaderSync.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/silverlight/file/FileReaderSync +@private +*/ +define("moxie/runtime/silverlight/file/FileReaderSync", [ + "moxie/runtime/silverlight/Runtime", + "moxie/core/utils/Basic", + "moxie/runtime/flash/file/FileReaderSync" +], function(extensions, Basic, FileReaderSync) { + return (extensions.FileReaderSync = Basic.extend({}, FileReaderSync)); +}); + +// Included from: src/javascript/runtime/silverlight/xhr/XMLHttpRequest.js + +/** + * XMLHttpRequest.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/silverlight/xhr/XMLHttpRequest +@private +*/ +define("moxie/runtime/silverlight/xhr/XMLHttpRequest", [ + "moxie/runtime/silverlight/Runtime", + "moxie/core/utils/Basic", + "moxie/runtime/flash/xhr/XMLHttpRequest" +], function(extensions, Basic, XMLHttpRequest) { + return (extensions.XMLHttpRequest = Basic.extend({}, XMLHttpRequest)); +}); + +// Included from: src/javascript/runtime/silverlight/runtime/Transporter.js + +/** + * Transporter.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/silverlight/runtime/Transporter +@private +*/ +define("moxie/runtime/silverlight/runtime/Transporter", [ + "moxie/runtime/silverlight/Runtime", + "moxie/core/utils/Basic", + "moxie/runtime/flash/runtime/Transporter" +], function(extensions, Basic, Transporter) { + return (extensions.Transporter = Basic.extend({}, Transporter)); +}); + +// Included from: src/javascript/runtime/silverlight/image/Image.js + +/** + * Image.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/silverlight/image/Image +@private +*/ +define("moxie/runtime/silverlight/image/Image", [ + "moxie/runtime/silverlight/Runtime", + "moxie/core/utils/Basic", + "moxie/runtime/flash/image/Image" +], function(extensions, Basic, Image) { + return (extensions.Image = Basic.extend({}, Image, { + + getInfo: function() { + var self = this.getRuntime() + , grps = ['tiff', 'exif', 'gps'] + , info = { meta: {} } + , rawInfo = self.shimExec.call(this, 'Image', 'getInfo') + ; + + if (rawInfo.meta) { + Basic.each(grps, function(grp) { + var meta = rawInfo.meta[grp] + , tag + , i + , length + , value + ; + if (meta && meta.keys) { + info.meta[grp] = {}; + for (i = 0, length = meta.keys.length; i < length; i++) { + tag = meta.keys[i]; + value = meta[tag]; + if (value) { + // convert numbers + if (/^(\d|[1-9]\d+)$/.test(value)) { // integer (make sure doesn't start with zero) + value = parseInt(value, 10); + } else if (/^\d*\.\d+$/.test(value)) { // double + value = parseFloat(value); + } + info.meta[grp][tag] = value; + } + } + } + }); + } + + info.width = parseInt(rawInfo.width, 10); + info.height = parseInt(rawInfo.height, 10); + info.size = parseInt(rawInfo.size, 10); + info.type = rawInfo.type; + info.name = rawInfo.name; + + return info; + } + })); +}); + +// Included from: src/javascript/runtime/html4/Runtime.js + +/** + * Runtime.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/*global File:true */ + +/** +Defines constructor for HTML4 runtime. + +@class moxie/runtime/html4/Runtime +@private +*/ +define("moxie/runtime/html4/Runtime", [ + "moxie/core/utils/Basic", + "moxie/core/Exceptions", + "moxie/runtime/Runtime", + "moxie/core/utils/Env" +], function(Basic, x, Runtime, Env) { + + var type = 'html4', extensions = {}; + + function Html4Runtime(options) { + var I = this + , Test = Runtime.capTest + , True = Runtime.capTrue + ; + + Runtime.call(this, options, type, { + access_binary: Test(window.FileReader || window.File && File.getAsDataURL), + access_image_binary: false, + display_media: Test(extensions.Image && (Env.can('create_canvas') || Env.can('use_data_uri_over32kb'))), + do_cors: false, + drag_and_drop: false, + filter_by_extension: Test(function() { // if you know how to feature-detect this, please suggest + return (Env.browser === 'Chrome' && Env.version >= 28) || (Env.browser === 'IE' && Env.version >= 10); + }()), + resize_image: function() { + return extensions.Image && I.can('access_binary') && Env.can('create_canvas'); + }, + report_upload_progress: false, + return_response_headers: false, + return_response_type: function(responseType) { + if (responseType === 'json' && !!window.JSON) { + return true; + } + return !!~Basic.inArray(responseType, ['text', 'document', '']); + }, + return_status_code: function(code) { + return !Basic.arrayDiff(code, [200, 404]); + }, + select_file: function() { + return Env.can('use_fileinput'); + }, + select_multiple: false, + send_binary_string: false, + send_custom_headers: false, + send_multipart: true, + slice_blob: false, + stream_upload: function() { + return I.can('select_file'); + }, + summon_file_dialog: Test(function() { // yeah... some dirty sniffing here... + return (Env.browser === 'Firefox' && Env.version >= 4) || + (Env.browser === 'Opera' && Env.version >= 12) || + !!~Basic.inArray(Env.browser, ['Chrome', 'Safari']); + }()), + upload_filesize: True, + use_http_method: function(methods) { + return !Basic.arrayDiff(methods, ['GET', 'POST']); + } + }); + + + Basic.extend(this, { + init : function() { + this.trigger("Init"); + }, + + destroy: (function(destroy) { // extend default destroy method + return function() { + destroy.call(I); + destroy = I = null; + }; + }(this.destroy)) + }); + + Basic.extend(this.getShim(), extensions); + } + + Runtime.addConstructor(type, Html4Runtime); + + return extensions; +}); + +// Included from: src/javascript/runtime/html4/file/FileInput.js + +/** + * FileInput.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html4/file/FileInput +@private +*/ +define("moxie/runtime/html4/file/FileInput", [ + "moxie/runtime/html4/Runtime", + "moxie/core/utils/Basic", + "moxie/core/utils/Dom", + "moxie/core/utils/Events", + "moxie/core/utils/Mime", + "moxie/core/utils/Env" +], function(extensions, Basic, Dom, Events, Mime, Env) { + + function FileInput() { + var _uid, _files = [], _mimes = [], _options; + + function addInput() { + var comp = this, I = comp.getRuntime(), shimContainer, browseButton, currForm, form, input, uid; + + uid = Basic.guid('uid_'); + + shimContainer = I.getShimContainer(); // we get new ref everytime to avoid memory leaks in IE + + if (_uid) { // move previous form out of the view + currForm = Dom.get(_uid + '_form'); + if (currForm) { + Basic.extend(currForm.style, { top: '100%' }); + } + } + + // build form in DOM, since innerHTML version not able to submit file for some reason + form = document.createElement('form'); + form.setAttribute('id', uid + '_form'); + form.setAttribute('method', 'post'); + form.setAttribute('enctype', 'multipart/form-data'); + form.setAttribute('encoding', 'multipart/form-data'); + + Basic.extend(form.style, { + overflow: 'hidden', + position: 'absolute', + top: 0, + left: 0, + width: '100%', + height: '100%' + }); + + input = document.createElement('input'); + input.setAttribute('id', uid); + input.setAttribute('type', 'file'); + input.setAttribute('name', _options.name || 'Filedata'); + input.setAttribute('accept', _mimes.join(',')); + + Basic.extend(input.style, { + fontSize: '999px', + opacity: 0 + }); + + form.appendChild(input); + shimContainer.appendChild(form); + + // prepare file input to be placed underneath the browse_button element + Basic.extend(input.style, { + position: 'absolute', + top: 0, + left: 0, + width: '100%', + height: '100%' + }); + + if (Env.browser === 'IE' && Env.version < 10) { + Basic.extend(input.style, { + filter : "progid:DXImageTransform.Microsoft.Alpha(opacity=0)" + }); + } + + input.onchange = function() { // there should be only one handler for this + var file; + + if (!this.value) { + return; + } + + if (this.files) { + file = this.files[0]; + } else { + file = { + name: this.value + }; + } + + _files = [file]; + + this.onchange = function() {}; // clear event handler + addInput.call(comp); + + // after file is initialized as o.File, we need to update form and input ids + comp.bind('change', function onChange() { + var input = Dom.get(uid), form = Dom.get(uid + '_form'), file; + + comp.unbind('change', onChange); + + if (comp.files.length && input && form) { + file = comp.files[0]; + + input.setAttribute('id', file.uid); + form.setAttribute('id', file.uid + '_form'); + + // set upload target + form.setAttribute('target', file.uid + '_iframe'); + } + input = form = null; + }, 998); + + input = form = null; + comp.trigger('change'); + }; + + + // route click event to the input + if (I.can('summon_file_dialog')) { + browseButton = Dom.get(_options.browse_button); + Events.removeEvent(browseButton, 'click', comp.uid); + Events.addEvent(browseButton, 'click', function(e) { + if (input && !input.disabled) { // for some reason FF (up to 8.0.1 so far) lets to click disabled input[type=file] + input.click(); + } + e.preventDefault(); + }, comp.uid); + } + + _uid = uid; + + shimContainer = currForm = browseButton = null; + } + + Basic.extend(this, { + init: function(options) { + var comp = this, I = comp.getRuntime(), shimContainer; + + // figure out accept string + _options = options; + _mimes = options.accept.mimes || Mime.extList2mimes(options.accept, I.can('filter_by_extension')); + + shimContainer = I.getShimContainer(); + + (function() { + var browseButton, zIndex, top; + + browseButton = Dom.get(options.browse_button); + + // Route click event to the input[type=file] element for browsers that support such behavior + if (I.can('summon_file_dialog')) { + if (Dom.getStyle(browseButton, 'position') === 'static') { + browseButton.style.position = 'relative'; + } + + zIndex = parseInt(Dom.getStyle(browseButton, 'z-index'), 10) || 1; + + browseButton.style.zIndex = zIndex; + shimContainer.style.zIndex = zIndex - 1; + } + + /* Since we have to place input[type=file] on top of the browse_button for some browsers, + browse_button loses interactivity, so we restore it here */ + top = I.can('summon_file_dialog') ? browseButton : shimContainer; + + Events.addEvent(top, 'mouseover', function() { + comp.trigger('mouseenter'); + }, comp.uid); + + Events.addEvent(top, 'mouseout', function() { + comp.trigger('mouseleave'); + }, comp.uid); + + Events.addEvent(top, 'mousedown', function() { + comp.trigger('mousedown'); + }, comp.uid); + + Events.addEvent(Dom.get(options.container), 'mouseup', function() { + comp.trigger('mouseup'); + }, comp.uid); + + browseButton = null; + }()); + + addInput.call(this); + + shimContainer = null; + + // trigger ready event asynchronously + comp.trigger({ + type: 'ready', + async: true + }); + }, + + getFiles: function() { + return _files; + }, + + disable: function(state) { + var input; + + if ((input = Dom.get(_uid))) { + input.disabled = !!state; + } + }, + + destroy: function() { + var I = this.getRuntime() + , shim = I.getShim() + , shimContainer = I.getShimContainer() + ; + + Events.removeAllEvents(shimContainer, this.uid); + Events.removeAllEvents(_options && Dom.get(_options.container), this.uid); + Events.removeAllEvents(_options && Dom.get(_options.browse_button), this.uid); + + if (shimContainer) { + shimContainer.innerHTML = ''; + } + + shim.removeInstance(this.uid); + + _uid = _files = _mimes = _options = shimContainer = shim = null; + } + }); + } + + return (extensions.FileInput = FileInput); +}); + +// Included from: src/javascript/runtime/html4/file/FileReader.js + +/** + * FileReader.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html4/file/FileReader +@private +*/ +define("moxie/runtime/html4/file/FileReader", [ + "moxie/runtime/html4/Runtime", + "moxie/runtime/html5/file/FileReader" +], function(extensions, FileReader) { + return (extensions.FileReader = FileReader); +}); + +// Included from: src/javascript/runtime/html4/xhr/XMLHttpRequest.js + +/** + * XMLHttpRequest.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html4/xhr/XMLHttpRequest +@private +*/ +define("moxie/runtime/html4/xhr/XMLHttpRequest", [ + "moxie/runtime/html4/Runtime", + "moxie/core/utils/Basic", + "moxie/core/utils/Dom", + "moxie/core/utils/Url", + "moxie/core/Exceptions", + "moxie/core/utils/Events", + "moxie/file/Blob", + "moxie/xhr/FormData" +], function(extensions, Basic, Dom, Url, x, Events, Blob, FormData) { + + function XMLHttpRequest() { + var _status, _response, _iframe; + + function cleanup(cb) { + var target = this, uid, form, inputs, i, hasFile = false; + + if (!_iframe) { + return; + } + + uid = _iframe.id.replace(/_iframe$/, ''); + + form = Dom.get(uid + '_form'); + if (form) { + inputs = form.getElementsByTagName('input'); + i = inputs.length; + + while (i--) { + switch (inputs[i].getAttribute('type')) { + case 'hidden': + inputs[i].parentNode.removeChild(inputs[i]); + break; + case 'file': + hasFile = true; // flag the case for later + break; + } + } + inputs = []; + + if (!hasFile) { // we need to keep the form for sake of possible retries + form.parentNode.removeChild(form); + } + form = null; + } + + // without timeout, request is marked as canceled (in console) + setTimeout(function() { + Events.removeEvent(_iframe, 'load', target.uid); + if (_iframe.parentNode) { // #382 + _iframe.parentNode.removeChild(_iframe); + } + + // check if shim container has any other children, if - not, remove it as well + var shimContainer = target.getRuntime().getShimContainer(); + if (!shimContainer.children.length) { + shimContainer.parentNode.removeChild(shimContainer); + } + + shimContainer = _iframe = null; + cb(); + }, 1); + } + + Basic.extend(this, { + send: function(meta, data) { + var target = this, I = target.getRuntime(), uid, form, input, blob; + + _status = _response = null; + + function createIframe() { + var container = I.getShimContainer() || document.body + , temp = document.createElement('div') + ; + + // IE 6 won't be able to set the name using setAttribute or iframe.name + temp.innerHTML = ''; + _iframe = temp.firstChild; + container.appendChild(_iframe); + + /* _iframe.onreadystatechange = function() { + console.info(_iframe.readyState); + };*/ + + Events.addEvent(_iframe, 'load', function() { // _iframe.onload doesn't work in IE lte 8 + var el; + + try { + el = _iframe.contentWindow.document || _iframe.contentDocument || window.frames[_iframe.id].document; + + // try to detect some standard error pages + if (/^4(0[0-9]|1[0-7]|2[2346])\s/.test(el.title)) { // test if title starts with 4xx HTTP error + _status = el.title.replace(/^(\d+).*$/, '$1'); + } else { + _status = 200; + // get result + _response = Basic.trim(el.body.innerHTML); + + // we need to fire these at least once + target.trigger({ + type: 'progress', + loaded: _response.length, + total: _response.length + }); + + if (blob) { // if we were uploading a file + target.trigger({ + type: 'uploadprogress', + loaded: blob.size || 1025, + total: blob.size || 1025 + }); + } + } + } catch (ex) { + if (Url.hasSameOrigin(meta.url)) { + // if response is sent with error code, iframe in IE gets redirected to res://ieframe.dll/http_x.htm + // which obviously results to cross domain error (wtf?) + _status = 404; + } else { + cleanup.call(target, function() { + target.trigger('error'); + }); + return; + } + } + + cleanup.call(target, function() { + target.trigger('load'); + }); + }, target.uid); + } // end createIframe + + // prepare data to be sent and convert if required + if (data instanceof FormData && data.hasBlob()) { + blob = data.getBlob(); + uid = blob.uid; + input = Dom.get(uid); + form = Dom.get(uid + '_form'); + if (!form) { + throw new x.DOMException(x.DOMException.NOT_FOUND_ERR); + } + } else { + uid = Basic.guid('uid_'); + + form = document.createElement('form'); + form.setAttribute('id', uid + '_form'); + form.setAttribute('method', meta.method); + form.setAttribute('enctype', 'multipart/form-data'); + form.setAttribute('encoding', 'multipart/form-data'); + form.setAttribute('target', uid + '_iframe'); + + I.getShimContainer().appendChild(form); + } + + if (data instanceof FormData) { + data.each(function(value, name) { + if (value instanceof Blob) { + if (input) { + input.setAttribute('name', name); + } + } else { + var hidden = document.createElement('input'); + + Basic.extend(hidden, { + type : 'hidden', + name : name, + value : value + }); + + // make sure that input[type="file"], if it's there, comes last + if (input) { + form.insertBefore(hidden, input); + } else { + form.appendChild(hidden); + } + } + }); + } + + // set destination url + form.setAttribute("action", meta.url); + + createIframe(); + form.submit(); + target.trigger('loadstart'); + }, + + getStatus: function() { + return _status; + }, + + getResponse: function(responseType) { + if ('json' === responseType) { + // strip off
      ..
      tags that might be enclosing the response + if (Basic.typeOf(_response) === 'string' && !!window.JSON) { + try { + return JSON.parse(_response.replace(/^\s*]*>/, '').replace(/<\/pre>\s*$/, '')); + } catch (ex) { + return null; + } + } + } else if ('document' === responseType) { + + } + return _response; + }, + + abort: function() { + var target = this; + + if (_iframe && _iframe.contentWindow) { + if (_iframe.contentWindow.stop) { // FireFox/Safari/Chrome + _iframe.contentWindow.stop(); + } else if (_iframe.contentWindow.document.execCommand) { // IE + _iframe.contentWindow.document.execCommand('Stop'); + } else { + _iframe.src = "about:blank"; + } + } + + cleanup.call(this, function() { + // target.dispatchEvent('readystatechange'); + target.dispatchEvent('abort'); + }); + } + }); + } + + return (extensions.XMLHttpRequest = XMLHttpRequest); +}); + +// Included from: src/javascript/runtime/html4/image/Image.js + +/** + * Image.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html4/image/Image +@private +*/ +define("moxie/runtime/html4/image/Image", [ + "moxie/runtime/html4/Runtime", + "moxie/runtime/html5/image/Image" +], function(extensions, Image) { + return (extensions.Image = Image); +}); + +expose(["moxie/core/utils/Basic","moxie/core/I18n","moxie/core/utils/Mime","moxie/core/utils/Env","moxie/core/utils/Dom","moxie/core/Exceptions","moxie/core/EventTarget","moxie/core/utils/Encode","moxie/runtime/Runtime","moxie/runtime/RuntimeClient","moxie/file/Blob","moxie/file/File","moxie/file/FileInput","moxie/file/FileDrop","moxie/runtime/RuntimeTarget","moxie/file/FileReader","moxie/core/utils/Url","moxie/file/FileReaderSync","moxie/xhr/FormData","moxie/xhr/XMLHttpRequest","moxie/runtime/Transporter","moxie/image/Image","moxie/core/utils/Events"]); +})(this);/** + * o.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/*global moxie:true */ + +/** +Globally exposed namespace with the most frequently used public classes and handy methods. + +@class o +@static +@private +*/ +(function(exports) { + "use strict"; + + var o = {}, inArray = exports.moxie.core.utils.Basic.inArray; + + // directly add some public classes + // (we do it dynamically here, since for custom builds we cannot know beforehand what modules were included) + (function addAlias(ns) { + var name, itemType; + for (name in ns) { + itemType = typeof(ns[name]); + if (itemType === 'object' && !~inArray(name, ['Exceptions', 'Env', 'Mime'])) { + addAlias(ns[name]); + } else if (itemType === 'function') { + o[name] = ns[name]; + } + } + })(exports.moxie); + + // add some manually + o.Env = exports.moxie.core.utils.Env; + o.Mime = exports.moxie.core.utils.Mime; + o.Exceptions = exports.moxie.core.Exceptions; + + // expose globally + exports.mOxie = o; + if (!exports.o) { + exports.o = o; + } + return o; +})(this); diff --git a/themes/default/js/plugins/plupload/moxie.min.js b/themes/default/js/plugins/plupload/moxie.min.js new file mode 100644 index 000000000..8d94a0dde --- /dev/null +++ b/themes/default/js/plugins/plupload/moxie.min.js @@ -0,0 +1,15 @@ +/** + * mOxie - multi-runtime File API & XMLHttpRequest L2 Polyfill + * v1.2.1 + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + * + * Date: 2014-05-14 + */ +!function(e,t){"use strict";function n(e,t){for(var n,i=[],r=0;r0&&n(o,function(n,o){n!==r&&(e(i[o])===e(n)&&~a(e(n),["array","object"])?t(i[o],n):i[o]=n)})}),i},n=function(e,t){var n,i,r,o;if(e){try{n=e.length}catch(a){n=o}if(n===o){for(i in e)if(e.hasOwnProperty(i)&&t(e[i],i)===!1)return}else for(r=0;n>r;r++)if(t(e[r],r)===!1)return}},i=function(t){var n;if(!t||"object"!==e(t))return!0;for(n in t)return!1;return!0},r=function(t,n){function i(r){"function"===e(t[r])&&t[r](function(e){++rn;n++)if(t[n]===e)return n}return-1},s=function(t,n){var i=[];"array"!==e(t)&&(t=[t]),"array"!==e(n)&&(n=[n]);for(var r in t)-1===a(t[r],n)&&i.push(t[r]);return i.length?i:!1},u=function(e,t){var i=[];return n(e,function(e){-1!==a(e,t)&&i.push(e)}),i.length?i:null},c=function(e){var t,n=[];for(t=0;ti;i++)n+=Math.floor(65535*Math.random()).toString(32);return(t||"o_")+n+(e++).toString(32)}}(),d=function(e){return e?String.prototype.trim?String.prototype.trim.call(e):e.toString().replace(/^\s*/,"").replace(/\s*$/,""):e},f=function(e){if("string"!=typeof e)return e;var t={t:1099511627776,g:1073741824,m:1048576,k:1024},n;return e=/^([0-9]+)([mgk]?)$/.exec(e.toLowerCase().replace(/[^0-9mkg]/g,"")),n=e[2],e=+e[1],t.hasOwnProperty(n)&&(e*=t[n]),e};return{guid:l,typeOf:e,extend:t,each:n,isEmptyObj:i,inSeries:r,inParallel:o,inArray:a,arrayDiff:s,arrayIntersect:u,toArray:c,trim:d,parseSizeStr:f}}),i(c,[u],function(e){var t={};return{addI18n:function(n){return e.extend(t,n)},translate:function(e){return t[e]||e},_:function(e){return this.translate(e)},sprintf:function(t){var n=[].slice.call(arguments,1);return t.replace(/%[a-z]/g,function(){var t=n.shift();return"undefined"!==e.typeOf(t)?t:""})}}}),i(l,[u,c],function(e,t){var n="application/msword,doc dot,application/pdf,pdf,application/pgp-signature,pgp,application/postscript,ps ai eps,application/rtf,rtf,application/vnd.ms-excel,xls xlb,application/vnd.ms-powerpoint,ppt pps pot,application/zip,zip,application/x-shockwave-flash,swf swfl,application/vnd.openxmlformats-officedocument.wordprocessingml.document,docx,application/vnd.openxmlformats-officedocument.wordprocessingml.template,dotx,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,xlsx,application/vnd.openxmlformats-officedocument.presentationml.presentation,pptx,application/vnd.openxmlformats-officedocument.presentationml.template,potx,application/vnd.openxmlformats-officedocument.presentationml.slideshow,ppsx,application/x-javascript,js,application/json,json,audio/mpeg,mp3 mpga mpega mp2,audio/x-wav,wav,audio/x-m4a,m4a,audio/ogg,oga ogg,audio/aiff,aiff aif,audio/flac,flac,audio/aac,aac,audio/ac3,ac3,audio/x-ms-wma,wma,image/bmp,bmp,image/gif,gif,image/jpeg,jpg jpeg jpe,image/photoshop,psd,image/png,png,image/svg+xml,svg svgz,image/tiff,tiff tif,text/plain,asc txt text diff log,text/html,htm html xhtml,text/css,css,text/csv,csv,text/rtf,rtf,video/mpeg,mpeg mpg mpe m2v,video/quicktime,qt mov,video/mp4,mp4,video/x-m4v,m4v,video/x-flv,flv,video/x-ms-wmv,wmv,video/avi,avi,video/webm,webm,video/3gpp,3gpp 3gp,video/3gpp2,3g2,video/vnd.rn-realvideo,rv,video/ogg,ogv,video/x-matroska,mkv,application/vnd.oasis.opendocument.formula-template,otf,application/octet-stream,exe",i={mimes:{},extensions:{},addMimeType:function(e){var t=e.split(/,/),n,i,r;for(n=0;ni;i++)if(e[i]!=t[i]){if(e[i]=u(e[i]),t[i]=u(t[i]),e[i]t[i]){o=1;break}}if(!n)return o;switch(n){case">":case"gt":return o>0;case">=":case"ge":return o>=0;case"<=":case"le":return 0>=o;case"==":case"=":case"eq":return 0===o;case"<>":case"!=":case"ne":return 0!==o;case"":case"<":case"lt":return 0>o;default:return null}}var n=function(e){var t="",n="?",i="function",r="undefined",o="object",a="major",s="model",u="name",c="type",l="vendor",d="version",f="architecture",h="console",p="mobile",m="tablet",g={has:function(e,t){return-1!==t.toLowerCase().indexOf(e.toLowerCase())},lowerize:function(e){return e.toLowerCase()}},v={rgx:function(){for(var t,n=0,a,s,u,c,l,d,f=arguments;n0?2==c.length?t[c[0]]=typeof c[1]==i?c[1].call(this,d):c[1]:3==c.length?t[c[0]]=typeof c[1]!==i||c[1].exec&&c[1].test?d?d.replace(c[1],c[2]):e:d?c[1].call(this,d,c[2]):e:4==c.length&&(t[c[0]]=d?c[3].call(this,d.replace(c[1],c[2])):e):t[c]=d?d:e;break}if(l)break}return t},str:function(t,i){for(var r in i)if(typeof i[r]===o&&i[r].length>0){for(var a=0;a=9)},use_data_uri_of:function(e){return t.use_data_uri&&33e3>e||t.use_data_uri_over32kb()},use_fileinput:function(){var e=document.createElement("input");return e.setAttribute("type","file"),!e.disabled}};return function(n){var i=[].slice.call(arguments);return i.shift(),"function"===e.typeOf(t[n])?t[n].apply(this,i):!!t[n]}}(),r={can:i,browser:n.browser.name,version:parseFloat(n.browser.major),os:n.os.name,osVersion:n.os.version,verComp:t,swf_url:"../flash/Moxie.swf",xap_url:"../silverlight/Moxie.xap",global_event_dispatcher:"moxie.core.EventTarget.instance.dispatchEvent"};return r.OS=r.os,r}),i(f,[d],function(e){var t=function(e){return"string"!=typeof e?e:document.getElementById(e)},n=function(e,t){if(!e.className)return!1;var n=new RegExp("(^|\\s+)"+t+"(\\s+|$)");return n.test(e.className)},i=function(e,t){n(e,t)||(e.className=e.className?e.className.replace(/\s+$/,"")+" "+t:t)},r=function(e,t){if(e.className){var n=new RegExp("(^|\\s+)"+t+"(\\s+|$)");e.className=e.className.replace(n,function(e,t,n){return" "===t&&" "===n?" ":""})}},o=function(e,t){return e.currentStyle?e.currentStyle[t]:window.getComputedStyle?window.getComputedStyle(e,null)[t]:void 0},a=function(t,n){function i(e){var t,n,i=0,r=0;return e&&(n=e.getBoundingClientRect(),t="CSS1Compat"===s.compatMode?s.documentElement:s.body,i=n.left+t.scrollLeft,r=n.top+t.scrollTop),{x:i,y:r}}var r=0,o=0,a,s=document,u,c;if(t=t,n=n||s.body,t&&t.getBoundingClientRect&&"IE"===e.browser&&(!s.documentMode||s.documentMode<8))return u=i(t),c=i(n),{x:u.x-c.x,y:u.y-c.y};for(a=t;a&&a!=n&&a.nodeType;)r+=a.offsetLeft||0,o+=a.offsetTop||0,a=a.offsetParent;for(a=t.parentNode;a&&a!=n&&a.nodeType;)r-=a.scrollLeft||0,o-=a.scrollTop||0,a=a.parentNode;return{x:r,y:o}},s=function(e){return{w:e.offsetWidth||e.clientWidth,h:e.offsetHeight||e.clientHeight}};return{get:t,hasClass:n,addClass:i,removeClass:r,getStyle:o,getPos:a,getSize:s}}),i(h,[u],function(e){function t(e,t){var n;for(n in e)if(e[n]===t)return n;return null}return{RuntimeError:function(){function n(e){this.code=e,this.name=t(i,e),this.message=this.name+": RuntimeError "+this.code}var i={NOT_INIT_ERR:1,NOT_SUPPORTED_ERR:9,JS_ERR:4};return e.extend(n,i),n.prototype=Error.prototype,n}(),OperationNotAllowedException:function(){function t(e){this.code=e,this.name="OperationNotAllowedException"}return e.extend(t,{NOT_ALLOWED_ERR:1}),t.prototype=Error.prototype,t}(),ImageError:function(){function n(e){this.code=e,this.name=t(i,e),this.message=this.name+": ImageError "+this.code}var i={WRONG_FORMAT:1,MAX_RESOLUTION_ERR:2};return e.extend(n,i),n.prototype=Error.prototype,n}(),FileException:function(){function n(e){this.code=e,this.name=t(i,e),this.message=this.name+": FileException "+this.code}var i={NOT_FOUND_ERR:1,SECURITY_ERR:2,ABORT_ERR:3,NOT_READABLE_ERR:4,ENCODING_ERR:5,NO_MODIFICATION_ALLOWED_ERR:6,INVALID_STATE_ERR:7,SYNTAX_ERR:8};return e.extend(n,i),n.prototype=Error.prototype,n}(),DOMException:function(){function n(e){this.code=e,this.name=t(i,e),this.message=this.name+": DOMException "+this.code}var i={INDEX_SIZE_ERR:1,DOMSTRING_SIZE_ERR:2,HIERARCHY_REQUEST_ERR:3,WRONG_DOCUMENT_ERR:4,INVALID_CHARACTER_ERR:5,NO_DATA_ALLOWED_ERR:6,NO_MODIFICATION_ALLOWED_ERR:7,NOT_FOUND_ERR:8,NOT_SUPPORTED_ERR:9,INUSE_ATTRIBUTE_ERR:10,INVALID_STATE_ERR:11,SYNTAX_ERR:12,INVALID_MODIFICATION_ERR:13,NAMESPACE_ERR:14,INVALID_ACCESS_ERR:15,VALIDATION_ERR:16,TYPE_MISMATCH_ERR:17,SECURITY_ERR:18,NETWORK_ERR:19,ABORT_ERR:20,URL_MISMATCH_ERR:21,QUOTA_EXCEEDED_ERR:22,TIMEOUT_ERR:23,INVALID_NODE_TYPE_ERR:24,DATA_CLONE_ERR:25};return e.extend(n,i),n.prototype=Error.prototype,n}(),EventException:function(){function t(e){this.code=e,this.name="EventException"}return e.extend(t,{UNSPECIFIED_EVENT_TYPE_ERR:0}),t.prototype=Error.prototype,t}()}}),i(p,[h,u],function(e,t){function n(){var n={};t.extend(this,{uid:null,init:function(){this.uid||(this.uid=t.guid("uid_"))},addEventListener:function(e,i,r,o){var a=this,s;return e=t.trim(e),/\s/.test(e)?void t.each(e.split(/\s+/),function(e){a.addEventListener(e,i,r,o)}):(e=e.toLowerCase(),r=parseInt(r,10)||0,s=n[this.uid]&&n[this.uid][e]||[],s.push({fn:i,priority:r,scope:o||this}),n[this.uid]||(n[this.uid]={}),void(n[this.uid][e]=s))},hasEventListener:function(e){return e?!(!n[this.uid]||!n[this.uid][e]):!!n[this.uid]},removeEventListener:function(e,i){e=e.toLowerCase();var r=n[this.uid]&&n[this.uid][e],o;if(r){if(i){for(o=r.length-1;o>=0;o--)if(r[o].fn===i){r.splice(o,1);break}}else r=[];r.length||(delete n[this.uid][e],t.isEmptyObj(n[this.uid])&&delete n[this.uid])}},removeAllEventListeners:function(){n[this.uid]&&delete n[this.uid]},dispatchEvent:function(i){var r,o,a,s,u={},c=!0,l;if("string"!==t.typeOf(i)){if(s=i,"string"!==t.typeOf(s.type))throw new e.EventException(e.EventException.UNSPECIFIED_EVENT_TYPE_ERR);i=s.type,s.total!==l&&s.loaded!==l&&(u.total=s.total,u.loaded=s.loaded),u.async=s.async||!1}if(-1!==i.indexOf("::")?!function(e){r=e[0],i=e[1]}(i.split("::")):r=this.uid,i=i.toLowerCase(),o=n[r]&&n[r][i]){o.sort(function(e,t){return t.priority-e.priority}),a=[].slice.call(arguments),a.shift(),u.type=i,a.unshift(u);var d=[];t.each(o,function(e){a[0].target=e.scope,d.push(u.async?function(t){setTimeout(function(){t(e.fn.apply(e.scope,a)===!1)},1)}:function(t){t(e.fn.apply(e.scope,a)===!1)})}),d.length&&t.inSeries(d,function(e){c=!e})}return c},bind:function(){this.addEventListener.apply(this,arguments)},unbind:function(){this.removeEventListener.apply(this,arguments)},unbindAll:function(){this.removeAllEventListeners.apply(this,arguments)},trigger:function(){return this.dispatchEvent.apply(this,arguments)},convertEventPropsToHandlers:function(e){var n;"array"!==t.typeOf(e)&&(e=[e]);for(var i=0;i>16&255,o=d>>8&255,a=255&d,m[h++]=64==c?String.fromCharCode(r):64==l?String.fromCharCode(r,o):String.fromCharCode(r,o,a);while(f>18&63,u=d>>12&63,c=d>>6&63,l=63&d,m[h++]=i.charAt(s)+i.charAt(u)+i.charAt(c)+i.charAt(l);while(fa;a++)o+=String.fromCharCode(r[a]);return o}}t.call(this),e.extend(this,{uid:e.guid("uid_"),readAsBinaryString:function(e){return i.call(this,"readAsBinaryString",e)},readAsDataURL:function(e){return i.call(this,"readAsDataURL",e)},readAsText:function(e){return i.call(this,"readAsText",e)}})}}),i(A,[h,u,y],function(e,t,n){function i(){var e,i=[];t.extend(this,{append:function(r,o){var a=this,s=t.typeOf(o);o instanceof n?e={name:r,value:o}:"array"===s?(r+="[]",t.each(o,function(e){a.append(r,e)})):"object"===s?t.each(o,function(e,t){a.append(r+"["+t+"]",e)}):"null"===s||"undefined"===s||"number"===s&&isNaN(o)?a.append(r,"false"):i.push({name:r,value:o.toString()})},hasBlob:function(){return!!this.getBlob()},getBlob:function(){return e&&e.value||null},getBlobName:function(){return e&&e.name||null},each:function(n){t.each(i,function(e){n(e.value,e.name)}),e&&n(e.value,e.name)},destroy:function(){e=null,i=[]}})}return i}),i(S,[u,h,p,m,R,g,x,y,T,A,d,l],function(e,t,n,i,r,o,a,s,u,c,l,d){function f(){this.uid=e.guid("uid_")}function h(){function n(e,t){return y.hasOwnProperty(e)?1===arguments.length?l.can("define_property")?y[e]:v[e]:void(l.can("define_property")?y[e]=t:v[e]=t):void 0}function u(t){function i(){k&&(k.destroy(),k=null),s.dispatchEvent("loadend"),s=null}function r(r){k.bind("LoadStart",function(e){n("readyState",h.LOADING),s.dispatchEvent("readystatechange"),s.dispatchEvent(e),I&&s.upload.dispatchEvent(e)}),k.bind("Progress",function(e){n("readyState")!==h.LOADING&&(n("readyState",h.LOADING),s.dispatchEvent("readystatechange")),s.dispatchEvent(e)}),k.bind("UploadProgress",function(e){I&&s.upload.dispatchEvent({type:"progress",lengthComputable:!1,total:e.total,loaded:e.loaded})}),k.bind("Load",function(t){n("readyState",h.DONE),n("status",Number(r.exec.call(k,"XMLHttpRequest","getStatus")||0)),n("statusText",p[n("status")]||""),n("response",r.exec.call(k,"XMLHttpRequest","getResponse",n("responseType"))),~e.inArray(n("responseType"),["text",""])?n("responseText",n("response")):"document"===n("responseType")&&n("responseXML",n("response")),U=r.exec.call(k,"XMLHttpRequest","getAllResponseHeaders"),s.dispatchEvent("readystatechange"),n("status")>0?(I&&s.upload.dispatchEvent(t),s.dispatchEvent(t)):(N=!0,s.dispatchEvent("error")),i()}),k.bind("Abort",function(e){s.dispatchEvent(e),i()}),k.bind("Error",function(e){N=!0,n("readyState",h.DONE),s.dispatchEvent("readystatechange"),D=!0,s.dispatchEvent(e),i()}),r.exec.call(k,"XMLHttpRequest","send",{url:E,method:_,async:w,user:b,password:R,headers:x,mimeType:A,encoding:T,responseType:s.responseType,withCredentials:s.withCredentials,options:P},t)}var s=this;M=(new Date).getTime(),k=new a,"string"==typeof P.required_caps&&(P.required_caps=o.parseCaps(P.required_caps)),P.required_caps=e.extend({},P.required_caps,{return_response_type:s.responseType}),t instanceof c&&(P.required_caps.send_multipart=!0),L||(P.required_caps.do_cors=!0),P.ruid?r(k.connectRuntime(P)):(k.bind("RuntimeInit",function(e,t){r(t)}),k.bind("RuntimeError",function(e,t){s.dispatchEvent("RuntimeError",t)}),k.connectRuntime(P))}function g(){n("responseText",""),n("responseXML",null),n("response",null),n("status",0),n("statusText",""),M=C=null}var v=this,y={timeout:0,readyState:h.UNSENT,withCredentials:!1,status:0,statusText:"",responseType:"",responseXML:null,responseText:null,response:null},w=!0,E,_,x={},b,R,T=null,A=null,S=!1,O=!1,I=!1,D=!1,N=!1,L=!1,M,C,F=null,H=null,P={},k,U="",B;e.extend(this,y,{uid:e.guid("uid_"),upload:new f,open:function(o,a,s,u,c){var l;if(!o||!a)throw new t.DOMException(t.DOMException.SYNTAX_ERR);if(/[\u0100-\uffff]/.test(o)||i.utf8_encode(o)!==o)throw new t.DOMException(t.DOMException.SYNTAX_ERR);if(~e.inArray(o.toUpperCase(),["CONNECT","DELETE","GET","HEAD","OPTIONS","POST","PUT","TRACE","TRACK"])&&(_=o.toUpperCase()),~e.inArray(_,["CONNECT","TRACE","TRACK"]))throw new t.DOMException(t.DOMException.SECURITY_ERR);if(a=i.utf8_encode(a),l=r.parseUrl(a),L=r.hasSameOrigin(l),E=r.resolveUrl(a),(u||c)&&!L)throw new t.DOMException(t.DOMException.INVALID_ACCESS_ERR);if(b=u||l.user,R=c||l.pass,w=s||!0,w===!1&&(n("timeout")||n("withCredentials")||""!==n("responseType")))throw new t.DOMException(t.DOMException.INVALID_ACCESS_ERR);S=!w,O=!1,x={},g.call(this),n("readyState",h.OPENED),this.convertEventPropsToHandlers(["readystatechange"]),this.dispatchEvent("readystatechange")},setRequestHeader:function(r,o){var a=["accept-charset","accept-encoding","access-control-request-headers","access-control-request-method","connection","content-length","cookie","cookie2","content-transfer-encoding","date","expect","host","keep-alive","origin","referer","te","trailer","transfer-encoding","upgrade","user-agent","via"];if(n("readyState")!==h.OPENED||O)throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);if(/[\u0100-\uffff]/.test(r)||i.utf8_encode(r)!==r)throw new t.DOMException(t.DOMException.SYNTAX_ERR);return r=e.trim(r).toLowerCase(),~e.inArray(r,a)||/^(proxy\-|sec\-)/.test(r)?!1:(x[r]?x[r]+=", "+o:x[r]=o,!0)},getAllResponseHeaders:function(){return U||""},getResponseHeader:function(t){return t=t.toLowerCase(),N||~e.inArray(t,["set-cookie","set-cookie2"])?null:U&&""!==U&&(B||(B={},e.each(U.split(/\r\n/),function(t){var n=t.split(/:\s+/);2===n.length&&(n[0]=e.trim(n[0]),B[n[0].toLowerCase()]={header:n[0],value:e.trim(n[1])})})),B.hasOwnProperty(t))?B[t].header+": "+B[t].value:null},overrideMimeType:function(i){var r,o;if(~e.inArray(n("readyState"),[h.LOADING,h.DONE]))throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);if(i=e.trim(i.toLowerCase()),/;/.test(i)&&(r=i.match(/^([^;]+)(?:;\scharset\=)?(.*)$/))&&(i=r[1],r[2]&&(o=r[2])),!d.mimes[i])throw new t.DOMException(t.DOMException.SYNTAX_ERR);F=i,H=o},send:function(n,r){if(P="string"===e.typeOf(r)?{ruid:r}:r?r:{},this.convertEventPropsToHandlers(m),this.upload.convertEventPropsToHandlers(m),this.readyState!==h.OPENED||O)throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);if(n instanceof s)P.ruid=n.ruid,A=n.type||"application/octet-stream";else if(n instanceof c){if(n.hasBlob()){var o=n.getBlob();P.ruid=o.ruid,A=o.type||"application/octet-stream"}}else"string"==typeof n&&(T="UTF-8",A="text/plain;charset=UTF-8",n=i.utf8_encode(n));this.withCredentials||(this.withCredentials=P.required_caps&&P.required_caps.send_browser_cookies&&!L),I=!S&&this.upload.hasEventListener(),N=!1,D=!n,S||(O=!0),u.call(this,n)},abort:function(){if(N=!0,S=!1,~e.inArray(n("readyState"),[h.UNSENT,h.OPENED,h.DONE]))n("readyState",h.UNSENT);else{if(n("readyState",h.DONE),O=!1,!k)throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);k.getRuntime().exec.call(k,"XMLHttpRequest","abort",D),D=!0}},destroy:function(){k&&("function"===e.typeOf(k.destroy)&&k.destroy(),k=null),this.unbindAll(),this.upload&&(this.upload.unbindAll(),this.upload=null)}})}var p={100:"Continue",101:"Switching Protocols",102:"Processing",200:"OK",201:"Created",202:"Accepted",203:"Non-Authoritative Information",204:"No Content",205:"Reset Content",206:"Partial Content",207:"Multi-Status",226:"IM Used",300:"Multiple Choices",301:"Moved Permanently",302:"Found",303:"See Other",304:"Not Modified",305:"Use Proxy",306:"Reserved",307:"Temporary Redirect",400:"Bad Request",401:"Unauthorized",402:"Payment Required",403:"Forbidden",404:"Not Found",405:"Method Not Allowed",406:"Not Acceptable",407:"Proxy Authentication Required",408:"Request Timeout",409:"Conflict",410:"Gone",411:"Length Required",412:"Precondition Failed",413:"Request Entity Too Large",414:"Request-URI Too Long",415:"Unsupported Media Type",416:"Requested Range Not Satisfiable",417:"Expectation Failed",422:"Unprocessable Entity",423:"Locked",424:"Failed Dependency",426:"Upgrade Required",500:"Internal Server Error",501:"Not Implemented",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout",505:"HTTP Version Not Supported",506:"Variant Also Negotiates",507:"Insufficient Storage",510:"Not Extended"};f.prototype=n.instance;var m=["loadstart","progress","abort","error","load","timeout","loadend"],g=1,v=2;return h.UNSENT=0,h.OPENED=1,h.HEADERS_RECEIVED=2,h.LOADING=3,h.DONE=4,h.prototype=n.instance,h}),i(O,[u,m,v,p],function(e,t,n,i){function r(){function i(){l=d=0,c=this.result=null}function o(t,n){var i=this;u=n,i.bind("TransportingProgress",function(t){d=t.loaded,l>d&&-1===e.inArray(i.state,[r.IDLE,r.DONE])&&a.call(i)},999),i.bind("TransportingComplete",function(){d=l,i.state=r.DONE,c=null,i.result=u.exec.call(i,"Transporter","getAsBlob",t||"")},999),i.state=r.BUSY,i.trigger("TransportingStarted"),a.call(i)}function a(){var e=this,n,i=l-d;f>i&&(f=i),n=t.btoa(c.substr(d,f)),u.exec.call(e,"Transporter","receive",n,l)}var s,u,c,l,d,f;n.call(this),e.extend(this,{uid:e.guid("uid_"),state:r.IDLE,result:null,transport:function(t,n,r){var a=this;if(r=e.extend({chunk_size:204798},r),(s=r.chunk_size%3)&&(r.chunk_size+=3-s),f=r.chunk_size,i.call(this),c=t,l=t.length,"string"===e.typeOf(r)||r.ruid)o.call(a,n,this.connectRuntime(r));else{var u=function(e,t){a.unbind("RuntimeInit",u),o.call(a,n,t)};this.bind("RuntimeInit",u),this.connectRuntime(r)}},abort:function(){var e=this;e.state=r.IDLE,u&&(u.exec.call(e,"Transporter","clear"),e.trigger("TransportingAborted")),i.call(e)},destroy:function(){this.unbindAll(),u=null,this.disconnectRuntime(),i.call(this)}})}return r.IDLE=0,r.BUSY=1,r.DONE=2,r.prototype=i.instance,r}),i(I,[u,f,h,T,S,g,v,O,d,p,y,w,m],function(e,t,n,i,r,o,a,s,u,c,l,d,f){function h(){function i(e){e||(e=this.getRuntime().exec.call(this,"Image","getInfo")),this.size=e.size,this.width=e.width,this.height=e.height,this.type=e.type,this.meta=e.meta,""===this.name&&(this.name=e.name)}function c(t){var i=e.typeOf(t);try{if(t instanceof h){if(!t.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);m.apply(this,arguments)}else if(t instanceof l){if(!~e.inArray(t.type,["image/jpeg","image/png"]))throw new n.ImageError(n.ImageError.WRONG_FORMAT);g.apply(this,arguments)}else if(-1!==e.inArray(i,["blob","file"]))c.call(this,new d(null,t),arguments[1]);else if("string"===i)/^data:[^;]*;base64,/.test(t)?c.call(this,new l(null,{data:t}),arguments[1]):v.apply(this,arguments);else{if("node"!==i||"img"!==t.nodeName.toLowerCase())throw new n.DOMException(n.DOMException.TYPE_MISMATCH_ERR);c.call(this,t.src,arguments[1])}}catch(r){this.trigger("error",r.code)}}function m(t,n){var i=this.connectRuntime(t.ruid);this.ruid=i.uid,i.exec.call(this,"Image","loadFromImage",t,"undefined"===e.typeOf(n)?!0:n)}function g(t,n){function i(e){r.ruid=e.uid,e.exec.call(r,"Image","loadFromBlob",t)}var r=this;r.name=t.name||"",t.isDetached()?(this.bind("RuntimeInit",function(e,t){i(t)}),n&&"string"==typeof n.required_caps&&(n.required_caps=o.parseCaps(n.required_caps)),this.connectRuntime(e.extend({required_caps:{access_image_binary:!0,resize_image:!0}},n))):i(this.connectRuntime(t.ruid))}function v(e,t){var n=this,i;i=new r,i.open("get",e),i.responseType="blob",i.onprogress=function(e){n.trigger(e)},i.onload=function(){g.call(n,i.response,!0)},i.onerror=function(e){n.trigger(e)},i.onloadend=function(){i.destroy()},i.bind("RuntimeError",function(e,t){n.trigger("RuntimeError",t)}),i.send(null,t)}a.call(this),e.extend(this,{uid:e.guid("uid_"),ruid:null,name:"",size:0,width:0,height:0,type:"",meta:{},clone:function(){this.load.apply(this,arguments)},load:function(){this.bind("Load Resize",function(){i.call(this)},999),this.convertEventPropsToHandlers(p),c.apply(this,arguments)},downsize:function(t){var i={width:this.width,height:this.height,crop:!1,preserveHeaders:!0};t="object"==typeof t?e.extend(i,t):e.extend(i,{width:arguments[0],height:arguments[1],crop:arguments[2],preserveHeaders:arguments[3]});try{if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);if(this.width>h.MAX_RESIZE_WIDTH||this.height>h.MAX_RESIZE_HEIGHT)throw new n.ImageError(n.ImageError.MAX_RESOLUTION_ERR);this.getRuntime().exec.call(this,"Image","downsize",t.width,t.height,t.crop,t.preserveHeaders)}catch(r){this.trigger("error",r.code)}},crop:function(e,t,n){this.downsize(e,t,!0,n)},getAsCanvas:function(){if(!u.can("create_canvas"))throw new n.RuntimeError(n.RuntimeError.NOT_SUPPORTED_ERR);var e=this.connectRuntime(this.ruid);return e.exec.call(this,"Image","getAsCanvas")},getAsBlob:function(e,t){if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);return e||(e="image/jpeg"),"image/jpeg"!==e||t||(t=90),this.getRuntime().exec.call(this,"Image","getAsBlob",e,t)},getAsDataURL:function(e,t){if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);return this.getRuntime().exec.call(this,"Image","getAsDataURL",e,t)},getAsBinaryString:function(e,t){var n=this.getAsDataURL(e,t);return f.atob(n.substring(n.indexOf("base64,")+7))},embed:function(i){function r(){if(u.can("create_canvas")){var t=a.getAsCanvas();if(t)return i.appendChild(t),t=null,a.destroy(),void o.trigger("embedded")}var r=a.getAsDataURL(c,l);if(!r)throw new n.ImageError(n.ImageError.WRONG_FORMAT);if(u.can("use_data_uri_of",r.length))i.innerHTML='',a.destroy(),o.trigger("embedded");else{var d=new s;d.bind("TransportingComplete",function(){v=o.connectRuntime(this.result.ruid),o.bind("Embedded",function(){e.extend(v.getShimContainer().style,{top:"0px",left:"0px",width:a.width+"px",height:a.height+"px"}),v=null},999),v.exec.call(o,"ImageView","display",this.result.uid,m,g),a.destroy()}),d.transport(f.atob(r.substring(r.indexOf("base64,")+7)),c,e.extend({},p,{required_caps:{display_media:!0},runtime_order:"flash,silverlight",container:i}))}}var o=this,a,c,l,d,p=arguments[1]||{},m=this.width,g=this.height,v;try{if(!(i=t.get(i)))throw new n.DOMException(n.DOMException.INVALID_NODE_TYPE_ERR);if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);if(this.width>h.MAX_RESIZE_WIDTH||this.height>h.MAX_RESIZE_HEIGHT)throw new n.ImageError(n.ImageError.MAX_RESOLUTION_ERR);if(c=p.type||this.type||"image/jpeg",l=p.quality||90,d="undefined"!==e.typeOf(p.crop)?p.crop:!1,p.width)m=p.width,g=p.height||m;else{var y=t.getSize(i);y.w&&y.h&&(m=y.w,g=y.h)}return a=new h,a.bind("Resize",function(){r.call(o)}),a.bind("Load",function(){a.downsize(m,g,d,!1)}),a.clone(this,!1),a}catch(w){this.trigger("error",w.code)}},destroy:function(){this.ruid&&(this.getRuntime().exec.call(this,"Image","destroy"),this.disconnectRuntime()),this.unbindAll()}})}var p=["progress","load","error","resize","embedded"];return h.MAX_RESIZE_WIDTH=6500,h.MAX_RESIZE_HEIGHT=6500,h.prototype=c.instance,h}),i(D,[u,h,g,d],function(e,t,n,i){function r(t){var r=this,s=n.capTest,u=n.capTrue,c=e.extend({access_binary:s(window.FileReader||window.File&&window.File.getAsDataURL),access_image_binary:function(){return r.can("access_binary")&&!!a.Image},display_media:s(i.can("create_canvas")||i.can("use_data_uri_over32kb")),do_cors:s(window.XMLHttpRequest&&"withCredentials"in new XMLHttpRequest),drag_and_drop:s(function(){var e=document.createElement("div");return("draggable"in e||"ondragstart"in e&&"ondrop"in e)&&("IE"!==i.browser||i.version>9)}()),filter_by_extension:s(function(){return"Chrome"===i.browser&&i.version>=28||"IE"===i.browser&&i.version>=10}()),return_response_headers:u,return_response_type:function(e){return"json"===e&&window.JSON?!0:i.can("return_response_type",e)},return_status_code:u,report_upload_progress:s(window.XMLHttpRequest&&(new XMLHttpRequest).upload),resize_image:function(){return r.can("access_binary")&&i.can("create_canvas")},select_file:function(){return i.can("use_fileinput")&&window.File},select_folder:function(){return r.can("select_file")&&"Chrome"===i.browser&&i.version>=21},select_multiple:function(){return!(!r.can("select_file")||"Safari"===i.browser&&"Windows"===i.os||"iOS"===i.os&&i.verComp(i.osVersion,"7.0.4","<"))},send_binary_string:s(window.XMLHttpRequest&&((new XMLHttpRequest).sendAsBinary||window.Uint8Array&&window.ArrayBuffer)),send_custom_headers:s(window.XMLHttpRequest),send_multipart:function(){return!!(window.XMLHttpRequest&&(new XMLHttpRequest).upload&&window.FormData)||r.can("send_binary_string")},slice_blob:s(window.File&&(File.prototype.mozSlice||File.prototype.webkitSlice||File.prototype.slice)),stream_upload:function(){return r.can("slice_blob")&&r.can("send_multipart")},summon_file_dialog:s(function(){return"Firefox"===i.browser&&i.version>=4||"Opera"===i.browser&&i.version>=12||"IE"===i.browser&&i.version>=10||!!~e.inArray(i.browser,["Chrome","Safari"])}()),upload_filesize:u},arguments[2]);n.call(this,t,arguments[1]||o,c),e.extend(this,{init:function(){this.trigger("Init")},destroy:function(e){return function(){e.call(r),e=r=null}}(this.destroy)}),e.extend(this.getShim(),a)}var o="html5",a={};return n.addConstructor(o,r),a}),i(N,[D,y],function(e,t){function n(){function e(e,t,n){var i;if(!window.File.prototype.slice)return(i=window.File.prototype.webkitSlice||window.File.prototype.mozSlice)?i.call(e,t,n):null;try{return e.slice(),e.slice(t,n)}catch(r){return e.slice(t,n-t)}}this.slice=function(){return new t(this.getRuntime().uid,e.apply(this,arguments))}}return e.Blob=n}),i(L,[u],function(e){function t(){this.returnValue=!1}function n(){this.cancelBubble=!0}var i={},r="moxie_"+e.guid(),o=function(o,a,s,u){var c,l;a=a.toLowerCase(),o.addEventListener?(c=s,o.addEventListener(a,c,!1)):o.attachEvent&&(c=function(){var e=window.event;e.target||(e.target=e.srcElement),e.preventDefault=t,e.stopPropagation=n,s(e)},o.attachEvent("on"+a,c)),o[r]||(o[r]=e.guid()),i.hasOwnProperty(o[r])||(i[o[r]]={}),l=i[o[r]],l.hasOwnProperty(a)||(l[a]=[]),l[a].push({func:c,orig:s,key:u})},a=function(t,n,o){var a,s;if(n=n.toLowerCase(),t[r]&&i[t[r]]&&i[t[r]][n]){a=i[t[r]][n];for(var u=a.length-1;u>=0&&(a[u].orig!==o&&a[u].key!==o||(t.removeEventListener?t.removeEventListener(n,a[u].func,!1):t.detachEvent&&t.detachEvent("on"+n,a[u].func),a[u].orig=null,a[u].func=null,a.splice(u,1),o===s));u--);if(a.length||delete i[t[r]][n],e.isEmptyObj(i[t[r]])){delete i[t[r]];try{delete t[r]}catch(c){t[r]=s}}}},s=function(t,n){t&&t[r]&&e.each(i[t[r]],function(e,i){a(t,i,n)})};return{addEvent:o,removeEvent:a,removeAllEvents:s}}),i(M,[D,u,f,L,l,d],function(e,t,n,i,r,o){function a(){var e=[],a;t.extend(this,{init:function(s){var u=this,c=u.getRuntime(),l,d,f,h,p,m;a=s,e=[],f=a.accept.mimes||r.extList2mimes(a.accept,c.can("filter_by_extension")),d=c.getShimContainer(),d.innerHTML='",l=n.get(c.uid),t.extend(l.style,{position:"absolute",top:0,left:0,width:"100%",height:"100%"}),h=n.get(a.browse_button),c.can("summon_file_dialog")&&("static"===n.getStyle(h,"position")&&(h.style.position="relative"),p=parseInt(n.getStyle(h,"z-index"),10)||1,h.style.zIndex=p,d.style.zIndex=p-1,i.addEvent(h,"click",function(e){var t=n.get(c.uid);t&&!t.disabled&&t.click(),e.preventDefault()},u.uid)),m=c.can("summon_file_dialog")?h:d,i.addEvent(m,"mouseover",function(){u.trigger("mouseenter")},u.uid),i.addEvent(m,"mouseout",function(){u.trigger("mouseleave")},u.uid),i.addEvent(m,"mousedown",function(){u.trigger("mousedown")},u.uid),i.addEvent(n.get(a.container),"mouseup",function(){u.trigger("mouseup")},u.uid),l.onchange=function g(){if(e=[],a.directory?t.each(this.files,function(t){"."!==t.name&&e.push(t)}):e=[].slice.call(this.files),"IE"!==o.browser&&"IEMobile"!==o.browser)this.value="";else{var n=this.cloneNode(!0);this.parentNode.replaceChild(n,this),n.onchange=g}u.trigger("change")},u.trigger({type:"ready",async:!0}),d=null},getFiles:function(){return e},disable:function(e){var t=this.getRuntime(),i;(i=n.get(t.uid))&&(i.disabled=!!e)},destroy:function(){var t=this.getRuntime(),r=t.getShim(),o=t.getShimContainer();i.removeAllEvents(o,this.uid),i.removeAllEvents(a&&n.get(a.container),this.uid),i.removeAllEvents(a&&n.get(a.browse_button),this.uid),o&&(o.innerHTML=""),r.removeInstance(this.uid),e=a=o=r=null}})}return e.FileInput=a}),i(C,[D,u,f,L,l],function(e,t,n,i,r){function o(){function e(e){if(!e.dataTransfer||!e.dataTransfer.types)return!1;var n=t.toArray(e.dataTransfer.types||[]);return-1!==t.inArray("Files",n)||-1!==t.inArray("public.file-url",n)||-1!==t.inArray("application/x-moz-file",n)}function o(e){for(var n=[],i=0;i=4&&u.version<7,f="Android Browser"===u.browser,m=!1;if(p=n.url.replace(/^.+?\/([\w\-\.]+)$/,"$1").toLowerCase(),h=c(),h.open(n.method,n.url,n.async,n.user,n.password),r instanceof o)r.isDetached()&&(m=!0),r=r.getSource();else if(r instanceof a){if(r.hasBlob())if(r.getBlob().isDetached())r=d.call(s,r),m=!0;else if((l||f)&&"blob"===t.typeOf(r.getBlob().getSource())&&window.FileReader)return void e.call(s,n,r);if(r instanceof a){var g=new window.FormData;r.each(function(e,t){e instanceof o?g.append(t,e.getSource()):g.append(t,e)}),r=g}}h.upload?(n.withCredentials&&(h.withCredentials=!0),h.addEventListener("load",function(e){s.trigger(e)}),h.addEventListener("error",function(e){s.trigger(e)}),h.addEventListener("progress",function(e){s.trigger(e)}),h.upload.addEventListener("progress",function(e){s.trigger({type:"UploadProgress",loaded:e.loaded,total:e.total})})):h.onreadystatechange=function v(){switch(h.readyState){case 1:break;case 2:break;case 3:var e,t;try{i.hasSameOrigin(n.url)&&(e=h.getResponseHeader("Content-Length")||0),h.responseText&&(t=h.responseText.length)}catch(r){e=t=0}s.trigger({type:"progress",lengthComputable:!!e,total:parseInt(e,10),loaded:t});break;case 4:h.onreadystatechange=function(){},s.trigger(0===h.status?"error":"load")}},t.isEmptyObj(n.headers)||t.each(n.headers,function(e,t){h.setRequestHeader(t,e)}),""!==n.responseType&&"responseType"in h&&(h.responseType="json"!==n.responseType||u.can("return_response_type","json")?n.responseType:"text"),m?h.sendAsBinary?h.sendAsBinary(r):!function(){for(var e=new Uint8Array(r.length),t=0;ta;a++)i|=o.charCodeAt(e+a)<s;s++)o+=String.fromCharCode(t>>Math.abs(a+8*s)&255);n(o,e,i)}var r=!1,o;return{II:function(e){return e===t?r:void(r=e)},init:function(e){r=!1,o=e},SEGMENT:function(e,t,i){switch(arguments.length){case 1:return o.substr(e,o.length-e-1);case 2:return o.substr(e,t);case 3:n(i,e,t);break;default:return o}},BYTE:function(t){return e(t,1)},SHORT:function(t){return e(t,2)},LONG:function(n,r){return r===t?e(n,4):void i(n,r,4)},SLONG:function(t){var n=e(t,4);return n>2147483647?n-4294967296:n},STRING:function(t,n){var i="";for(n+=t;n>t;t++)i+=String.fromCharCode(e(t,1));return i}}}}),i(k,[P],function(e){return function t(n){var i=[],r,o,a,s=0;if(r=new e,r.init(n),65496===r.SHORT(0)){for(o=2;o<=n.length;)if(a=r.SHORT(o),a>=65488&&65495>=a)o+=2;else{if(65498===a||65497===a)break;s=r.SHORT(o+2)+2,a>=65505&&65519>=a&&i.push({hex:a,name:"APP"+(15&a),start:o,length:s,segment:r.SEGMENT(o,s)}),o+=s}return r.init(null),{headers:i,restore:function(e){var t,n;for(r.init(e),o=65504==r.SHORT(2)?4+r.SHORT(4):2,n=0,t=i.length;t>n;n++)r.SEGMENT(o,0,i[n].segment),o+=i[n].length;return e=r.SEGMENT(),r.init(null),e},strip:function(e){var n,i,o;for(i=new t(e),n=i.headers,i.purge(),r.init(e),o=n.length;o--;)r.SEGMENT(n[o].start,n[o].length,"");return e=r.SEGMENT(),r.init(null),e},get:function(e){for(var t=[],n=0,r=i.length;r>n;n++)i[n].name===e.toUpperCase()&&t.push(i[n].segment);return t},set:function(e,t){var n=[],r,o,a;for("string"==typeof t?n.push(t):n=t,r=o=0,a=i.length;a>r&&(i[r].name===e.toUpperCase()&&(i[r].segment=n[o],i[r].length=n[o].length,o++),!(o>=n.length));r++);},purge:function(){i=[],r.init(null),r=null}}}}}),i(U,[u,P],function(e,n){return function i(){function i(e,n){var i=a.SHORT(e),r,o,s,u,d,f,h,p,m=[],g={};for(r=0;i>r;r++)if(h=f=e+12*r+2,s=n[a.SHORT(h)],s!==t){switch(u=a.SHORT(h+=2),d=a.LONG(h+=2),h+=4,m=[],u){case 1:case 7:for(d>4&&(h=a.LONG(h)+c.tiffHeader),o=0;d>o;o++)m[o]=a.BYTE(h+o);break;case 2:d>4&&(h=a.LONG(h)+c.tiffHeader),g[s]=a.STRING(h,d-1);continue;case 3:for(d>2&&(h=a.LONG(h)+c.tiffHeader),o=0;d>o;o++)m[o]=a.SHORT(h+2*o);break;case 4:for(d>1&&(h=a.LONG(h)+c.tiffHeader),o=0;d>o;o++)m[o]=a.LONG(h+4*o);break;case 5:for(h=a.LONG(h)+c.tiffHeader,o=0;d>o;o++)m[o]=a.LONG(h+4*o)/a.LONG(h+4*o+4);break;case 9:for(h=a.LONG(h)+c.tiffHeader,o=0;d>o;o++)m[o]=a.SLONG(h+4*o);break;case 10:for(h=a.LONG(h)+c.tiffHeader,o=0;d>o;o++)m[o]=a.SLONG(h+4*o)/a.SLONG(h+4*o+4);break;default:continue}p=1==d?m[0]:m,g[s]=l.hasOwnProperty(s)&&"object"!=typeof p?l[s][p]:p}return g}function r(){var e=c.tiffHeader;return a.II(18761==a.SHORT(e)),42!==a.SHORT(e+=2)?!1:(c.IFD0=c.tiffHeader+a.LONG(e+=2),u=i(c.IFD0,s.tiff),"ExifIFDPointer"in u&&(c.exifIFD=c.tiffHeader+u.ExifIFDPointer,delete u.ExifIFDPointer),"GPSInfoIFDPointer"in u&&(c.gpsIFD=c.tiffHeader+u.GPSInfoIFDPointer,delete u.GPSInfoIFDPointer),!0)}function o(e,t,n){var i,r,o,u=0;if("string"==typeof t){var l=s[e.toLowerCase()];for(var d in l)if(l[d]===t){t=d;break}}i=c[e.toLowerCase()+"IFD"],r=a.SHORT(i);for(var f=0;r>f;f++)if(o=i+12*f+2,a.SHORT(o)==t){u=o+8;break}return u?(a.LONG(u,n),!0):!1}var a,s,u,c={},l;return a=new n,s={tiff:{274:"Orientation",270:"ImageDescription",271:"Make",272:"Model",305:"Software",34665:"ExifIFDPointer",34853:"GPSInfoIFDPointer"},exif:{36864:"ExifVersion",40961:"ColorSpace",40962:"PixelXDimension",40963:"PixelYDimension",36867:"DateTimeOriginal",33434:"ExposureTime",33437:"FNumber",34855:"ISOSpeedRatings",37377:"ShutterSpeedValue",37378:"ApertureValue",37383:"MeteringMode",37384:"LightSource",37385:"Flash",37386:"FocalLength",41986:"ExposureMode",41987:"WhiteBalance",41990:"SceneCaptureType",41988:"DigitalZoomRatio",41992:"Contrast",41993:"Saturation",41994:"Sharpness"},gps:{0:"GPSVersionID",1:"GPSLatitudeRef",2:"GPSLatitude",3:"GPSLongitudeRef",4:"GPSLongitude"}},l={ColorSpace:{1:"sRGB",0:"Uncalibrated"},MeteringMode:{0:"Unknown",1:"Average",2:"CenterWeightedAverage",3:"Spot",4:"MultiSpot",5:"Pattern",6:"Partial",255:"Other"},LightSource:{1:"Daylight",2:"Fliorescent",3:"Tungsten",4:"Flash",9:"Fine weather",10:"Cloudy weather",11:"Shade",12:"Daylight fluorescent (D 5700 - 7100K)",13:"Day white fluorescent (N 4600 -5400K)",14:"Cool white fluorescent (W 3900 - 4500K)",15:"White fluorescent (WW 3200 - 3700K)",17:"Standard light A",18:"Standard light B",19:"Standard light C",20:"D55",21:"D65",22:"D75",23:"D50",24:"ISO studio tungsten",255:"Other"},Flash:{0:"Flash did not fire.",1:"Flash fired.",5:"Strobe return light not detected.",7:"Strobe return light detected.",9:"Flash fired, compulsory flash mode",13:"Flash fired, compulsory flash mode, return light not detected",15:"Flash fired, compulsory flash mode, return light detected",16:"Flash did not fire, compulsory flash mode",24:"Flash did not fire, auto mode",25:"Flash fired, auto mode",29:"Flash fired, auto mode, return light not detected",31:"Flash fired, auto mode, return light detected",32:"No flash function",65:"Flash fired, red-eye reduction mode",69:"Flash fired, red-eye reduction mode, return light not detected",71:"Flash fired, red-eye reduction mode, return light detected",73:"Flash fired, compulsory flash mode, red-eye reduction mode",77:"Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",79:"Flash fired, compulsory flash mode, red-eye reduction mode, return light detected",89:"Flash fired, auto mode, red-eye reduction mode",93:"Flash fired, auto mode, return light not detected, red-eye reduction mode",95:"Flash fired, auto mode, return light detected, red-eye reduction mode"},ExposureMode:{0:"Auto exposure",1:"Manual exposure",2:"Auto bracket"},WhiteBalance:{0:"Auto white balance",1:"Manual white balance"},SceneCaptureType:{0:"Standard",1:"Landscape",2:"Portrait",3:"Night scene"},Contrast:{0:"Normal",1:"Soft",2:"Hard"},Saturation:{0:"Normal",1:"Low saturation",2:"High saturation"},Sharpness:{0:"Normal",1:"Soft",2:"Hard"},GPSLatitudeRef:{N:"North latitude",S:"South latitude"},GPSLongitudeRef:{E:"East longitude",W:"West longitude"}},{init:function(e){return c={tiffHeader:10},e!==t&&e.length?(a.init(e),65505===a.SHORT(0)&&"EXIF\x00"===a.STRING(4,5).toUpperCase()?r():!1):!1 +},TIFF:function(){return u},EXIF:function(){var t;if(t=i(c.exifIFD,s.exif),t.ExifVersion&&"array"===e.typeOf(t.ExifVersion)){for(var n=0,r="";n=65472&&65475>=t)return e+=5,{height:c.SHORT(e),width:c.SHORT(e+=2)};n=c.SHORT(e+=2),e+=n-2}return null}function s(){d&&l&&c&&(d.purge(),l.purge(),c.init(null),u=f=l=d=c=null)}var u,c,l,d,f,h;if(u=o,c=new i,c.init(u),65496!==c.SHORT(0))throw new t.ImageError(t.ImageError.WRONG_FORMAT);l=new n(o),d=new r,h=!!d.init(l.get("app1")[0]),f=a.call(this),e.extend(this,{type:"image/jpeg",size:u.length,width:f&&f.width||0,height:f&&f.height||0,setExif:function(t,n){return h?("object"===e.typeOf(t)?e.each(t,function(e,t){d.setExif(t,e)}):d.setExif(t,n),void l.set("app1",d.getBinary())):!1},writeHeaders:function(){return arguments.length?l.restore(arguments[0]):u=l.restore(u)},stripHeaders:function(e){return l.strip(e)},purge:function(){s.call(this)}}),h&&(this.meta={tiff:d.TIFF(),exif:d.EXIF(),gps:d.GPS()})}return o}),i(z,[h,u,P],function(e,t,n){function i(i){function r(){var e,t;return e=a.call(this,8),"IHDR"==e.type?(t=e.start,{width:u.LONG(t),height:u.LONG(t+=4)}):null}function o(){u&&(u.init(null),s=d=c=l=u=null)}function a(e){var t,n,i,r;return t=u.LONG(e),n=u.STRING(e+=4,4),i=e+=4,r=u.LONG(e+t),{length:t,type:n,start:i,CRC:r}}var s,u,c,l,d;s=i,u=new n,u.init(s),function(){var t=0,n=0,i=[35152,20039,3338,6666];for(n=0;ng;){for(var v=g+f>a?a-g:f,y=0;o>y;){var w=y+f>o?o-y:f;p.clearRect(0,0,f,f),p.drawImage(e,-y,-g);var E=y*s/o+c<<0,_=Math.ceil(w*s/o),x=g*u/a/m+l<<0,b=Math.ceil(v*u/a/m);d.drawImage(h,0,0,w,v,E,x,_,b),y+=f}g+=f}h=p=null}function t(e){var t=e.naturalWidth,n=e.naturalHeight;if(t*n>1048576){var i=document.createElement("canvas");i.width=i.height=1;var r=i.getContext("2d");return r.drawImage(e,-t+1,0),0===r.getImageData(0,0,1,1).data[3]}return!1}function n(e,t,n){var i=document.createElement("canvas");i.width=1,i.height=n;var r=i.getContext("2d");r.drawImage(e,0,0);for(var o=r.getImageData(0,0,1,n).data,a=0,s=n,u=n;u>a;){var c=o[4*(u-1)+3];0===c?s=u:a=u,u=s+a>>1}i=null;var l=u/n;return 0===l?1:l}return{isSubsampled:t,renderTo:e}}),i(X,[D,u,h,m,w,G,q,l,d],function(e,t,n,i,r,o,a,s,u){function c(){function e(){if(!E&&!y)throw new n.ImageError(n.DOMException.INVALID_STATE_ERR);return E||y}function c(e){return i.atob(e.substring(e.indexOf("base64,")+7))}function l(e,t){return"data:"+(t||"")+";base64,"+i.btoa(e)}function d(e){var t=this;y=new Image,y.onerror=function(){g.call(this),t.trigger("error",n.ImageError.WRONG_FORMAT)},y.onload=function(){t.trigger("load")},y.src=/^data:[^;]*;base64,/.test(e)?e:l(e,x.type)}function f(e,t){var i=this,r;return window.FileReader?(r=new FileReader,r.onload=function(){t(this.result)},r.onerror=function(){i.trigger("error",n.ImageError.WRONG_FORMAT)},r.readAsDataURL(e),void 0):t(e.getAsDataURL())}function h(n,i,r,o){var a=this,s,u,c=0,l=0,d,f,h,g;if(R=o,g=this.meta&&this.meta.tiff&&this.meta.tiff.Orientation||1,-1!==t.inArray(g,[5,6,7,8])){var v=n;n=i,i=v}return d=e(),r?(n=Math.min(n,d.width),i=Math.min(i,d.height),s=Math.max(n/d.width,i/d.height)):s=Math.min(n/d.width,i/d.height),s>1&&!r&&o?void this.trigger("Resize"):(E||(E=document.createElement("canvas")),f=Math.round(d.width*s),h=Math.round(d.height*s),r?(E.width=n,E.height=i,f>n&&(c=Math.round((f-n)/2)),h>i&&(l=Math.round((h-i)/2))):(E.width=f,E.height=h),R||m(E.width,E.height,g),p.call(this,d,E,-c,-l,f,h),this.width=E.width,this.height=E.height,b=!0,void a.trigger("Resize"))}function p(e,t,n,i,r,o){if("iOS"===u.OS)a.renderTo(e,t,{width:r,height:o,x:n,y:i});else{var s=t.getContext("2d");s.drawImage(e,n,i,r,o)}}function m(e,t,n){switch(n){case 5:case 6:case 7:case 8:E.width=t,E.height=e;break;default:E.width=e,E.height=t}var i=E.getContext("2d");switch(n){case 2:i.translate(e,0),i.scale(-1,1);break;case 3:i.translate(e,t),i.rotate(Math.PI);break;case 4:i.translate(0,t),i.scale(1,-1);break;case 5:i.rotate(.5*Math.PI),i.scale(1,-1);break;case 6:i.rotate(.5*Math.PI),i.translate(0,-t);break;case 7:i.rotate(.5*Math.PI),i.translate(e,-t),i.scale(-1,1);break;case 8:i.rotate(-.5*Math.PI),i.translate(-e,0)}}function g(){w&&(w.purge(),w=null),_=y=E=x=null,b=!1}var v=this,y,w,E,_,x,b=!1,R=!0;t.extend(this,{loadFromBlob:function(e){var t=this,i=t.getRuntime(),r=arguments.length>1?arguments[1]:!0;if(!i.can("access_binary"))throw new n.RuntimeError(n.RuntimeError.NOT_SUPPORTED_ERR);return x=e,e.isDetached()?(_=e.getSource(),void d.call(this,_)):void f.call(this,e.getSource(),function(e){r&&(_=c(e)),d.call(t,e)})},loadFromImage:function(e,t){this.meta=e.meta,x=new r(null,{name:e.name,size:e.size,type:e.type}),d.call(this,t?_=e.getAsBinaryString():e.getAsDataURL())},getInfo:function(){var t=this.getRuntime(),n;return!w&&_&&t.can("access_image_binary")&&(w=new o(_)),n={width:e().width||0,height:e().height||0,type:x.type||s.getFileMime(x.name),size:_&&_.length||x.size||0,name:x.name||"",meta:w&&w.meta||this.meta||{}}},downsize:function(){h.apply(this,arguments)},getAsCanvas:function(){return E&&(E.id=this.uid+"_canvas"),E},getAsBlob:function(e,t){return e!==this.type&&h.call(this,this.width,this.height,!1),new r(null,{name:x.name||"",type:e,data:v.getAsBinaryString.call(this,e,t)})},getAsDataURL:function(e){var t=arguments[1]||90;if(!b)return y.src;if("image/jpeg"!==e)return E.toDataURL("image/png");try{return E.toDataURL("image/jpeg",t/100)}catch(n){return E.toDataURL("image/jpeg")}},getAsBinaryString:function(e,t){if(!b)return _||(_=c(v.getAsDataURL(e,t))),_;if("image/jpeg"!==e)_=c(v.getAsDataURL(e,t));else{var n;t||(t=90);try{n=E.toDataURL("image/jpeg",t/100)}catch(i){n=E.toDataURL("image/jpeg")}_=c(n),w&&(_=w.stripHeaders(_),R&&(w.meta&&w.meta.exif&&w.setExif({PixelXDimension:this.width,PixelYDimension:this.height}),_=w.writeHeaders(_)),w.purge(),w=null)}return b=!1,_},destroy:function(){v=null,g.call(this),this.getRuntime().getShim().removeInstance(this.uid)}})}return e.Image=c}),i(j,[u,d,f,h,g],function(e,t,n,i,r){function o(){var e;try{e=navigator.plugins["Shockwave Flash"],e=e.description}catch(t){try{e=new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version")}catch(n){e="0.0"}}return e=e.match(/\d+/g),parseFloat(e[0]+"."+e[1])}function a(a){var c=this,l;a=e.extend({swf_url:t.swf_url},a),r.call(this,a,s,{access_binary:function(e){return e&&"browser"===c.mode},access_image_binary:function(e){return e&&"browser"===c.mode},display_media:r.capTrue,do_cors:r.capTrue,drag_and_drop:!1,report_upload_progress:function(){return"client"===c.mode},resize_image:r.capTrue,return_response_headers:!1,return_response_type:function(t){return"json"===t&&window.JSON?!0:!e.arrayDiff(t,["","text","document"])||"browser"===c.mode},return_status_code:function(t){return"browser"===c.mode||!e.arrayDiff(t,[200,404])},select_file:r.capTrue,select_multiple:r.capTrue,send_binary_string:function(e){return e&&"browser"===c.mode},send_browser_cookies:function(e){return e&&"browser"===c.mode},send_custom_headers:function(e){return e&&"browser"===c.mode},send_multipart:r.capTrue,slice_blob:function(e){return e&&"browser"===c.mode},stream_upload:function(e){return e&&"browser"===c.mode},summon_file_dialog:!1,upload_filesize:function(t){return e.parseSizeStr(t)<=2097152||"client"===c.mode},use_http_method:function(t){return!e.arrayDiff(t,["GET","POST"])}},{access_binary:function(e){return e?"browser":"client"},access_image_binary:function(e){return e?"browser":"client"},report_upload_progress:function(e){return e?"browser":"client"},return_response_type:function(t){return e.arrayDiff(t,["","text","json","document"])?"browser":["client","browser"]},return_status_code:function(t){return e.arrayDiff(t,[200,404])?"browser":["client","browser"]},send_binary_string:function(e){return e?"browser":"client"},send_browser_cookies:function(e){return e?"browser":"client"},send_custom_headers:function(e){return e?"browser":"client"},stream_upload:function(e){return e?"client":"browser"},upload_filesize:function(t){return e.parseSizeStr(t)>=2097152?"client":"browser"}},"client"),o()<10&&(this.mode=!1),e.extend(this,{getShim:function(){return n.get(this.uid)},shimExec:function(e,t){var n=[].slice.call(arguments,2);return c.getShim().exec(this.uid,e,t,n)},init:function(){var n,r,o;o=this.getShimContainer(),e.extend(o.style,{position:"absolute",top:"-8px",left:"-8px",width:"9px",height:"9px",overflow:"hidden"}),n='',"IE"===t.browser?(r=document.createElement("div"),o.appendChild(r),r.outerHTML=n,r=o=null):o.innerHTML=n,l=setTimeout(function(){c&&!c.initialized&&c.trigger("Error",new i.RuntimeError(i.RuntimeError.NOT_INIT_ERR))},5e3)},destroy:function(e){return function(){e.call(c),clearTimeout(l),a=l=e=c=null}}(this.destroy)},u)}var s="flash",u={};return r.addConstructor(s,a),u}),i(V,[j,y],function(e,t){var n={slice:function(e,n,i,r){var o=this.getRuntime();return 0>n?n=Math.max(e.size+n,0):n>0&&(n=Math.min(n,e.size)),0>i?i=Math.max(e.size+i,0):i>0&&(i=Math.min(i,e.size)),e=o.shimExec.call(this,"Blob","slice",n,i,r||""),e&&(e=new t(o.uid,e)),e}};return e.Blob=n}),i(W,[j],function(e){var t={init:function(e){this.getRuntime().shimExec.call(this,"FileInput","init",{name:e.name,accept:e.accept,multiple:e.multiple}),this.trigger("ready")}};return e.FileInput=t}),i(Y,[j,m],function(e,t){function n(e,n){switch(n){case"readAsText":return t.atob(e,"utf8");case"readAsBinaryString":return t.atob(e);case"readAsDataURL":return e}return null}var i="",r={read:function(e,t){var r=this,o=r.getRuntime();return"readAsDataURL"===e&&(i="data:"+(t.type||"")+";base64,"),r.bind("Progress",function(t,r){r&&(i+=n(r,e))}),o.shimExec.call(this,"FileReader","readAsBase64",t.uid)},getResult:function(){return i},destroy:function(){i=null}};return e.FileReader=r}),i($,[j,m],function(e,t){function n(e,n){switch(n){case"readAsText":return t.atob(e,"utf8");case"readAsBinaryString":return t.atob(e);case"readAsDataURL":return e}return null}var i={read:function(e,t){var i,r=this.getRuntime();return(i=r.shimExec.call(this,"FileReaderSync","readAsBase64",t.uid))?("readAsDataURL"===e&&(i="data:"+(t.type||"")+";base64,"+i),n(i,e,t.type)):null}};return e.FileReaderSync=i}),i(J,[j,u,y,w,T,A,O],function(e,t,n,i,r,o,a){var s={send:function(e,i){function r(){e.transport=l.mode,l.shimExec.call(c,"XMLHttpRequest","send",e,i)}function s(e,t){l.shimExec.call(c,"XMLHttpRequest","appendBlob",e,t.uid),i=null,r()}function u(e,t){var n=new a;n.bind("TransportingComplete",function(){t(this.result)}),n.transport(e.getSource(),e.type,{ruid:l.uid})}var c=this,l=c.getRuntime();if(t.isEmptyObj(e.headers)||t.each(e.headers,function(e,t){l.shimExec.call(c,"XMLHttpRequest","setRequestHeader",t,e.toString())}),i instanceof o){var d;if(i.each(function(e,t){e instanceof n?d=t:l.shimExec.call(c,"XMLHttpRequest","append",t,e)}),i.hasBlob()){var f=i.getBlob();f.isDetached()?u(f,function(e){f.destroy(),s(d,e)}):s(d,f)}else i=null,r()}else i instanceof n?i.isDetached()?u(i,function(e){i.destroy(),i=e.uid,r()}):(i=i.uid,r()):r()},getResponse:function(e){var n,o,a=this.getRuntime();if(o=a.shimExec.call(this,"XMLHttpRequest","getResponseAsBlob")){if(o=new i(a.uid,o),"blob"===e)return o;try{if(n=new r,~t.inArray(e,["","text"]))return n.readAsText(o);if("json"===e&&window.JSON)return JSON.parse(n.readAsText(o))}finally{o.destroy()}}return null},abort:function(e){var t=this.getRuntime();t.shimExec.call(this,"XMLHttpRequest","abort"),this.dispatchEvent("readystatechange"),this.dispatchEvent("abort")}};return e.XMLHttpRequest=s}),i(Z,[j,y],function(e,t){var n={getAsBlob:function(e){var n=this.getRuntime(),i=n.shimExec.call(this,"Transporter","getAsBlob",e);return i?new t(n.uid,i):null}};return e.Transporter=n}),i(K,[j,u,O,y,T],function(e,t,n,i,r){var o={loadFromBlob:function(e){function t(e){r.shimExec.call(i,"Image","loadFromBlob",e.uid),i=r=null}var i=this,r=i.getRuntime();if(e.isDetached()){var o=new n;o.bind("TransportingComplete",function(){t(o.result.getSource())}),o.transport(e.getSource(),e.type,{ruid:r.uid})}else t(e.getSource())},loadFromImage:function(e){var t=this.getRuntime();return t.shimExec.call(this,"Image","loadFromImage",e.uid)},getAsBlob:function(e,t){var n=this.getRuntime(),r=n.shimExec.call(this,"Image","getAsBlob",e,t);return r?new i(n.uid,r):null},getAsDataURL:function(){var e=this.getRuntime(),t=e.Image.getAsBlob.apply(this,arguments),n;return t?(n=new r,n.readAsDataURL(t)):null}};return e.Image=o}),i(Q,[u,d,f,h,g],function(e,t,n,i,r){function o(e){var t=!1,n=null,i,r,o,a,s,u=0;try{try{n=new ActiveXObject("AgControl.AgControl"),n.IsVersionSupported(e)&&(t=!0),n=null}catch(c){var l=navigator.plugins["Silverlight Plug-In"];if(l){for(i=l.description,"1.0.30226.2"===i&&(i="2.0.30226.2"),r=i.split(".");r.length>3;)r.pop();for(;r.length<4;)r.push(0);for(o=e.split(".");o.length>4;)o.pop();do a=parseInt(o[u],10),s=parseInt(r[u],10),u++;while(u=a&&!isNaN(a)&&(t=!0)}}}catch(d){t=!1}return t}function a(a){var c=this,l;a=e.extend({xap_url:t.xap_url},a),r.call(this,a,s,{access_binary:r.capTrue,access_image_binary:r.capTrue,display_media:r.capTrue,do_cors:r.capTrue,drag_and_drop:!1,report_upload_progress:r.capTrue,resize_image:r.capTrue,return_response_headers:function(e){return e&&"client"===c.mode},return_response_type:function(e){return"json"!==e?!0:!!window.JSON},return_status_code:function(t){return"client"===c.mode||!e.arrayDiff(t,[200,404])},select_file:r.capTrue,select_multiple:r.capTrue,send_binary_string:r.capTrue,send_browser_cookies:function(e){return e&&"browser"===c.mode},send_custom_headers:function(e){return e&&"client"===c.mode},send_multipart:r.capTrue,slice_blob:r.capTrue,stream_upload:!0,summon_file_dialog:!1,upload_filesize:r.capTrue,use_http_method:function(t){return"client"===c.mode||!e.arrayDiff(t,["GET","POST"])}},{return_response_headers:function(e){return e?"client":"browser"},return_status_code:function(t){return e.arrayDiff(t,[200,404])?"client":["client","browser"]},send_browser_cookies:function(e){return e?"browser":"client"},send_custom_headers:function(e){return e?"client":"browser"},use_http_method:function(t){return e.arrayDiff(t,["GET","POST"])?"client":["client","browser"]}}),o("2.0.31005.0")&&"Opera"!==t.browser||(this.mode=!1),e.extend(this,{getShim:function(){return n.get(this.uid).content.Moxie},shimExec:function(e,t){var n=[].slice.call(arguments,2);return c.getShim().exec(this.uid,e,t,n)},init:function(){var e;e=this.getShimContainer(),e.innerHTML='',l=setTimeout(function(){c&&!c.initialized&&c.trigger("Error",new i.RuntimeError(i.RuntimeError.NOT_INIT_ERR))},"Windows"!==t.OS?1e4:5e3)},destroy:function(e){return function(){e.call(c),clearTimeout(l),a=l=e=c=null}}(this.destroy)},u)}var s="silverlight",u={};return r.addConstructor(s,a),u}),i(et,[Q,u,V],function(e,t,n){return e.Blob=t.extend({},n)}),i(tt,[Q],function(e){var t={init:function(e){function t(e){for(var t="",n=0;no;o++)n=t.keys[o],s=t[n],s&&(/^(\d|[1-9]\d+)$/.test(s)?s=parseInt(s,10):/^\d*\.\d+$/.test(s)&&(s=parseFloat(s)),i.meta[e][n]=s)}),i.width=parseInt(r.width,10),i.height=parseInt(r.height,10),i.size=parseInt(r.size,10),i.type=r.type,i.name=r.name,i}})}),i(ut,[u,h,g,d],function(e,t,n,i){function r(t){var r=this,s=n.capTest,u=n.capTrue;n.call(this,t,o,{access_binary:s(window.FileReader||window.File&&File.getAsDataURL),access_image_binary:!1,display_media:s(a.Image&&(i.can("create_canvas")||i.can("use_data_uri_over32kb"))),do_cors:!1,drag_and_drop:!1,filter_by_extension:s(function(){return"Chrome"===i.browser&&i.version>=28||"IE"===i.browser&&i.version>=10}()),resize_image:function(){return a.Image&&r.can("access_binary")&&i.can("create_canvas")},report_upload_progress:!1,return_response_headers:!1,return_response_type:function(t){return"json"===t&&window.JSON?!0:!!~e.inArray(t,["text","document",""])},return_status_code:function(t){return!e.arrayDiff(t,[200,404])},select_file:function(){return i.can("use_fileinput")},select_multiple:!1,send_binary_string:!1,send_custom_headers:!1,send_multipart:!0,slice_blob:!1,stream_upload:function(){return r.can("select_file")},summon_file_dialog:s(function(){return"Firefox"===i.browser&&i.version>=4||"Opera"===i.browser&&i.version>=12||!!~e.inArray(i.browser,["Chrome","Safari"])}()),upload_filesize:u,use_http_method:function(t){return!e.arrayDiff(t,["GET","POST"])}}),e.extend(this,{init:function(){this.trigger("Init")},destroy:function(e){return function(){e.call(r),e=r=null}}(this.destroy)}),e.extend(this.getShim(),a)}var o="html4",a={};return n.addConstructor(o,r),a}),i(ct,[ut,u,f,L,l,d],function(e,t,n,i,r,o){function a(){function e(){var r=this,l=r.getRuntime(),d,f,h,p,m,g;g=t.guid("uid_"),d=l.getShimContainer(),a&&(h=n.get(a+"_form"),h&&t.extend(h.style,{top:"100%"})),p=document.createElement("form"),p.setAttribute("id",g+"_form"),p.setAttribute("method","post"),p.setAttribute("enctype","multipart/form-data"),p.setAttribute("encoding","multipart/form-data"),t.extend(p.style,{overflow:"hidden",position:"absolute",top:0,left:0,width:"100%",height:"100%"}),m=document.createElement("input"),m.setAttribute("id",g),m.setAttribute("type","file"),m.setAttribute("name",c.name||"Filedata"),m.setAttribute("accept",u.join(",")),t.extend(m.style,{fontSize:"999px",opacity:0}),p.appendChild(m),d.appendChild(p),t.extend(m.style,{position:"absolute",top:0,left:0,width:"100%",height:"100%"}),"IE"===o.browser&&o.version<10&&t.extend(m.style,{filter:"progid:DXImageTransform.Microsoft.Alpha(opacity=0)"}),m.onchange=function(){var t;this.value&&(t=this.files?this.files[0]:{name:this.value},s=[t],this.onchange=function(){},e.call(r),r.bind("change",function i(){var e=n.get(g),t=n.get(g+"_form"),o;r.unbind("change",i),r.files.length&&e&&t&&(o=r.files[0],e.setAttribute("id",o.uid),t.setAttribute("id",o.uid+"_form"),t.setAttribute("target",o.uid+"_iframe")),e=t=null},998),m=p=null,r.trigger("change"))},l.can("summon_file_dialog")&&(f=n.get(c.browse_button),i.removeEvent(f,"click",r.uid),i.addEvent(f,"click",function(e){m&&!m.disabled&&m.click(),e.preventDefault()},r.uid)),a=g,d=h=f=null}var a,s=[],u=[],c;t.extend(this,{init:function(t){var o=this,a=o.getRuntime(),s;c=t,u=t.accept.mimes||r.extList2mimes(t.accept,a.can("filter_by_extension")),s=a.getShimContainer(),function(){var e,r,u;e=n.get(t.browse_button),a.can("summon_file_dialog")&&("static"===n.getStyle(e,"position")&&(e.style.position="relative"),r=parseInt(n.getStyle(e,"z-index"),10)||1,e.style.zIndex=r,s.style.zIndex=r-1),u=a.can("summon_file_dialog")?e:s,i.addEvent(u,"mouseover",function(){o.trigger("mouseenter")},o.uid),i.addEvent(u,"mouseout",function(){o.trigger("mouseleave")},o.uid),i.addEvent(u,"mousedown",function(){o.trigger("mousedown")},o.uid),i.addEvent(n.get(t.container),"mouseup",function(){o.trigger("mouseup")},o.uid),e=null}(),e.call(this),s=null,o.trigger({type:"ready",async:!0})},getFiles:function(){return s},disable:function(e){var t;(t=n.get(a))&&(t.disabled=!!e)},destroy:function(){var e=this.getRuntime(),t=e.getShim(),r=e.getShimContainer();i.removeAllEvents(r,this.uid),i.removeAllEvents(c&&n.get(c.container),this.uid),i.removeAllEvents(c&&n.get(c.browse_button),this.uid),r&&(r.innerHTML=""),t.removeInstance(this.uid),a=s=u=c=r=t=null}})}return e.FileInput=a}),i(lt,[ut,F],function(e,t){return e.FileReader=t}),i(dt,[ut,u,f,R,h,L,y,A],function(e,t,n,i,r,o,a,s){function u(){function e(e){var t=this,i,r,a,s,u=!1;if(l){if(i=l.id.replace(/_iframe$/,""),r=n.get(i+"_form")){for(a=r.getElementsByTagName("input"),s=a.length;s--;)switch(a[s].getAttribute("type")){case"hidden":a[s].parentNode.removeChild(a[s]);break;case"file":u=!0}a=[],u||r.parentNode.removeChild(r),r=null}setTimeout(function(){o.removeEvent(l,"load",t.uid),l.parentNode&&l.parentNode.removeChild(l);var n=t.getRuntime().getShimContainer();n.children.length||n.parentNode.removeChild(n),n=l=null,e()},1)}}var u,c,l;t.extend(this,{send:function(d,f){function h(){var n=m.getShimContainer()||document.body,r=document.createElement("div");r.innerHTML='',l=r.firstChild,n.appendChild(l),o.addEvent(l,"load",function(){var n;try{n=l.contentWindow.document||l.contentDocument||window.frames[l.id].document,/^4(0[0-9]|1[0-7]|2[2346])\s/.test(n.title)?u=n.title.replace(/^(\d+).*$/,"$1"):(u=200,c=t.trim(n.body.innerHTML),p.trigger({type:"progress",loaded:c.length,total:c.length}),w&&p.trigger({type:"uploadprogress",loaded:w.size||1025,total:w.size||1025}))}catch(r){if(!i.hasSameOrigin(d.url))return void e.call(p,function(){p.trigger("error")});u=404}e.call(p,function(){p.trigger("load")})},p.uid)}var p=this,m=p.getRuntime(),g,v,y,w;if(u=c=null,f instanceof s&&f.hasBlob()){if(w=f.getBlob(),g=w.uid,y=n.get(g),v=n.get(g+"_form"),!v)throw new r.DOMException(r.DOMException.NOT_FOUND_ERR)}else g=t.guid("uid_"),v=document.createElement("form"),v.setAttribute("id",g+"_form"),v.setAttribute("method",d.method),v.setAttribute("enctype","multipart/form-data"),v.setAttribute("encoding","multipart/form-data"),v.setAttribute("target",g+"_iframe"),m.getShimContainer().appendChild(v);f instanceof s&&f.each(function(e,n){if(e instanceof a)y&&y.setAttribute("name",n);else{var i=document.createElement("input");t.extend(i,{type:"hidden",name:n,value:e}),y?v.insertBefore(i,y):v.appendChild(i)}}),v.setAttribute("action",d.url),h(),v.submit(),p.trigger("loadstart")},getStatus:function(){return u},getResponse:function(e){if("json"===e&&"string"===t.typeOf(c)&&window.JSON)try{return JSON.parse(c.replace(/^\s*]*>/,"").replace(/<\/pre>\s*$/,""))}catch(n){return null}return c},abort:function(){var t=this;l&&l.contentWindow&&(l.contentWindow.stop?l.contentWindow.stop():l.contentWindow.document.execCommand?l.contentWindow.document.execCommand("Stop"):l.src="about:blank"),e.call(this,function(){t.dispatchEvent("abort")})}})}return e.XMLHttpRequest=u}),i(ft,[ut,X],function(e,t){return e.Image=t}),a([u,c,l,d,f,h,p,m,g,v,y,w,E,_,x,b,R,T,A,S,O,I,L])}(this);;(function(e){"use strict";var t={},n=e.moxie.core.utils.Basic.inArray;return function r(e){var i,s;for(i in e)s=typeof e[i],s==="object"&&!~n(i,["Exceptions","Env","Mime"])?r(e[i]):s==="function"&&(t[i]=e[i])}(e.moxie),t.Env=e.moxie.core.utils.Env,t.Mime=e.moxie.core.utils.Mime,t.Exceptions=e.moxie.core.Exceptions,e.mOxie=t,e.o||(e.o=t),t})(this); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/plupload.dev.js b/themes/default/js/plugins/plupload/plupload.dev.js new file mode 100644 index 000000000..732231ed9 --- /dev/null +++ b/themes/default/js/plugins/plupload/plupload.dev.js @@ -0,0 +1,2315 @@ +/** + * Plupload - multi-runtime File Uploader + * v2.1.2 + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + * + * Date: 2014-05-14 + */ +/** + * Plupload.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/*global mOxie:true */ + +;(function(window, o, undef) { + +var delay = window.setTimeout +, fileFilters = {} +; + +// convert plupload features to caps acceptable by mOxie +function normalizeCaps(settings) { + var features = settings.required_features, caps = {}; + + function resolve(feature, value, strict) { + // Feature notation is deprecated, use caps (this thing here is required for backward compatibility) + var map = { + chunks: 'slice_blob', + jpgresize: 'send_binary_string', + pngresize: 'send_binary_string', + progress: 'report_upload_progress', + multi_selection: 'select_multiple', + dragdrop: 'drag_and_drop', + drop_element: 'drag_and_drop', + headers: 'send_custom_headers', + urlstream_upload: 'send_binary_string', + canSendBinary: 'send_binary', + triggerDialog: 'summon_file_dialog' + }; + + if (map[feature]) { + caps[map[feature]] = value; + } else if (!strict) { + caps[feature] = value; + } + } + + if (typeof(features) === 'string') { + plupload.each(features.split(/\s*,\s*/), function(feature) { + resolve(feature, true); + }); + } else if (typeof(features) === 'object') { + plupload.each(features, function(value, feature) { + resolve(feature, value); + }); + } else if (features === true) { + // check settings for required features + if (settings.chunk_size > 0) { + caps.slice_blob = true; + } + + if (settings.resize.enabled || !settings.multipart) { + caps.send_binary_string = true; + } + + plupload.each(settings, function(value, feature) { + resolve(feature, !!value, true); // strict check + }); + } + + return caps; +} + +/** + * @module plupload + * @static + */ +var plupload = { + /** + * Plupload version will be replaced on build. + * + * @property VERSION + * @for Plupload + * @static + * @final + */ + VERSION : '2.1.2', + + /** + * Inital state of the queue and also the state ones it's finished all it's uploads. + * + * @property STOPPED + * @static + * @final + */ + STOPPED : 1, + + /** + * Upload process is running + * + * @property STARTED + * @static + * @final + */ + STARTED : 2, + + /** + * File is queued for upload + * + * @property QUEUED + * @static + * @final + */ + QUEUED : 1, + + /** + * File is being uploaded + * + * @property UPLOADING + * @static + * @final + */ + UPLOADING : 2, + + /** + * File has failed to be uploaded + * + * @property FAILED + * @static + * @final + */ + FAILED : 4, + + /** + * File has been uploaded successfully + * + * @property DONE + * @static + * @final + */ + DONE : 5, + + // Error constants used by the Error event + + /** + * Generic error for example if an exception is thrown inside Silverlight. + * + * @property GENERIC_ERROR + * @static + * @final + */ + GENERIC_ERROR : -100, + + /** + * HTTP transport error. For example if the server produces a HTTP status other than 200. + * + * @property HTTP_ERROR + * @static + * @final + */ + HTTP_ERROR : -200, + + /** + * Generic I/O error. For example if it wasn't possible to open the file stream on local machine. + * + * @property IO_ERROR + * @static + * @final + */ + IO_ERROR : -300, + + /** + * @property SECURITY_ERROR + * @static + * @final + */ + SECURITY_ERROR : -400, + + /** + * Initialization error. Will be triggered if no runtime was initialized. + * + * @property INIT_ERROR + * @static + * @final + */ + INIT_ERROR : -500, + + /** + * File size error. If the user selects a file that is too large it will be blocked and an error of this type will be triggered. + * + * @property FILE_SIZE_ERROR + * @static + * @final + */ + FILE_SIZE_ERROR : -600, + + /** + * File extension error. If the user selects a file that isn't valid according to the filters setting. + * + * @property FILE_EXTENSION_ERROR + * @static + * @final + */ + FILE_EXTENSION_ERROR : -601, + + /** + * Duplicate file error. If prevent_duplicates is set to true and user selects the same file again. + * + * @property FILE_DUPLICATE_ERROR + * @static + * @final + */ + FILE_DUPLICATE_ERROR : -602, + + /** + * Runtime will try to detect if image is proper one. Otherwise will throw this error. + * + * @property IMAGE_FORMAT_ERROR + * @static + * @final + */ + IMAGE_FORMAT_ERROR : -700, + + /** + * While working on files runtime may run out of memory and will throw this error. + * + * @since 2.1.2 + * @property MEMORY_ERROR + * @static + * @final + */ + MEMORY_ERROR : -701, + + /** + * Each runtime has an upper limit on a dimension of the image it can handle. If bigger, will throw this error. + * + * @property IMAGE_DIMENSIONS_ERROR + * @static + * @final + */ + IMAGE_DIMENSIONS_ERROR : -702, + + /** + * Mime type lookup table. + * + * @property mimeTypes + * @type Object + * @final + */ + mimeTypes : o.mimes, + + /** + * In some cases sniffing is the only way around :( + */ + ua: o.ua, + + /** + * Gets the true type of the built-in object (better version of typeof). + * @credits Angus Croll (http://javascriptweblog.wordpress.com/) + * + * @method typeOf + * @static + * @param {Object} o Object to check. + * @return {String} Object [[Class]] + */ + typeOf: o.typeOf, + + /** + * Extends the specified object with another object. + * + * @method extend + * @static + * @param {Object} target Object to extend. + * @param {Object..} obj Multiple objects to extend with. + * @return {Object} Same as target, the extended object. + */ + extend : o.extend, + + /** + * Generates an unique ID. This is 99.99% unique since it takes the current time and 5 random numbers. + * The only way a user would be able to get the same ID is if the two persons at the same exact milisecond manages + * to get 5 the same random numbers between 0-65535 it also uses a counter so each call will be guaranteed to be page unique. + * It's more probable for the earth to be hit with an ansteriod. You can also if you want to be 100% sure set the plupload.guidPrefix property + * to an user unique key. + * + * @method guid + * @static + * @return {String} Virtually unique id. + */ + guid : o.guid, + + /** + * Get array of DOM Elements by their ids. + * + * @method get + * @for Utils + * @param {String} id Identifier of the DOM Element + * @return {Array} + */ + get : function get(ids) { + var els = [], el; + + if (o.typeOf(ids) !== 'array') { + ids = [ids]; + } + + var i = ids.length; + while (i--) { + el = o.get(ids[i]); + if (el) { + els.push(el); + } + } + + return els.length ? els : null; + }, + + /** + * Executes the callback function for each item in array/object. If you return false in the + * callback it will break the loop. + * + * @method each + * @static + * @param {Object} obj Object to iterate. + * @param {function} callback Callback function to execute for each item. + */ + each : o.each, + + /** + * Returns the absolute x, y position of an Element. The position will be returned in a object with x, y fields. + * + * @method getPos + * @static + * @param {Element} node HTML element or element id to get x, y position from. + * @param {Element} root Optional root element to stop calculations at. + * @return {object} Absolute position of the specified element object with x, y fields. + */ + getPos : o.getPos, + + /** + * Returns the size of the specified node in pixels. + * + * @method getSize + * @static + * @param {Node} node Node to get the size of. + * @return {Object} Object with a w and h property. + */ + getSize : o.getSize, + + /** + * Encodes the specified string. + * + * @method xmlEncode + * @static + * @param {String} s String to encode. + * @return {String} Encoded string. + */ + xmlEncode : function(str) { + var xmlEncodeChars = {'<' : 'lt', '>' : 'gt', '&' : 'amp', '"' : 'quot', '\'' : '#39'}, xmlEncodeRegExp = /[<>&\"\']/g; + + return str ? ('' + str).replace(xmlEncodeRegExp, function(chr) { + return xmlEncodeChars[chr] ? '&' + xmlEncodeChars[chr] + ';' : chr; + }) : str; + }, + + /** + * Forces anything into an array. + * + * @method toArray + * @static + * @param {Object} obj Object with length field. + * @return {Array} Array object containing all items. + */ + toArray : o.toArray, + + /** + * Find an element in array and return it's index if present, otherwise return -1. + * + * @method inArray + * @static + * @param {mixed} needle Element to find + * @param {Array} array + * @return {Int} Index of the element, or -1 if not found + */ + inArray : o.inArray, + + /** + * Extends the language pack object with new items. + * + * @method addI18n + * @static + * @param {Object} pack Language pack items to add. + * @return {Object} Extended language pack object. + */ + addI18n : o.addI18n, + + /** + * Translates the specified string by checking for the english string in the language pack lookup. + * + * @method translate + * @static + * @param {String} str String to look for. + * @return {String} Translated string or the input string if it wasn't found. + */ + translate : o.translate, + + /** + * Checks if object is empty. + * + * @method isEmptyObj + * @static + * @param {Object} obj Object to check. + * @return {Boolean} + */ + isEmptyObj : o.isEmptyObj, + + /** + * Checks if specified DOM element has specified class. + * + * @method hasClass + * @static + * @param {Object} obj DOM element like object to add handler to. + * @param {String} name Class name + */ + hasClass : o.hasClass, + + /** + * Adds specified className to specified DOM element. + * + * @method addClass + * @static + * @param {Object} obj DOM element like object to add handler to. + * @param {String} name Class name + */ + addClass : o.addClass, + + /** + * Removes specified className from specified DOM element. + * + * @method removeClass + * @static + * @param {Object} obj DOM element like object to add handler to. + * @param {String} name Class name + */ + removeClass : o.removeClass, + + /** + * Returns a given computed style of a DOM element. + * + * @method getStyle + * @static + * @param {Object} obj DOM element like object. + * @param {String} name Style you want to get from the DOM element + */ + getStyle : o.getStyle, + + /** + * Adds an event handler to the specified object and store reference to the handler + * in objects internal Plupload registry (@see removeEvent). + * + * @method addEvent + * @static + * @param {Object} obj DOM element like object to add handler to. + * @param {String} name Name to add event listener to. + * @param {Function} callback Function to call when event occurs. + * @param {String} (optional) key that might be used to add specifity to the event record. + */ + addEvent : o.addEvent, + + /** + * Remove event handler from the specified object. If third argument (callback) + * is not specified remove all events with the specified name. + * + * @method removeEvent + * @static + * @param {Object} obj DOM element to remove event listener(s) from. + * @param {String} name Name of event listener to remove. + * @param {Function|String} (optional) might be a callback or unique key to match. + */ + removeEvent: o.removeEvent, + + /** + * Remove all kind of events from the specified object + * + * @method removeAllEvents + * @static + * @param {Object} obj DOM element to remove event listeners from. + * @param {String} (optional) unique key to match, when removing events. + */ + removeAllEvents: o.removeAllEvents, + + /** + * Cleans the specified name from national characters (diacritics). The result will be a name with only a-z, 0-9 and _. + * + * @method cleanName + * @static + * @param {String} s String to clean up. + * @return {String} Cleaned string. + */ + cleanName : function(name) { + var i, lookup; + + // Replace diacritics + lookup = [ + /[\300-\306]/g, 'A', /[\340-\346]/g, 'a', + /\307/g, 'C', /\347/g, 'c', + /[\310-\313]/g, 'E', /[\350-\353]/g, 'e', + /[\314-\317]/g, 'I', /[\354-\357]/g, 'i', + /\321/g, 'N', /\361/g, 'n', + /[\322-\330]/g, 'O', /[\362-\370]/g, 'o', + /[\331-\334]/g, 'U', /[\371-\374]/g, 'u' + ]; + + for (i = 0; i < lookup.length; i += 2) { + name = name.replace(lookup[i], lookup[i + 1]); + } + + // Replace whitespace + name = name.replace(/\s+/g, '_'); + + // Remove anything else + name = name.replace(/[^a-z0-9_\-\.]+/gi, ''); + + return name; + }, + + /** + * Builds a full url out of a base URL and an object with items to append as query string items. + * + * @method buildUrl + * @static + * @param {String} url Base URL to append query string items to. + * @param {Object} items Name/value object to serialize as a querystring. + * @return {String} String with url + serialized query string items. + */ + buildUrl : function(url, items) { + var query = ''; + + plupload.each(items, function(value, name) { + query += (query ? '&' : '') + encodeURIComponent(name) + '=' + encodeURIComponent(value); + }); + + if (query) { + url += (url.indexOf('?') > 0 ? '&' : '?') + query; + } + + return url; + }, + + /** + * Formats the specified number as a size string for example 1024 becomes 1 KB. + * + * @method formatSize + * @static + * @param {Number} size Size to format as string. + * @return {String} Formatted size string. + */ + formatSize : function(size) { + + if (size === undef || /\D/.test(size)) { + return plupload.translate('N/A'); + } + + function round(num, precision) { + return Math.round(num * Math.pow(10, precision)) / Math.pow(10, precision); + } + + var boundary = Math.pow(1024, 4); + + // TB + if (size > boundary) { + return round(size / boundary, 1) + " " + plupload.translate('tb'); + } + + // GB + if (size > (boundary/=1024)) { + return round(size / boundary, 1) + " " + plupload.translate('gb'); + } + + // MB + if (size > (boundary/=1024)) { + return round(size / boundary, 1) + " " + plupload.translate('mb'); + } + + // KB + if (size > 1024) { + return Math.round(size / 1024) + " " + plupload.translate('kb'); + } + + return size + " " + plupload.translate('b'); + }, + + + /** + * Parses the specified size string into a byte value. For example 10kb becomes 10240. + * + * @method parseSize + * @static + * @param {String|Number} size String to parse or number to just pass through. + * @return {Number} Size in bytes. + */ + parseSize : o.parseSizeStr, + + + /** + * A way to predict what runtime will be choosen in the current environment with the + * specified settings. + * + * @method predictRuntime + * @static + * @param {Object|String} config Plupload settings to check + * @param {String} [runtimes] Comma-separated list of runtimes to check against + * @return {String} Type of compatible runtime + */ + predictRuntime : function(config, runtimes) { + var up, runtime; + + up = new plupload.Uploader(config); + runtime = o.Runtime.thatCan(up.getOption().required_features, runtimes || config.runtimes); + up.destroy(); + return runtime; + }, + + /** + * Registers a filter that will be executed for each file added to the queue. + * If callback returns false, file will not be added. + * + * Callback receives two arguments: a value for the filter as it was specified in settings.filters + * and a file to be filtered. Callback is executed in the context of uploader instance. + * + * @method addFileFilter + * @static + * @param {String} name Name of the filter by which it can be referenced in settings.filters + * @param {String} cb Callback - the actual routine that every added file must pass + */ + addFileFilter: function(name, cb) { + fileFilters[name] = cb; + } +}; + + +plupload.addFileFilter('mime_types', function(filters, file, cb) { + if (filters.length && !filters.regexp.test(file.name)) { + this.trigger('Error', { + code : plupload.FILE_EXTENSION_ERROR, + message : plupload.translate('File extension error.'), + file : file + }); + cb(false); + } else { + cb(true); + } +}); + + +plupload.addFileFilter('max_file_size', function(maxSize, file, cb) { + var undef; + + maxSize = plupload.parseSize(maxSize); + + // Invalid file size + if (file.size !== undef && maxSize && file.size > maxSize) { + this.trigger('Error', { + code : plupload.FILE_SIZE_ERROR, + message : plupload.translate('File size error.'), + file : file + }); + cb(false); + } else { + cb(true); + } +}); + + +plupload.addFileFilter('prevent_duplicates', function(value, file, cb) { + if (value) { + var ii = this.files.length; + while (ii--) { + // Compare by name and size (size might be 0 or undefined, but still equivalent for both) + if (file.name === this.files[ii].name && file.size === this.files[ii].size) { + this.trigger('Error', { + code : plupload.FILE_DUPLICATE_ERROR, + message : plupload.translate('Duplicate file error.'), + file : file + }); + cb(false); + return; + } + } + } + cb(true); +}); + + +/** +@class Uploader +@constructor + +@param {Object} settings For detailed information about each option check documentation. + @param {String|DOMElement} settings.browse_button id of the DOM element or DOM element itself to use as file dialog trigger. + @param {String} settings.url URL of the server-side upload handler. + @param {Number|String} [settings.chunk_size=0] Chunk size in bytes to slice the file into. Shorcuts with b, kb, mb, gb, tb suffixes also supported. `e.g. 204800 or "204800b" or "200kb"`. By default - disabled. + @param {Boolean} [settings.send_chunk_number=true] Whether to send chunks and chunk numbers, or total and offset bytes. + @param {String} [settings.container] id of the DOM element to use as a container for uploader structures. Defaults to document.body. + @param {String|DOMElement} [settings.drop_element] id of the DOM element or DOM element itself to use as a drop zone for Drag-n-Drop. + @param {String} [settings.file_data_name="file"] Name for the file field in Multipart formated message. + @param {Object} [settings.filters={}] Set of file type filters. + @param {Array} [settings.filters.mime_types=[]] List of file types to accept, each one defined by title and list of extensions. `e.g. {title : "Image files", extensions : "jpg,jpeg,gif,png"}`. Dispatches `plupload.FILE_EXTENSION_ERROR` + @param {String|Number} [settings.filters.max_file_size=0] Maximum file size that the user can pick, in bytes. Optionally supports b, kb, mb, gb, tb suffixes. `e.g. "10mb" or "1gb"`. By default - not set. Dispatches `plupload.FILE_SIZE_ERROR`. + @param {Boolean} [settings.filters.prevent_duplicates=false] Do not let duplicates into the queue. Dispatches `plupload.FILE_DUPLICATE_ERROR`. + @param {String} [settings.flash_swf_url] URL of the Flash swf. + @param {Object} [settings.headers] Custom headers to send with the upload. Hash of name/value pairs. + @param {Number} [settings.max_retries=0] How many times to retry the chunk or file, before triggering Error event. + @param {Boolean} [settings.multipart=true] Whether to send file and additional parameters as Multipart formated message. + @param {Object} [settings.multipart_params] Hash of key/value pairs to send with every file upload. + @param {Boolean} [settings.multi_selection=true] Enable ability to select multiple files at once in file dialog. + @param {String|Object} [settings.required_features] Either comma-separated list or hash of required features that chosen runtime should absolutely possess. + @param {Object} [settings.resize] Enable resizng of images on client-side. Applies to `image/jpeg` and `image/png` only. `e.g. {width : 200, height : 200, quality : 90, crop: true}` + @param {Number} [settings.resize.width] If image is bigger, it will be resized. + @param {Number} [settings.resize.height] If image is bigger, it will be resized. + @param {Number} [settings.resize.quality=90] Compression quality for jpegs (1-100). + @param {Boolean} [settings.resize.crop=false] Whether to crop images to exact dimensions. By default they will be resized proportionally. + @param {String} [settings.runtimes="html5,flash,silverlight,html4"] Comma separated list of runtimes, that Plupload will try in turn, moving to the next if previous fails. + @param {String} [settings.silverlight_xap_url] URL of the Silverlight xap. + @param {Boolean} [settings.unique_names=false] If true will generate unique filenames for uploaded files. + @param {Boolean} [settings.send_file_name=true] Whether to send file name as additional argument - 'name' (required for chunked uploads and some other cases where file name cannot be sent via normal ways). +*/ +plupload.Uploader = function(options) { + /** + * Fires when the current RunTime has been initialized. + * + * @event Init + * @param {plupload.Uploader} uploader Uploader instance sending the event. + */ + + /** + * Fires after the init event incase you need to perform actions there. + * + * @event PostInit + * @param {plupload.Uploader} uploader Uploader instance sending the event. + */ + + /** + * Fires when the option is changed in via uploader.setOption(). + * + * @event OptionChanged + * @since 2.1 + * @param {plupload.Uploader} uploader Uploader instance sending the event. + * @param {String} name Name of the option that was changed + * @param {Mixed} value New value for the specified option + * @param {Mixed} oldValue Previous value of the option + */ + + /** + * Fires when the silverlight/flash or other shim needs to move. + * + * @event Refresh + * @param {plupload.Uploader} uploader Uploader instance sending the event. + */ + + /** + * Fires when the overall state is being changed for the upload queue. + * + * @event StateChanged + * @param {plupload.Uploader} uploader Uploader instance sending the event. + */ + + /** + * Fires when browse_button is clicked and browse dialog shows. + * + * @event Browse + * @since 2.1.2 + * @param {plupload.Uploader} uploader Uploader instance sending the event. + */ + + /** + * Fires for every filtered file before it is added to the queue. + * + * @event FileFiltered + * @since 2.1 + * @param {plupload.Uploader} uploader Uploader instance sending the event. + * @param {plupload.File} file Another file that has to be added to the queue. + */ + + /** + * Fires when the file queue is changed. In other words when files are added/removed to the files array of the uploader instance. + * + * @event QueueChanged + * @param {plupload.Uploader} uploader Uploader instance sending the event. + */ + + /** + * Fires after files were filtered and added to the queue. + * + * @event FilesAdded + * @param {plupload.Uploader} uploader Uploader instance sending the event. + * @param {Array} files Array of file objects that were added to queue by the user. + */ + + /** + * Fires when file is removed from the queue. + * + * @event FilesRemoved + * @param {plupload.Uploader} uploader Uploader instance sending the event. + * @param {Array} files Array of files that got removed. + */ + + /** + * Fires when just before a file is uploaded. This event enables you to override settings + * on the uploader instance before the file is uploaded. + * + * @event BeforeUpload + * @param {plupload.Uploader} uploader Uploader instance sending the event. + * @param {plupload.File} file File to be uploaded. + */ + + /** + * Fires when a file is to be uploaded by the runtime. + * + * @event UploadFile + * @param {plupload.Uploader} uploader Uploader instance sending the event. + * @param {plupload.File} file File to be uploaded. + */ + + /** + * Fires while a file is being uploaded. Use this event to update the current file upload progress. + * + * @event UploadProgress + * @param {plupload.Uploader} uploader Uploader instance sending the event. + * @param {plupload.File} file File that is currently being uploaded. + */ + + /** + * Fires when file chunk is uploaded. + * + * @event ChunkUploaded + * @param {plupload.Uploader} uploader Uploader instance sending the event. + * @param {plupload.File} file File that the chunk was uploaded for. + * @param {Object} response Object with response properties. + */ + + /** + * Fires when a file is successfully uploaded. + * + * @event FileUploaded + * @param {plupload.Uploader} uploader Uploader instance sending the event. + * @param {plupload.File} file File that was uploaded. + * @param {Object} response Object with response properties. + */ + + /** + * Fires when all files in a queue are uploaded. + * + * @event UploadComplete + * @param {plupload.Uploader} uploader Uploader instance sending the event. + * @param {Array} files Array of file objects that was added to queue/selected by the user. + */ + + /** + * Fires when a error occurs. + * + * @event Error + * @param {plupload.Uploader} uploader Uploader instance sending the event. + * @param {Object} error Contains code, message and sometimes file and other details. + */ + + /** + * Fires when destroy method is called. + * + * @event Destroy + * @param {plupload.Uploader} uploader Uploader instance sending the event. + */ + var uid = plupload.guid() + , settings + , files = [] + , preferred_caps = {} + , fileInputs = [] + , fileDrops = [] + , startTime + , total + , disabled = false + , xhr + ; + + + // Private methods + function uploadNext() { + var file, count = 0, i; + + if (this.state == plupload.STARTED) { + // Find first QUEUED file + for (i = 0; i < files.length; i++) { + if (!file && files[i].status == plupload.QUEUED) { + file = files[i]; + if (this.trigger("BeforeUpload", file)) { + file.status = plupload.UPLOADING; + this.trigger("UploadFile", file); + } + } else { + count++; + } + } + + // All files are DONE or FAILED + if (count == files.length) { + if (this.state !== plupload.STOPPED) { + this.state = plupload.STOPPED; + this.trigger("StateChanged"); + } + this.trigger("UploadComplete", files); + } + } + } + + + function calcFile(file) { + file.percent = file.size > 0 ? Math.ceil(file.loaded / file.size * 100) : 100; + calc(); + } + + + function calc() { + var i, file; + + // Reset stats + total.reset(); + + // Check status, size, loaded etc on all files + for (i = 0; i < files.length; i++) { + file = files[i]; + + if (file.size !== undef) { + // We calculate totals based on original file size + total.size += file.origSize; + + // Since we cannot predict file size after resize, we do opposite and + // interpolate loaded amount to match magnitude of total + total.loaded += file.loaded * file.origSize / file.size; + } else { + total.size = undef; + } + + if (file.status == plupload.DONE) { + total.uploaded++; + } else if (file.status == plupload.FAILED) { + total.failed++; + } else { + total.queued++; + } + } + + // If we couldn't calculate a total file size then use the number of files to calc percent + if (total.size === undef) { + total.percent = files.length > 0 ? Math.ceil(total.uploaded / files.length * 100) : 0; + } else { + total.bytesPerSec = Math.ceil(total.loaded / ((+new Date() - startTime || 1) / 1000.0)); + total.percent = total.size > 0 ? Math.ceil(total.loaded / total.size * 100) : 0; + } + } + + + function getRUID() { + var ctrl = fileInputs[0] || fileDrops[0]; + if (ctrl) { + return ctrl.getRuntime().uid; + } + return false; + } + + + function runtimeCan(file, cap) { + if (file.ruid) { + var info = o.Runtime.getInfo(file.ruid); + if (info) { + return info.can(cap); + } + } + return false; + } + + + function bindEventListeners() { + this.bind('FilesAdded FilesRemoved', function(up) { + up.trigger('QueueChanged'); + up.refresh(); + }); + + this.bind('CancelUpload', onCancelUpload); + + this.bind('BeforeUpload', onBeforeUpload); + + this.bind('UploadFile', onUploadFile); + + this.bind('UploadProgress', onUploadProgress); + + this.bind('StateChanged', onStateChanged); + + this.bind('QueueChanged', calc); + + this.bind('Error', onError); + + this.bind('FileUploaded', onFileUploaded); + + this.bind('Destroy', onDestroy); + } + + + function initControls(settings, cb) { + var self = this, inited = 0, queue = []; + + // common settings + var options = { + runtime_order: settings.runtimes, + required_caps: settings.required_features, + preferred_caps: preferred_caps, + swf_url: settings.flash_swf_url, + xap_url: settings.silverlight_xap_url + }; + + // add runtime specific options if any + plupload.each(settings.runtimes.split(/\s*,\s*/), function(runtime) { + if (settings[runtime]) { + options[runtime] = settings[runtime]; + } + }); + + // initialize file pickers - there can be many + if (settings.browse_button) { + plupload.each(settings.browse_button, function(el) { + queue.push(function(cb) { + var fileInput = new o.FileInput(plupload.extend({}, options, { + accept: settings.filters.mime_types, + name: settings.file_data_name, + multiple: settings.multi_selection, + container: settings.container, + browse_button: el + })); + + fileInput.onready = function() { + var info = o.Runtime.getInfo(this.ruid); + + // for backward compatibility + o.extend(self.features, { + chunks: info.can('slice_blob'), + multipart: info.can('send_multipart'), + multi_selection: info.can('select_multiple') + }); + + inited++; + fileInputs.push(this); + cb(); + }; + + fileInput.onchange = function() { + self.addFile(this.files); + }; + + fileInput.bind('mouseenter mouseleave mousedown mouseup', function(e) { + if (!disabled) { + if (settings.browse_button_hover) { + if ('mouseenter' === e.type) { + o.addClass(el, settings.browse_button_hover); + } else if ('mouseleave' === e.type) { + o.removeClass(el, settings.browse_button_hover); + } + } + + if (settings.browse_button_active) { + if ('mousedown' === e.type) { + o.addClass(el, settings.browse_button_active); + } else if ('mouseup' === e.type) { + o.removeClass(el, settings.browse_button_active); + } + } + } + }); + + fileInput.bind('mousedown', function() { + self.trigger('Browse'); + }); + + fileInput.bind('error runtimeerror', function() { + fileInput = null; + cb(); + }); + + fileInput.init(); + }); + }); + } + + // initialize drop zones + if (settings.drop_element) { + plupload.each(settings.drop_element, function(el) { + queue.push(function(cb) { + var fileDrop = new o.FileDrop(plupload.extend({}, options, { + drop_zone: el + })); + + fileDrop.onready = function() { + var info = o.Runtime.getInfo(this.ruid); + + self.features.dragdrop = info.can('drag_and_drop'); // for backward compatibility + + inited++; + fileDrops.push(this); + cb(); + }; + + fileDrop.ondrop = function() { + self.addFile(this.files); + }; + + fileDrop.bind('error runtimeerror', function() { + fileDrop = null; + cb(); + }); + + fileDrop.init(); + }); + }); + } + + + o.inSeries(queue, function() { + if (typeof(cb) === 'function') { + cb(inited); + } + }); + } + + + function resizeImage(blob, params, cb) { + var img = new o.Image(); + + try { + img.onload = function() { + // no manipulation required if... + if (params.width > this.width && + params.height > this.height && + params.quality === undef && + params.preserve_headers && + !params.crop + ) { + this.destroy(); + return cb(blob); + } + // otherwise downsize + img.downsize(params.width, params.height, params.crop, params.preserve_headers); + }; + + img.onresize = function() { + cb(this.getAsBlob(blob.type, params.quality)); + this.destroy(); + }; + + img.onerror = function() { + cb(blob); + }; + + img.load(blob); + } catch(ex) { + cb(blob); + } + } + + + function setOption(option, value, init) { + var self = this, reinitRequired = false; + + function _setOption(option, value, init) { + var oldValue = settings[option]; + + switch (option) { + case 'max_file_size': + if (option === 'max_file_size') { + settings.max_file_size = settings.filters.max_file_size = value; + } + break; + + case 'chunk_size': + if (value = plupload.parseSize(value)) { + settings[option] = value; + settings.send_file_name = true; + } + break; + + case 'multipart': + settings[option] = value; + if (!value) { + settings.send_file_name = true; + } + break; + + case 'unique_names': + settings[option] = value; + if (value) { + settings.send_file_name = true; + } + break; + + case 'filters': + // for sake of backward compatibility + if (plupload.typeOf(value) === 'array') { + value = { + mime_types: value + }; + } + + if (init) { + plupload.extend(settings.filters, value); + } else { + settings.filters = value; + } + + // if file format filters are being updated, regenerate the matching expressions + if (value.mime_types) { + settings.filters.mime_types.regexp = (function(filters) { + var extensionsRegExp = []; + + plupload.each(filters, function(filter) { + plupload.each(filter.extensions.split(/,/), function(ext) { + if (/^\s*\*\s*$/.test(ext)) { + extensionsRegExp.push('\\.*'); + } else { + extensionsRegExp.push('\\.' + ext.replace(new RegExp('[' + ('/^$.*+?|()[]{}\\'.replace(/./g, '\\$&')) + ']', 'g'), '\\$&')); + } + }); + }); + + return new RegExp('(' + extensionsRegExp.join('|') + ')$', 'i'); + }(settings.filters.mime_types)); + } + break; + + case 'resize': + if (init) { + plupload.extend(settings.resize, value, { + enabled: true + }); + } else { + settings.resize = value; + } + break; + + case 'prevent_duplicates': + settings.prevent_duplicates = settings.filters.prevent_duplicates = !!value; + break; + + case 'browse_button': + case 'drop_element': + value = plupload.get(value); + + case 'container': + case 'runtimes': + case 'multi_selection': + case 'flash_swf_url': + case 'silverlight_xap_url': + settings[option] = value; + if (!init) { + reinitRequired = true; + } + break; + + default: + settings[option] = value; + } + + if (!init) { + self.trigger('OptionChanged', option, value, oldValue); + } + } + + if (typeof(option) === 'object') { + plupload.each(option, function(value, option) { + _setOption(option, value, init); + }); + } else { + _setOption(option, value, init); + } + + if (init) { + // Normalize the list of required capabilities + settings.required_features = normalizeCaps(plupload.extend({}, settings)); + + // Come up with the list of capabilities that can affect default mode in a multi-mode runtimes + preferred_caps = normalizeCaps(plupload.extend({}, settings, { + required_features: true + })); + } else if (reinitRequired) { + self.trigger('Destroy'); + + initControls.call(self, settings, function(inited) { + if (inited) { + self.runtime = o.Runtime.getInfo(getRUID()).type; + self.trigger('Init', { runtime: self.runtime }); + self.trigger('PostInit'); + } else { + self.trigger('Error', { + code : plupload.INIT_ERROR, + message : plupload.translate('Init error.') + }); + } + }); + } + } + + + // Internal event handlers + function onBeforeUpload(up, file) { + // Generate unique target filenames + if (up.settings.unique_names) { + var matches = file.name.match(/\.([^.]+)$/), ext = "part"; + if (matches) { + ext = matches[1]; + } + file.target_name = file.id + '.' + ext; + } + } + + + function onUploadFile(up, file) { + var url = up.settings.url + , chunkSize = up.settings.chunk_size + , retries = up.settings.max_retries + , features = up.features + , offset = 0 + , blob + ; + + // make sure we start at a predictable offset + if (file.loaded) { + offset = file.loaded = chunkSize ? chunkSize * Math.floor(file.loaded / chunkSize) : 0; + } + + function handleError() { + if (retries-- > 0) { + delay(uploadNextChunk, 1000); + } else { + file.loaded = offset; // reset all progress + + up.trigger('Error', { + code : plupload.HTTP_ERROR, + message : plupload.translate('HTTP Error.'), + file : file, + response : xhr.responseText, + status : xhr.status, + responseHeaders: xhr.getAllResponseHeaders() + }); + } + } + + function uploadNextChunk() { + var chunkBlob, formData, args = {}, curChunkSize; + + // make sure that file wasn't cancelled and upload is not stopped in general + if (file.status !== plupload.UPLOADING || up.state === plupload.STOPPED) { + return; + } + + // send additional 'name' parameter only if required + if (up.settings.send_file_name) { + args.name = file.target_name || file.name; + } + + if (chunkSize && features.chunks && blob.size > chunkSize) { // blob will be of type string if it was loaded in memory + curChunkSize = Math.min(chunkSize, blob.size - offset); + chunkBlob = blob.slice(offset, offset + curChunkSize); + } else { + curChunkSize = blob.size; + chunkBlob = blob; + } + + // If chunking is enabled add corresponding args, no matter if file is bigger than chunk or smaller + if (chunkSize && features.chunks) { + // Setup query string arguments + if (up.settings.send_chunk_number) { + args.chunk = Math.ceil(offset / chunkSize); + args.chunks = Math.ceil(blob.size / chunkSize); + } else { // keep support for experimental chunk format, just in case + args.offset = offset; + args.total = blob.size; + } + } + + xhr = new o.XMLHttpRequest(); + + // Do we have upload progress support + if (xhr.upload) { + xhr.upload.onprogress = function(e) { + file.loaded = Math.min(file.size, offset + e.loaded); + up.trigger('UploadProgress', file); + }; + } + + xhr.onload = function() { + // check if upload made itself through + if (xhr.status >= 400) { + handleError(); + return; + } + + retries = up.settings.max_retries; // reset the counter + + // Handle chunk response + if (curChunkSize < blob.size) { + chunkBlob.destroy(); + + offset += curChunkSize; + file.loaded = Math.min(offset, blob.size); + + up.trigger('ChunkUploaded', file, { + offset : file.loaded, + total : blob.size, + response : xhr.responseText, + status : xhr.status, + responseHeaders: xhr.getAllResponseHeaders() + }); + + // stock Android browser doesn't fire upload progress events, but in chunking mode we can fake them + if (o.Env.browser === 'Android Browser') { + // doesn't harm in general, but is not required anywhere else + up.trigger('UploadProgress', file); + } + } else { + file.loaded = file.size; + } + + chunkBlob = formData = null; // Free memory + + // Check if file is uploaded + if (!offset || offset >= blob.size) { + // If file was modified, destory the copy + if (file.size != file.origSize) { + blob.destroy(); + blob = null; + } + + up.trigger('UploadProgress', file); + + file.status = plupload.DONE; + + up.trigger('FileUploaded', file, { + response : xhr.responseText, + status : xhr.status, + responseHeaders: xhr.getAllResponseHeaders() + }); + } else { + // Still chunks left + delay(uploadNextChunk, 1); // run detached, otherwise event handlers interfere + } + }; + + xhr.onerror = function() { + handleError(); + }; + + xhr.onloadend = function() { + this.destroy(); + xhr = null; + }; + + // Build multipart request + if (up.settings.multipart && features.multipart) { + xhr.open("post", url, true); + + // Set custom headers + plupload.each(up.settings.headers, function(value, name) { + xhr.setRequestHeader(name, value); + }); + + formData = new o.FormData(); + + // Add multipart params + plupload.each(plupload.extend(args, up.settings.multipart_params), function(value, name) { + formData.append(name, value); + }); + + // Add file and send it + formData.append(up.settings.file_data_name, chunkBlob); + xhr.send(formData, { + runtime_order: up.settings.runtimes, + required_caps: up.settings.required_features, + preferred_caps: preferred_caps, + swf_url: up.settings.flash_swf_url, + xap_url: up.settings.silverlight_xap_url + }); + } else { + // if no multipart, send as binary stream + url = plupload.buildUrl(up.settings.url, plupload.extend(args, up.settings.multipart_params)); + + xhr.open("post", url, true); + + xhr.setRequestHeader('Content-Type', 'application/octet-stream'); // Binary stream header + + // Set custom headers + plupload.each(up.settings.headers, function(value, name) { + xhr.setRequestHeader(name, value); + }); + + xhr.send(chunkBlob, { + runtime_order: up.settings.runtimes, + required_caps: up.settings.required_features, + preferred_caps: preferred_caps, + swf_url: up.settings.flash_swf_url, + xap_url: up.settings.silverlight_xap_url + }); + } + } + + blob = file.getSource(); + + // Start uploading chunks + if (up.settings.resize.enabled && runtimeCan(blob, 'send_binary_string') && !!~o.inArray(blob.type, ['image/jpeg', 'image/png'])) { + // Resize if required + resizeImage.call(this, blob, up.settings.resize, function(resizedBlob) { + blob = resizedBlob; + file.size = resizedBlob.size; + uploadNextChunk(); + }); + } else { + uploadNextChunk(); + } + } + + + function onUploadProgress(up, file) { + calcFile(file); + } + + + function onStateChanged(up) { + if (up.state == plupload.STARTED) { + // Get start time to calculate bps + startTime = (+new Date()); + } else if (up.state == plupload.STOPPED) { + // Reset currently uploading files + for (var i = up.files.length - 1; i >= 0; i--) { + if (up.files[i].status == plupload.UPLOADING) { + up.files[i].status = plupload.QUEUED; + calc(); + } + } + } + } + + + function onCancelUpload() { + if (xhr) { + xhr.abort(); + } + } + + + function onFileUploaded(up) { + calc(); + + // Upload next file but detach it from the error event + // since other custom listeners might want to stop the queue + delay(function() { + uploadNext.call(up); + }, 1); + } + + + function onError(up, err) { + if (err.code === plupload.INIT_ERROR) { + up.destroy(); + } + // Set failed status if an error occured on a file + else if (err.file) { + err.file.status = plupload.FAILED; + calcFile(err.file); + + // Upload next file but detach it from the error event + // since other custom listeners might want to stop the queue + if (up.state == plupload.STARTED) { // upload in progress + up.trigger('CancelUpload'); + delay(function() { + uploadNext.call(up); + }, 1); + } + } + } + + + function onDestroy(up) { + up.stop(); + + // Purge the queue + plupload.each(files, function(file) { + file.destroy(); + }); + files = []; + + if (fileInputs.length) { + plupload.each(fileInputs, function(fileInput) { + fileInput.destroy(); + }); + fileInputs = []; + } + + if (fileDrops.length) { + plupload.each(fileDrops, function(fileDrop) { + fileDrop.destroy(); + }); + fileDrops = []; + } + + preferred_caps = {}; + disabled = false; + startTime = xhr = null; + total.reset(); + } + + + // Default settings + settings = { + runtimes: o.Runtime.order, + max_retries: 0, + chunk_size: 0, + multipart: true, + multi_selection: true, + file_data_name: 'file', + flash_swf_url: 'js/Moxie.swf', + silverlight_xap_url: 'js/Moxie.xap', + filters: { + mime_types: [], + prevent_duplicates: false, + max_file_size: 0 + }, + resize: { + enabled: false, + preserve_headers: true, + crop: false + }, + send_file_name: true, + send_chunk_number: true + }; + + + setOption.call(this, options, null, true); + + // Inital total state + total = new plupload.QueueProgress(); + + // Add public methods + plupload.extend(this, { + + /** + * Unique id for the Uploader instance. + * + * @property id + * @type String + */ + id : uid, + uid : uid, // mOxie uses this to differentiate between event targets + + /** + * Current state of the total uploading progress. This one can either be plupload.STARTED or plupload.STOPPED. + * These states are controlled by the stop/start methods. The default value is STOPPED. + * + * @property state + * @type Number + */ + state : plupload.STOPPED, + + /** + * Map of features that are available for the uploader runtime. Features will be filled + * before the init event is called, these features can then be used to alter the UI for the end user. + * Some of the current features that might be in this map is: dragdrop, chunks, jpgresize, pngresize. + * + * @property features + * @type Object + */ + features : {}, + + /** + * Current runtime name. + * + * @property runtime + * @type String + */ + runtime : null, + + /** + * Current upload queue, an array of File instances. + * + * @property files + * @type Array + * @see plupload.File + */ + files : files, + + /** + * Object with name/value settings. + * + * @property settings + * @type Object + */ + settings : settings, + + /** + * Total progess information. How many files has been uploaded, total percent etc. + * + * @property total + * @type plupload.QueueProgress + */ + total : total, + + + /** + * Initializes the Uploader instance and adds internal event listeners. + * + * @method init + */ + init : function() { + var self = this; + + if (typeof(settings.preinit) == "function") { + settings.preinit(self); + } else { + plupload.each(settings.preinit, function(func, name) { + self.bind(name, func); + }); + } + + bindEventListeners.call(this); + + // Check for required options + if (!settings.browse_button || !settings.url) { + this.trigger('Error', { + code : plupload.INIT_ERROR, + message : plupload.translate('Init error.') + }); + return; + } + + initControls.call(this, settings, function(inited) { + if (typeof(settings.init) == "function") { + settings.init(self); + } else { + plupload.each(settings.init, function(func, name) { + self.bind(name, func); + }); + } + + if (inited) { + self.runtime = o.Runtime.getInfo(getRUID()).type; + self.trigger('Init', { runtime: self.runtime }); + self.trigger('PostInit'); + } else { + self.trigger('Error', { + code : plupload.INIT_ERROR, + message : plupload.translate('Init error.') + }); + } + }); + }, + + /** + * Set the value for the specified option(s). + * + * @method setOption + * @since 2.1 + * @param {String|Object} option Name of the option to change or the set of key/value pairs + * @param {Mixed} [value] Value for the option (is ignored, if first argument is object) + */ + setOption: function(option, value) { + setOption.call(this, option, value, !this.runtime); // until runtime not set we do not need to reinitialize + }, + + /** + * Get the value for the specified option or the whole configuration, if not specified. + * + * @method getOption + * @since 2.1 + * @param {String} [option] Name of the option to get + * @return {Mixed} Value for the option or the whole set + */ + getOption: function(option) { + if (!option) { + return settings; + } + return settings[option]; + }, + + /** + * Refreshes the upload instance by dispatching out a refresh event to all runtimes. + * This would for example reposition flash/silverlight shims on the page. + * + * @method refresh + */ + refresh : function() { + if (fileInputs.length) { + plupload.each(fileInputs, function(fileInput) { + fileInput.trigger('Refresh'); + }); + } + this.trigger('Refresh'); + }, + + /** + * Starts uploading the queued files. + * + * @method start + */ + start : function() { + if (this.state != plupload.STARTED) { + this.state = plupload.STARTED; + this.trigger('StateChanged'); + + uploadNext.call(this); + } + }, + + /** + * Stops the upload of the queued files. + * + * @method stop + */ + stop : function() { + if (this.state != plupload.STOPPED) { + this.state = plupload.STOPPED; + this.trigger('StateChanged'); + this.trigger('CancelUpload'); + } + }, + + + /** + * Disables/enables browse button on request. + * + * @method disableBrowse + * @param {Boolean} disable Whether to disable or enable (default: true) + */ + disableBrowse : function() { + disabled = arguments[0] !== undef ? arguments[0] : true; + + if (fileInputs.length) { + plupload.each(fileInputs, function(fileInput) { + fileInput.disable(disabled); + }); + } + + this.trigger('DisableBrowse', disabled); + }, + + /** + * Returns the specified file object by id. + * + * @method getFile + * @param {String} id File id to look for. + * @return {plupload.File} File object or undefined if it wasn't found; + */ + getFile : function(id) { + var i; + for (i = files.length - 1; i >= 0; i--) { + if (files[i].id === id) { + return files[i]; + } + } + }, + + /** + * Adds file to the queue programmatically. Can be native file, instance of Plupload.File, + * instance of mOxie.File, input[type="file"] element, or array of these. Fires FilesAdded, + * if any files were added to the queue. Otherwise nothing happens. + * + * @method addFile + * @since 2.0 + * @param {plupload.File|mOxie.File|File|Node|Array} file File or files to add to the queue. + * @param {String} [fileName] If specified, will be used as a name for the file + */ + addFile : function(file, fileName) { + var self = this + , queue = [] + , filesAdded = [] + , ruid + ; + + function filterFile(file, cb) { + var queue = []; + o.each(self.settings.filters, function(rule, name) { + if (fileFilters[name]) { + queue.push(function(cb) { + fileFilters[name].call(self, rule, file, function(res) { + cb(!res); + }); + }); + } + }); + o.inSeries(queue, cb); + } + + /** + * @method resolveFile + * @private + * @param {o.File|o.Blob|plupload.File|File|Blob|input[type="file"]} file + */ + function resolveFile(file) { + var type = o.typeOf(file); + + // o.File + if (file instanceof o.File) { + if (!file.ruid && !file.isDetached()) { + if (!ruid) { // weird case + return false; + } + file.ruid = ruid; + file.connectRuntime(ruid); + } + resolveFile(new plupload.File(file)); + } + // o.Blob + else if (file instanceof o.Blob) { + resolveFile(file.getSource()); + file.destroy(); + } + // plupload.File - final step for other branches + else if (file instanceof plupload.File) { + if (fileName) { + file.name = fileName; + } + + queue.push(function(cb) { + // run through the internal and user-defined filters, if any + filterFile(file, function(err) { + if (!err) { + // make files available for the filters by updating the main queue directly + files.push(file); + // collect the files that will be passed to FilesAdded event + filesAdded.push(file); + + self.trigger("FileFiltered", file); + } + delay(cb, 1); // do not build up recursions or eventually we might hit the limits + }); + }); + } + // native File or blob + else if (o.inArray(type, ['file', 'blob']) !== -1) { + resolveFile(new o.File(null, file)); + } + // input[type="file"] + else if (type === 'node' && o.typeOf(file.files) === 'filelist') { + // if we are dealing with input[type="file"] + o.each(file.files, resolveFile); + } + // mixed array of any supported types (see above) + else if (type === 'array') { + fileName = null; // should never happen, but unset anyway to avoid funny situations + o.each(file, resolveFile); + } + } + + ruid = getRUID(); + + resolveFile(file); + + if (queue.length) { + o.inSeries(queue, function() { + // if any files left after filtration, trigger FilesAdded + if (filesAdded.length) { + self.trigger("FilesAdded", filesAdded); + } + }); + } + }, + + /** + * Removes a specific file. + * + * @method removeFile + * @param {plupload.File|String} file File to remove from queue. + */ + removeFile : function(file) { + var id = typeof(file) === 'string' ? file : file.id; + + for (var i = files.length - 1; i >= 0; i--) { + if (files[i].id === id) { + return this.splice(i, 1)[0]; + } + } + }, + + /** + * Removes part of the queue and returns the files removed. This will also trigger the FilesRemoved and QueueChanged events. + * + * @method splice + * @param {Number} start (Optional) Start index to remove from. + * @param {Number} length (Optional) Lengh of items to remove. + * @return {Array} Array of files that was removed. + */ + splice : function(start, length) { + // Splice and trigger events + var removed = files.splice(start === undef ? 0 : start, length === undef ? files.length : length); + + // if upload is in progress we need to stop it and restart after files are removed + var restartRequired = false; + if (this.state == plupload.STARTED) { // upload in progress + plupload.each(removed, function(file) { + if (file.status === plupload.UPLOADING) { + restartRequired = true; // do not restart, unless file that is being removed is uploading + return false; + } + }); + + if (restartRequired) { + this.stop(); + } + } + + this.trigger("FilesRemoved", removed); + + // Dispose any resources allocated by those files + plupload.each(removed, function(file) { + file.destroy(); + }); + + if (restartRequired) { + this.start(); + } + + return removed; + }, + + /** + * Dispatches the specified event name and it's arguments to all listeners. + * + * + * @method trigger + * @param {String} name Event name to fire. + * @param {Object..} Multiple arguments to pass along to the listener functions. + */ + + /** + * Check whether uploader has any listeners to the specified event. + * + * @method hasEventListener + * @param {String} name Event name to check for. + */ + + + /** + * Adds an event listener by name. + * + * @method bind + * @param {String} name Event name to listen for. + * @param {function} func Function to call ones the event gets fired. + * @param {Object} scope Optional scope to execute the specified function in. + */ + bind : function(name, func, scope) { + var self = this; + // adapt moxie EventTarget style to Plupload-like + plupload.Uploader.prototype.bind.call(this, name, function() { + var args = [].slice.call(arguments); + args.splice(0, 1, self); // replace event object with uploader instance + return func.apply(this, args); + }, 0, scope); + }, + + /** + * Removes the specified event listener. + * + * @method unbind + * @param {String} name Name of event to remove. + * @param {function} func Function to remove from listener. + */ + + /** + * Removes all event listeners. + * + * @method unbindAll + */ + + + /** + * Destroys Plupload instance and cleans after itself. + * + * @method destroy + */ + destroy : function() { + this.trigger('Destroy'); + settings = total = null; // purge these exclusively + this.unbindAll(); + } + }); +}; + +plupload.Uploader.prototype = o.EventTarget.instance; + +/** + * Constructs a new file instance. + * + * @class File + * @constructor + * + * @param {Object} file Object containing file properties + * @param {String} file.name Name of the file. + * @param {Number} file.size File size. + */ +plupload.File = (function() { + var filepool = {}; + + function PluploadFile(file) { + + plupload.extend(this, { + + /** + * File id this is a globally unique id for the specific file. + * + * @property id + * @type String + */ + id: plupload.guid(), + + /** + * File name for example "myfile.gif". + * + * @property name + * @type String + */ + name: file.name || file.fileName, + + /** + * File type, `e.g image/jpeg` + * + * @property type + * @type String + */ + type: file.type || '', + + /** + * File size in bytes (may change after client-side manupilation). + * + * @property size + * @type Number + */ + size: file.size || file.fileSize, + + /** + * Original file size in bytes. + * + * @property origSize + * @type Number + */ + origSize: file.size || file.fileSize, + + /** + * Number of bytes uploaded of the files total size. + * + * @property loaded + * @type Number + */ + loaded: 0, + + /** + * Number of percentage uploaded of the file. + * + * @property percent + * @type Number + */ + percent: 0, + + /** + * Status constant matching the plupload states QUEUED, UPLOADING, FAILED, DONE. + * + * @property status + * @type Number + * @see plupload + */ + status: plupload.QUEUED, + + /** + * Date of last modification. + * + * @property lastModifiedDate + * @type {String} + */ + lastModifiedDate: file.lastModifiedDate || (new Date()).toLocaleString(), // Thu Aug 23 2012 19:40:00 GMT+0400 (GET) + + /** + * Returns native window.File object, when it's available. + * + * @method getNative + * @return {window.File} or null, if plupload.File is of different origin + */ + getNative: function() { + var file = this.getSource().getSource(); + return o.inArray(o.typeOf(file), ['blob', 'file']) !== -1 ? file : null; + }, + + /** + * Returns mOxie.File - unified wrapper object that can be used across runtimes. + * + * @method getSource + * @return {mOxie.File} or null + */ + getSource: function() { + if (!filepool[this.id]) { + return null; + } + return filepool[this.id]; + }, + + /** + * Destroys plupload.File object. + * + * @method destroy + */ + destroy: function() { + var src = this.getSource(); + if (src) { + src.destroy(); + delete filepool[this.id]; + } + } + }); + + filepool[this.id] = file; + } + + return PluploadFile; +}()); + + +/** + * Constructs a queue progress. + * + * @class QueueProgress + * @constructor + */ + plupload.QueueProgress = function() { + var self = this; // Setup alias for self to reduce code size when it's compressed + + /** + * Total queue file size. + * + * @property size + * @type Number + */ + self.size = 0; + + /** + * Total bytes uploaded. + * + * @property loaded + * @type Number + */ + self.loaded = 0; + + /** + * Number of files uploaded. + * + * @property uploaded + * @type Number + */ + self.uploaded = 0; + + /** + * Number of files failed to upload. + * + * @property failed + * @type Number + */ + self.failed = 0; + + /** + * Number of files yet to be uploaded. + * + * @property queued + * @type Number + */ + self.queued = 0; + + /** + * Total percent of the uploaded bytes. + * + * @property percent + * @type Number + */ + self.percent = 0; + + /** + * Bytes uploaded per second. + * + * @property bytesPerSec + * @type Number + */ + self.bytesPerSec = 0; + + /** + * Resets the progress to it's initial values. + * + * @method reset + */ + self.reset = function() { + self.size = self.loaded = self.uploaded = self.failed = self.queued = self.percent = self.bytesPerSec = 0; + }; +}; + +window.plupload = plupload; + +}(window, mOxie)); diff --git a/themes/default/js/plugins/plupload/plupload.full.min.js b/themes/default/js/plugins/plupload/plupload.full.min.js new file mode 100644 index 000000000..ca6cdf82d --- /dev/null +++ b/themes/default/js/plugins/plupload/plupload.full.min.js @@ -0,0 +1,28 @@ +/** + * mOxie - multi-runtime File API & XMLHttpRequest L2 Polyfill + * v1.2.1 + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + * + * Date: 2014-05-14 + */ +!function(e,t){"use strict";function n(e,t){for(var n,i=[],r=0;r0&&n(o,function(n,o){n!==r&&(e(i[o])===e(n)&&~a(e(n),["array","object"])?t(i[o],n):i[o]=n)})}),i},n=function(e,t){var n,i,r,o;if(e){try{n=e.length}catch(a){n=o}if(n===o){for(i in e)if(e.hasOwnProperty(i)&&t(e[i],i)===!1)return}else for(r=0;n>r;r++)if(t(e[r],r)===!1)return}},i=function(t){var n;if(!t||"object"!==e(t))return!0;for(n in t)return!1;return!0},r=function(t,n){function i(r){"function"===e(t[r])&&t[r](function(e){++rn;n++)if(t[n]===e)return n}return-1},s=function(t,n){var i=[];"array"!==e(t)&&(t=[t]),"array"!==e(n)&&(n=[n]);for(var r in t)-1===a(t[r],n)&&i.push(t[r]);return i.length?i:!1},u=function(e,t){var i=[];return n(e,function(e){-1!==a(e,t)&&i.push(e)}),i.length?i:null},c=function(e){var t,n=[];for(t=0;ti;i++)n+=Math.floor(65535*Math.random()).toString(32);return(t||"o_")+n+(e++).toString(32)}}(),d=function(e){return e?String.prototype.trim?String.prototype.trim.call(e):e.toString().replace(/^\s*/,"").replace(/\s*$/,""):e},f=function(e){if("string"!=typeof e)return e;var t={t:1099511627776,g:1073741824,m:1048576,k:1024},n;return e=/^([0-9]+)([mgk]?)$/.exec(e.toLowerCase().replace(/[^0-9mkg]/g,"")),n=e[2],e=+e[1],t.hasOwnProperty(n)&&(e*=t[n]),e};return{guid:l,typeOf:e,extend:t,each:n,isEmptyObj:i,inSeries:r,inParallel:o,inArray:a,arrayDiff:s,arrayIntersect:u,toArray:c,trim:d,parseSizeStr:f}}),i(c,[u],function(e){var t={};return{addI18n:function(n){return e.extend(t,n)},translate:function(e){return t[e]||e},_:function(e){return this.translate(e)},sprintf:function(t){var n=[].slice.call(arguments,1);return t.replace(/%[a-z]/g,function(){var t=n.shift();return"undefined"!==e.typeOf(t)?t:""})}}}),i(l,[u,c],function(e,t){var n="application/msword,doc dot,application/pdf,pdf,application/pgp-signature,pgp,application/postscript,ps ai eps,application/rtf,rtf,application/vnd.ms-excel,xls xlb,application/vnd.ms-powerpoint,ppt pps pot,application/zip,zip,application/x-shockwave-flash,swf swfl,application/vnd.openxmlformats-officedocument.wordprocessingml.document,docx,application/vnd.openxmlformats-officedocument.wordprocessingml.template,dotx,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,xlsx,application/vnd.openxmlformats-officedocument.presentationml.presentation,pptx,application/vnd.openxmlformats-officedocument.presentationml.template,potx,application/vnd.openxmlformats-officedocument.presentationml.slideshow,ppsx,application/x-javascript,js,application/json,json,audio/mpeg,mp3 mpga mpega mp2,audio/x-wav,wav,audio/x-m4a,m4a,audio/ogg,oga ogg,audio/aiff,aiff aif,audio/flac,flac,audio/aac,aac,audio/ac3,ac3,audio/x-ms-wma,wma,image/bmp,bmp,image/gif,gif,image/jpeg,jpg jpeg jpe,image/photoshop,psd,image/png,png,image/svg+xml,svg svgz,image/tiff,tiff tif,text/plain,asc txt text diff log,text/html,htm html xhtml,text/css,css,text/csv,csv,text/rtf,rtf,video/mpeg,mpeg mpg mpe m2v,video/quicktime,qt mov,video/mp4,mp4,video/x-m4v,m4v,video/x-flv,flv,video/x-ms-wmv,wmv,video/avi,avi,video/webm,webm,video/3gpp,3gpp 3gp,video/3gpp2,3g2,video/vnd.rn-realvideo,rv,video/ogg,ogv,video/x-matroska,mkv,application/vnd.oasis.opendocument.formula-template,otf,application/octet-stream,exe",i={mimes:{},extensions:{},addMimeType:function(e){var t=e.split(/,/),n,i,r;for(n=0;ni;i++)if(e[i]!=t[i]){if(e[i]=u(e[i]),t[i]=u(t[i]),e[i]t[i]){o=1;break}}if(!n)return o;switch(n){case">":case"gt":return o>0;case">=":case"ge":return o>=0;case"<=":case"le":return 0>=o;case"==":case"=":case"eq":return 0===o;case"<>":case"!=":case"ne":return 0!==o;case"":case"<":case"lt":return 0>o;default:return null}}var n=function(e){var t="",n="?",i="function",r="undefined",o="object",a="major",s="model",u="name",c="type",l="vendor",d="version",f="architecture",h="console",p="mobile",m="tablet",g={has:function(e,t){return-1!==t.toLowerCase().indexOf(e.toLowerCase())},lowerize:function(e){return e.toLowerCase()}},v={rgx:function(){for(var t,n=0,a,s,u,c,l,d,f=arguments;n0?2==c.length?t[c[0]]=typeof c[1]==i?c[1].call(this,d):c[1]:3==c.length?t[c[0]]=typeof c[1]!==i||c[1].exec&&c[1].test?d?d.replace(c[1],c[2]):e:d?c[1].call(this,d,c[2]):e:4==c.length&&(t[c[0]]=d?c[3].call(this,d.replace(c[1],c[2])):e):t[c]=d?d:e;break}if(l)break}return t},str:function(t,i){for(var r in i)if(typeof i[r]===o&&i[r].length>0){for(var a=0;a=9)},use_data_uri_of:function(e){return t.use_data_uri&&33e3>e||t.use_data_uri_over32kb()},use_fileinput:function(){var e=document.createElement("input");return e.setAttribute("type","file"),!e.disabled}};return function(n){var i=[].slice.call(arguments);return i.shift(),"function"===e.typeOf(t[n])?t[n].apply(this,i):!!t[n]}}(),r={can:i,browser:n.browser.name,version:parseFloat(n.browser.major),os:n.os.name,osVersion:n.os.version,verComp:t,swf_url:"../flash/Moxie.swf",xap_url:"../silverlight/Moxie.xap",global_event_dispatcher:"moxie.core.EventTarget.instance.dispatchEvent"};return r.OS=r.os,r}),i(f,[d],function(e){var t=function(e){return"string"!=typeof e?e:document.getElementById(e)},n=function(e,t){if(!e.className)return!1;var n=new RegExp("(^|\\s+)"+t+"(\\s+|$)");return n.test(e.className)},i=function(e,t){n(e,t)||(e.className=e.className?e.className.replace(/\s+$/,"")+" "+t:t)},r=function(e,t){if(e.className){var n=new RegExp("(^|\\s+)"+t+"(\\s+|$)");e.className=e.className.replace(n,function(e,t,n){return" "===t&&" "===n?" ":""})}},o=function(e,t){return e.currentStyle?e.currentStyle[t]:window.getComputedStyle?window.getComputedStyle(e,null)[t]:void 0},a=function(t,n){function i(e){var t,n,i=0,r=0;return e&&(n=e.getBoundingClientRect(),t="CSS1Compat"===s.compatMode?s.documentElement:s.body,i=n.left+t.scrollLeft,r=n.top+t.scrollTop),{x:i,y:r}}var r=0,o=0,a,s=document,u,c;if(t=t,n=n||s.body,t&&t.getBoundingClientRect&&"IE"===e.browser&&(!s.documentMode||s.documentMode<8))return u=i(t),c=i(n),{x:u.x-c.x,y:u.y-c.y};for(a=t;a&&a!=n&&a.nodeType;)r+=a.offsetLeft||0,o+=a.offsetTop||0,a=a.offsetParent;for(a=t.parentNode;a&&a!=n&&a.nodeType;)r-=a.scrollLeft||0,o-=a.scrollTop||0,a=a.parentNode;return{x:r,y:o}},s=function(e){return{w:e.offsetWidth||e.clientWidth,h:e.offsetHeight||e.clientHeight}};return{get:t,hasClass:n,addClass:i,removeClass:r,getStyle:o,getPos:a,getSize:s}}),i(h,[u],function(e){function t(e,t){var n;for(n in e)if(e[n]===t)return n;return null}return{RuntimeError:function(){function n(e){this.code=e,this.name=t(i,e),this.message=this.name+": RuntimeError "+this.code}var i={NOT_INIT_ERR:1,NOT_SUPPORTED_ERR:9,JS_ERR:4};return e.extend(n,i),n.prototype=Error.prototype,n}(),OperationNotAllowedException:function(){function t(e){this.code=e,this.name="OperationNotAllowedException"}return e.extend(t,{NOT_ALLOWED_ERR:1}),t.prototype=Error.prototype,t}(),ImageError:function(){function n(e){this.code=e,this.name=t(i,e),this.message=this.name+": ImageError "+this.code}var i={WRONG_FORMAT:1,MAX_RESOLUTION_ERR:2};return e.extend(n,i),n.prototype=Error.prototype,n}(),FileException:function(){function n(e){this.code=e,this.name=t(i,e),this.message=this.name+": FileException "+this.code}var i={NOT_FOUND_ERR:1,SECURITY_ERR:2,ABORT_ERR:3,NOT_READABLE_ERR:4,ENCODING_ERR:5,NO_MODIFICATION_ALLOWED_ERR:6,INVALID_STATE_ERR:7,SYNTAX_ERR:8};return e.extend(n,i),n.prototype=Error.prototype,n}(),DOMException:function(){function n(e){this.code=e,this.name=t(i,e),this.message=this.name+": DOMException "+this.code}var i={INDEX_SIZE_ERR:1,DOMSTRING_SIZE_ERR:2,HIERARCHY_REQUEST_ERR:3,WRONG_DOCUMENT_ERR:4,INVALID_CHARACTER_ERR:5,NO_DATA_ALLOWED_ERR:6,NO_MODIFICATION_ALLOWED_ERR:7,NOT_FOUND_ERR:8,NOT_SUPPORTED_ERR:9,INUSE_ATTRIBUTE_ERR:10,INVALID_STATE_ERR:11,SYNTAX_ERR:12,INVALID_MODIFICATION_ERR:13,NAMESPACE_ERR:14,INVALID_ACCESS_ERR:15,VALIDATION_ERR:16,TYPE_MISMATCH_ERR:17,SECURITY_ERR:18,NETWORK_ERR:19,ABORT_ERR:20,URL_MISMATCH_ERR:21,QUOTA_EXCEEDED_ERR:22,TIMEOUT_ERR:23,INVALID_NODE_TYPE_ERR:24,DATA_CLONE_ERR:25};return e.extend(n,i),n.prototype=Error.prototype,n}(),EventException:function(){function t(e){this.code=e,this.name="EventException"}return e.extend(t,{UNSPECIFIED_EVENT_TYPE_ERR:0}),t.prototype=Error.prototype,t}()}}),i(p,[h,u],function(e,t){function n(){var n={};t.extend(this,{uid:null,init:function(){this.uid||(this.uid=t.guid("uid_"))},addEventListener:function(e,i,r,o){var a=this,s;return e=t.trim(e),/\s/.test(e)?void t.each(e.split(/\s+/),function(e){a.addEventListener(e,i,r,o)}):(e=e.toLowerCase(),r=parseInt(r,10)||0,s=n[this.uid]&&n[this.uid][e]||[],s.push({fn:i,priority:r,scope:o||this}),n[this.uid]||(n[this.uid]={}),void(n[this.uid][e]=s))},hasEventListener:function(e){return e?!(!n[this.uid]||!n[this.uid][e]):!!n[this.uid]},removeEventListener:function(e,i){e=e.toLowerCase();var r=n[this.uid]&&n[this.uid][e],o;if(r){if(i){for(o=r.length-1;o>=0;o--)if(r[o].fn===i){r.splice(o,1);break}}else r=[];r.length||(delete n[this.uid][e],t.isEmptyObj(n[this.uid])&&delete n[this.uid])}},removeAllEventListeners:function(){n[this.uid]&&delete n[this.uid]},dispatchEvent:function(i){var r,o,a,s,u={},c=!0,l;if("string"!==t.typeOf(i)){if(s=i,"string"!==t.typeOf(s.type))throw new e.EventException(e.EventException.UNSPECIFIED_EVENT_TYPE_ERR);i=s.type,s.total!==l&&s.loaded!==l&&(u.total=s.total,u.loaded=s.loaded),u.async=s.async||!1}if(-1!==i.indexOf("::")?!function(e){r=e[0],i=e[1]}(i.split("::")):r=this.uid,i=i.toLowerCase(),o=n[r]&&n[r][i]){o.sort(function(e,t){return t.priority-e.priority}),a=[].slice.call(arguments),a.shift(),u.type=i,a.unshift(u);var d=[];t.each(o,function(e){a[0].target=e.scope,d.push(u.async?function(t){setTimeout(function(){t(e.fn.apply(e.scope,a)===!1)},1)}:function(t){t(e.fn.apply(e.scope,a)===!1)})}),d.length&&t.inSeries(d,function(e){c=!e})}return c},bind:function(){this.addEventListener.apply(this,arguments)},unbind:function(){this.removeEventListener.apply(this,arguments)},unbindAll:function(){this.removeAllEventListeners.apply(this,arguments)},trigger:function(){return this.dispatchEvent.apply(this,arguments)},convertEventPropsToHandlers:function(e){var n;"array"!==t.typeOf(e)&&(e=[e]);for(var i=0;i>16&255,o=d>>8&255,a=255&d,m[h++]=64==c?String.fromCharCode(r):64==l?String.fromCharCode(r,o):String.fromCharCode(r,o,a);while(f>18&63,u=d>>12&63,c=d>>6&63,l=63&d,m[h++]=i.charAt(s)+i.charAt(u)+i.charAt(c)+i.charAt(l);while(fa;a++)o+=String.fromCharCode(r[a]);return o}}t.call(this),e.extend(this,{uid:e.guid("uid_"),readAsBinaryString:function(e){return i.call(this,"readAsBinaryString",e)},readAsDataURL:function(e){return i.call(this,"readAsDataURL",e)},readAsText:function(e){return i.call(this,"readAsText",e)}})}}),i(A,[h,u,y],function(e,t,n){function i(){var e,i=[];t.extend(this,{append:function(r,o){var a=this,s=t.typeOf(o);o instanceof n?e={name:r,value:o}:"array"===s?(r+="[]",t.each(o,function(e){a.append(r,e)})):"object"===s?t.each(o,function(e,t){a.append(r+"["+t+"]",e)}):"null"===s||"undefined"===s||"number"===s&&isNaN(o)?a.append(r,"false"):i.push({name:r,value:o.toString()})},hasBlob:function(){return!!this.getBlob()},getBlob:function(){return e&&e.value||null},getBlobName:function(){return e&&e.name||null},each:function(n){t.each(i,function(e){n(e.value,e.name)}),e&&n(e.value,e.name)},destroy:function(){e=null,i=[]}})}return i}),i(S,[u,h,p,m,R,g,x,y,T,A,d,l],function(e,t,n,i,r,o,a,s,u,c,l,d){function f(){this.uid=e.guid("uid_")}function h(){function n(e,t){return y.hasOwnProperty(e)?1===arguments.length?l.can("define_property")?y[e]:v[e]:void(l.can("define_property")?y[e]=t:v[e]=t):void 0}function u(t){function i(){k&&(k.destroy(),k=null),s.dispatchEvent("loadend"),s=null}function r(r){k.bind("LoadStart",function(e){n("readyState",h.LOADING),s.dispatchEvent("readystatechange"),s.dispatchEvent(e),I&&s.upload.dispatchEvent(e)}),k.bind("Progress",function(e){n("readyState")!==h.LOADING&&(n("readyState",h.LOADING),s.dispatchEvent("readystatechange")),s.dispatchEvent(e)}),k.bind("UploadProgress",function(e){I&&s.upload.dispatchEvent({type:"progress",lengthComputable:!1,total:e.total,loaded:e.loaded})}),k.bind("Load",function(t){n("readyState",h.DONE),n("status",Number(r.exec.call(k,"XMLHttpRequest","getStatus")||0)),n("statusText",p[n("status")]||""),n("response",r.exec.call(k,"XMLHttpRequest","getResponse",n("responseType"))),~e.inArray(n("responseType"),["text",""])?n("responseText",n("response")):"document"===n("responseType")&&n("responseXML",n("response")),U=r.exec.call(k,"XMLHttpRequest","getAllResponseHeaders"),s.dispatchEvent("readystatechange"),n("status")>0?(I&&s.upload.dispatchEvent(t),s.dispatchEvent(t)):(N=!0,s.dispatchEvent("error")),i()}),k.bind("Abort",function(e){s.dispatchEvent(e),i()}),k.bind("Error",function(e){N=!0,n("readyState",h.DONE),s.dispatchEvent("readystatechange"),D=!0,s.dispatchEvent(e),i()}),r.exec.call(k,"XMLHttpRequest","send",{url:E,method:_,async:w,user:b,password:R,headers:x,mimeType:A,encoding:T,responseType:s.responseType,withCredentials:s.withCredentials,options:P},t)}var s=this;M=(new Date).getTime(),k=new a,"string"==typeof P.required_caps&&(P.required_caps=o.parseCaps(P.required_caps)),P.required_caps=e.extend({},P.required_caps,{return_response_type:s.responseType}),t instanceof c&&(P.required_caps.send_multipart=!0),L||(P.required_caps.do_cors=!0),P.ruid?r(k.connectRuntime(P)):(k.bind("RuntimeInit",function(e,t){r(t)}),k.bind("RuntimeError",function(e,t){s.dispatchEvent("RuntimeError",t)}),k.connectRuntime(P))}function g(){n("responseText",""),n("responseXML",null),n("response",null),n("status",0),n("statusText",""),M=C=null}var v=this,y={timeout:0,readyState:h.UNSENT,withCredentials:!1,status:0,statusText:"",responseType:"",responseXML:null,responseText:null,response:null},w=!0,E,_,x={},b,R,T=null,A=null,S=!1,O=!1,I=!1,D=!1,N=!1,L=!1,M,C,F=null,H=null,P={},k,U="",B;e.extend(this,y,{uid:e.guid("uid_"),upload:new f,open:function(o,a,s,u,c){var l;if(!o||!a)throw new t.DOMException(t.DOMException.SYNTAX_ERR);if(/[\u0100-\uffff]/.test(o)||i.utf8_encode(o)!==o)throw new t.DOMException(t.DOMException.SYNTAX_ERR);if(~e.inArray(o.toUpperCase(),["CONNECT","DELETE","GET","HEAD","OPTIONS","POST","PUT","TRACE","TRACK"])&&(_=o.toUpperCase()),~e.inArray(_,["CONNECT","TRACE","TRACK"]))throw new t.DOMException(t.DOMException.SECURITY_ERR);if(a=i.utf8_encode(a),l=r.parseUrl(a),L=r.hasSameOrigin(l),E=r.resolveUrl(a),(u||c)&&!L)throw new t.DOMException(t.DOMException.INVALID_ACCESS_ERR);if(b=u||l.user,R=c||l.pass,w=s||!0,w===!1&&(n("timeout")||n("withCredentials")||""!==n("responseType")))throw new t.DOMException(t.DOMException.INVALID_ACCESS_ERR);S=!w,O=!1,x={},g.call(this),n("readyState",h.OPENED),this.convertEventPropsToHandlers(["readystatechange"]),this.dispatchEvent("readystatechange")},setRequestHeader:function(r,o){var a=["accept-charset","accept-encoding","access-control-request-headers","access-control-request-method","connection","content-length","cookie","cookie2","content-transfer-encoding","date","expect","host","keep-alive","origin","referer","te","trailer","transfer-encoding","upgrade","user-agent","via"];if(n("readyState")!==h.OPENED||O)throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);if(/[\u0100-\uffff]/.test(r)||i.utf8_encode(r)!==r)throw new t.DOMException(t.DOMException.SYNTAX_ERR);return r=e.trim(r).toLowerCase(),~e.inArray(r,a)||/^(proxy\-|sec\-)/.test(r)?!1:(x[r]?x[r]+=", "+o:x[r]=o,!0)},getAllResponseHeaders:function(){return U||""},getResponseHeader:function(t){return t=t.toLowerCase(),N||~e.inArray(t,["set-cookie","set-cookie2"])?null:U&&""!==U&&(B||(B={},e.each(U.split(/\r\n/),function(t){var n=t.split(/:\s+/);2===n.length&&(n[0]=e.trim(n[0]),B[n[0].toLowerCase()]={header:n[0],value:e.trim(n[1])})})),B.hasOwnProperty(t))?B[t].header+": "+B[t].value:null},overrideMimeType:function(i){var r,o;if(~e.inArray(n("readyState"),[h.LOADING,h.DONE]))throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);if(i=e.trim(i.toLowerCase()),/;/.test(i)&&(r=i.match(/^([^;]+)(?:;\scharset\=)?(.*)$/))&&(i=r[1],r[2]&&(o=r[2])),!d.mimes[i])throw new t.DOMException(t.DOMException.SYNTAX_ERR);F=i,H=o},send:function(n,r){if(P="string"===e.typeOf(r)?{ruid:r}:r?r:{},this.convertEventPropsToHandlers(m),this.upload.convertEventPropsToHandlers(m),this.readyState!==h.OPENED||O)throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);if(n instanceof s)P.ruid=n.ruid,A=n.type||"application/octet-stream";else if(n instanceof c){if(n.hasBlob()){var o=n.getBlob();P.ruid=o.ruid,A=o.type||"application/octet-stream"}}else"string"==typeof n&&(T="UTF-8",A="text/plain;charset=UTF-8",n=i.utf8_encode(n));this.withCredentials||(this.withCredentials=P.required_caps&&P.required_caps.send_browser_cookies&&!L),I=!S&&this.upload.hasEventListener(),N=!1,D=!n,S||(O=!0),u.call(this,n)},abort:function(){if(N=!0,S=!1,~e.inArray(n("readyState"),[h.UNSENT,h.OPENED,h.DONE]))n("readyState",h.UNSENT);else{if(n("readyState",h.DONE),O=!1,!k)throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);k.getRuntime().exec.call(k,"XMLHttpRequest","abort",D),D=!0}},destroy:function(){k&&("function"===e.typeOf(k.destroy)&&k.destroy(),k=null),this.unbindAll(),this.upload&&(this.upload.unbindAll(),this.upload=null)}})}var p={100:"Continue",101:"Switching Protocols",102:"Processing",200:"OK",201:"Created",202:"Accepted",203:"Non-Authoritative Information",204:"No Content",205:"Reset Content",206:"Partial Content",207:"Multi-Status",226:"IM Used",300:"Multiple Choices",301:"Moved Permanently",302:"Found",303:"See Other",304:"Not Modified",305:"Use Proxy",306:"Reserved",307:"Temporary Redirect",400:"Bad Request",401:"Unauthorized",402:"Payment Required",403:"Forbidden",404:"Not Found",405:"Method Not Allowed",406:"Not Acceptable",407:"Proxy Authentication Required",408:"Request Timeout",409:"Conflict",410:"Gone",411:"Length Required",412:"Precondition Failed",413:"Request Entity Too Large",414:"Request-URI Too Long",415:"Unsupported Media Type",416:"Requested Range Not Satisfiable",417:"Expectation Failed",422:"Unprocessable Entity",423:"Locked",424:"Failed Dependency",426:"Upgrade Required",500:"Internal Server Error",501:"Not Implemented",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout",505:"HTTP Version Not Supported",506:"Variant Also Negotiates",507:"Insufficient Storage",510:"Not Extended"};f.prototype=n.instance;var m=["loadstart","progress","abort","error","load","timeout","loadend"],g=1,v=2;return h.UNSENT=0,h.OPENED=1,h.HEADERS_RECEIVED=2,h.LOADING=3,h.DONE=4,h.prototype=n.instance,h}),i(O,[u,m,v,p],function(e,t,n,i){function r(){function i(){l=d=0,c=this.result=null}function o(t,n){var i=this;u=n,i.bind("TransportingProgress",function(t){d=t.loaded,l>d&&-1===e.inArray(i.state,[r.IDLE,r.DONE])&&a.call(i)},999),i.bind("TransportingComplete",function(){d=l,i.state=r.DONE,c=null,i.result=u.exec.call(i,"Transporter","getAsBlob",t||"")},999),i.state=r.BUSY,i.trigger("TransportingStarted"),a.call(i)}function a(){var e=this,n,i=l-d;f>i&&(f=i),n=t.btoa(c.substr(d,f)),u.exec.call(e,"Transporter","receive",n,l)}var s,u,c,l,d,f;n.call(this),e.extend(this,{uid:e.guid("uid_"),state:r.IDLE,result:null,transport:function(t,n,r){var a=this;if(r=e.extend({chunk_size:204798},r),(s=r.chunk_size%3)&&(r.chunk_size+=3-s),f=r.chunk_size,i.call(this),c=t,l=t.length,"string"===e.typeOf(r)||r.ruid)o.call(a,n,this.connectRuntime(r));else{var u=function(e,t){a.unbind("RuntimeInit",u),o.call(a,n,t)};this.bind("RuntimeInit",u),this.connectRuntime(r)}},abort:function(){var e=this;e.state=r.IDLE,u&&(u.exec.call(e,"Transporter","clear"),e.trigger("TransportingAborted")),i.call(e)},destroy:function(){this.unbindAll(),u=null,this.disconnectRuntime(),i.call(this)}})}return r.IDLE=0,r.BUSY=1,r.DONE=2,r.prototype=i.instance,r}),i(I,[u,f,h,T,S,g,v,O,d,p,y,w,m],function(e,t,n,i,r,o,a,s,u,c,l,d,f){function h(){function i(e){e||(e=this.getRuntime().exec.call(this,"Image","getInfo")),this.size=e.size,this.width=e.width,this.height=e.height,this.type=e.type,this.meta=e.meta,""===this.name&&(this.name=e.name)}function c(t){var i=e.typeOf(t);try{if(t instanceof h){if(!t.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);m.apply(this,arguments)}else if(t instanceof l){if(!~e.inArray(t.type,["image/jpeg","image/png"]))throw new n.ImageError(n.ImageError.WRONG_FORMAT);g.apply(this,arguments)}else if(-1!==e.inArray(i,["blob","file"]))c.call(this,new d(null,t),arguments[1]);else if("string"===i)/^data:[^;]*;base64,/.test(t)?c.call(this,new l(null,{data:t}),arguments[1]):v.apply(this,arguments);else{if("node"!==i||"img"!==t.nodeName.toLowerCase())throw new n.DOMException(n.DOMException.TYPE_MISMATCH_ERR);c.call(this,t.src,arguments[1])}}catch(r){this.trigger("error",r.code)}}function m(t,n){var i=this.connectRuntime(t.ruid);this.ruid=i.uid,i.exec.call(this,"Image","loadFromImage",t,"undefined"===e.typeOf(n)?!0:n)}function g(t,n){function i(e){r.ruid=e.uid,e.exec.call(r,"Image","loadFromBlob",t)}var r=this;r.name=t.name||"",t.isDetached()?(this.bind("RuntimeInit",function(e,t){i(t)}),n&&"string"==typeof n.required_caps&&(n.required_caps=o.parseCaps(n.required_caps)),this.connectRuntime(e.extend({required_caps:{access_image_binary:!0,resize_image:!0}},n))):i(this.connectRuntime(t.ruid))}function v(e,t){var n=this,i;i=new r,i.open("get",e),i.responseType="blob",i.onprogress=function(e){n.trigger(e)},i.onload=function(){g.call(n,i.response,!0)},i.onerror=function(e){n.trigger(e)},i.onloadend=function(){i.destroy()},i.bind("RuntimeError",function(e,t){n.trigger("RuntimeError",t)}),i.send(null,t)}a.call(this),e.extend(this,{uid:e.guid("uid_"),ruid:null,name:"",size:0,width:0,height:0,type:"",meta:{},clone:function(){this.load.apply(this,arguments)},load:function(){this.bind("Load Resize",function(){i.call(this)},999),this.convertEventPropsToHandlers(p),c.apply(this,arguments)},downsize:function(t){var i={width:this.width,height:this.height,crop:!1,preserveHeaders:!0};t="object"==typeof t?e.extend(i,t):e.extend(i,{width:arguments[0],height:arguments[1],crop:arguments[2],preserveHeaders:arguments[3]});try{if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);if(this.width>h.MAX_RESIZE_WIDTH||this.height>h.MAX_RESIZE_HEIGHT)throw new n.ImageError(n.ImageError.MAX_RESOLUTION_ERR);this.getRuntime().exec.call(this,"Image","downsize",t.width,t.height,t.crop,t.preserveHeaders)}catch(r){this.trigger("error",r.code)}},crop:function(e,t,n){this.downsize(e,t,!0,n)},getAsCanvas:function(){if(!u.can("create_canvas"))throw new n.RuntimeError(n.RuntimeError.NOT_SUPPORTED_ERR);var e=this.connectRuntime(this.ruid);return e.exec.call(this,"Image","getAsCanvas")},getAsBlob:function(e,t){if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);return e||(e="image/jpeg"),"image/jpeg"!==e||t||(t=90),this.getRuntime().exec.call(this,"Image","getAsBlob",e,t)},getAsDataURL:function(e,t){if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);return this.getRuntime().exec.call(this,"Image","getAsDataURL",e,t)},getAsBinaryString:function(e,t){var n=this.getAsDataURL(e,t);return f.atob(n.substring(n.indexOf("base64,")+7))},embed:function(i){function r(){if(u.can("create_canvas")){var t=a.getAsCanvas();if(t)return i.appendChild(t),t=null,a.destroy(),void o.trigger("embedded")}var r=a.getAsDataURL(c,l);if(!r)throw new n.ImageError(n.ImageError.WRONG_FORMAT);if(u.can("use_data_uri_of",r.length))i.innerHTML='',a.destroy(),o.trigger("embedded");else{var d=new s;d.bind("TransportingComplete",function(){v=o.connectRuntime(this.result.ruid),o.bind("Embedded",function(){e.extend(v.getShimContainer().style,{top:"0px",left:"0px",width:a.width+"px",height:a.height+"px"}),v=null},999),v.exec.call(o,"ImageView","display",this.result.uid,m,g),a.destroy()}),d.transport(f.atob(r.substring(r.indexOf("base64,")+7)),c,e.extend({},p,{required_caps:{display_media:!0},runtime_order:"flash,silverlight",container:i}))}}var o=this,a,c,l,d,p=arguments[1]||{},m=this.width,g=this.height,v;try{if(!(i=t.get(i)))throw new n.DOMException(n.DOMException.INVALID_NODE_TYPE_ERR);if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);if(this.width>h.MAX_RESIZE_WIDTH||this.height>h.MAX_RESIZE_HEIGHT)throw new n.ImageError(n.ImageError.MAX_RESOLUTION_ERR);if(c=p.type||this.type||"image/jpeg",l=p.quality||90,d="undefined"!==e.typeOf(p.crop)?p.crop:!1,p.width)m=p.width,g=p.height||m;else{var y=t.getSize(i);y.w&&y.h&&(m=y.w,g=y.h)}return a=new h,a.bind("Resize",function(){r.call(o)}),a.bind("Load",function(){a.downsize(m,g,d,!1)}),a.clone(this,!1),a}catch(w){this.trigger("error",w.code)}},destroy:function(){this.ruid&&(this.getRuntime().exec.call(this,"Image","destroy"),this.disconnectRuntime()),this.unbindAll()}})}var p=["progress","load","error","resize","embedded"];return h.MAX_RESIZE_WIDTH=6500,h.MAX_RESIZE_HEIGHT=6500,h.prototype=c.instance,h}),i(D,[u,h,g,d],function(e,t,n,i){function r(t){var r=this,s=n.capTest,u=n.capTrue,c=e.extend({access_binary:s(window.FileReader||window.File&&window.File.getAsDataURL),access_image_binary:function(){return r.can("access_binary")&&!!a.Image},display_media:s(i.can("create_canvas")||i.can("use_data_uri_over32kb")),do_cors:s(window.XMLHttpRequest&&"withCredentials"in new XMLHttpRequest),drag_and_drop:s(function(){var e=document.createElement("div");return("draggable"in e||"ondragstart"in e&&"ondrop"in e)&&("IE"!==i.browser||i.version>9)}()),filter_by_extension:s(function(){return"Chrome"===i.browser&&i.version>=28||"IE"===i.browser&&i.version>=10}()),return_response_headers:u,return_response_type:function(e){return"json"===e&&window.JSON?!0:i.can("return_response_type",e)},return_status_code:u,report_upload_progress:s(window.XMLHttpRequest&&(new XMLHttpRequest).upload),resize_image:function(){return r.can("access_binary")&&i.can("create_canvas")},select_file:function(){return i.can("use_fileinput")&&window.File},select_folder:function(){return r.can("select_file")&&"Chrome"===i.browser&&i.version>=21},select_multiple:function(){return!(!r.can("select_file")||"Safari"===i.browser&&"Windows"===i.os||"iOS"===i.os&&i.verComp(i.osVersion,"7.0.4","<"))},send_binary_string:s(window.XMLHttpRequest&&((new XMLHttpRequest).sendAsBinary||window.Uint8Array&&window.ArrayBuffer)),send_custom_headers:s(window.XMLHttpRequest),send_multipart:function(){return!!(window.XMLHttpRequest&&(new XMLHttpRequest).upload&&window.FormData)||r.can("send_binary_string")},slice_blob:s(window.File&&(File.prototype.mozSlice||File.prototype.webkitSlice||File.prototype.slice)),stream_upload:function(){return r.can("slice_blob")&&r.can("send_multipart")},summon_file_dialog:s(function(){return"Firefox"===i.browser&&i.version>=4||"Opera"===i.browser&&i.version>=12||"IE"===i.browser&&i.version>=10||!!~e.inArray(i.browser,["Chrome","Safari"])}()),upload_filesize:u},arguments[2]);n.call(this,t,arguments[1]||o,c),e.extend(this,{init:function(){this.trigger("Init")},destroy:function(e){return function(){e.call(r),e=r=null}}(this.destroy)}),e.extend(this.getShim(),a)}var o="html5",a={};return n.addConstructor(o,r),a}),i(N,[D,y],function(e,t){function n(){function e(e,t,n){var i;if(!window.File.prototype.slice)return(i=window.File.prototype.webkitSlice||window.File.prototype.mozSlice)?i.call(e,t,n):null;try{return e.slice(),e.slice(t,n)}catch(r){return e.slice(t,n-t)}}this.slice=function(){return new t(this.getRuntime().uid,e.apply(this,arguments))}}return e.Blob=n}),i(L,[u],function(e){function t(){this.returnValue=!1}function n(){this.cancelBubble=!0}var i={},r="moxie_"+e.guid(),o=function(o,a,s,u){var c,l;a=a.toLowerCase(),o.addEventListener?(c=s,o.addEventListener(a,c,!1)):o.attachEvent&&(c=function(){var e=window.event;e.target||(e.target=e.srcElement),e.preventDefault=t,e.stopPropagation=n,s(e)},o.attachEvent("on"+a,c)),o[r]||(o[r]=e.guid()),i.hasOwnProperty(o[r])||(i[o[r]]={}),l=i[o[r]],l.hasOwnProperty(a)||(l[a]=[]),l[a].push({func:c,orig:s,key:u})},a=function(t,n,o){var a,s;if(n=n.toLowerCase(),t[r]&&i[t[r]]&&i[t[r]][n]){a=i[t[r]][n];for(var u=a.length-1;u>=0&&(a[u].orig!==o&&a[u].key!==o||(t.removeEventListener?t.removeEventListener(n,a[u].func,!1):t.detachEvent&&t.detachEvent("on"+n,a[u].func),a[u].orig=null,a[u].func=null,a.splice(u,1),o===s));u--);if(a.length||delete i[t[r]][n],e.isEmptyObj(i[t[r]])){delete i[t[r]];try{delete t[r]}catch(c){t[r]=s}}}},s=function(t,n){t&&t[r]&&e.each(i[t[r]],function(e,i){a(t,i,n)})};return{addEvent:o,removeEvent:a,removeAllEvents:s}}),i(M,[D,u,f,L,l,d],function(e,t,n,i,r,o){function a(){var e=[],a;t.extend(this,{init:function(s){var u=this,c=u.getRuntime(),l,d,f,h,p,m;a=s,e=[],f=a.accept.mimes||r.extList2mimes(a.accept,c.can("filter_by_extension")),d=c.getShimContainer(),d.innerHTML='",l=n.get(c.uid),t.extend(l.style,{position:"absolute",top:0,left:0,width:"100%",height:"100%"}),h=n.get(a.browse_button),c.can("summon_file_dialog")&&("static"===n.getStyle(h,"position")&&(h.style.position="relative"),p=parseInt(n.getStyle(h,"z-index"),10)||1,h.style.zIndex=p,d.style.zIndex=p-1,i.addEvent(h,"click",function(e){var t=n.get(c.uid);t&&!t.disabled&&t.click(),e.preventDefault()},u.uid)),m=c.can("summon_file_dialog")?h:d,i.addEvent(m,"mouseover",function(){u.trigger("mouseenter")},u.uid),i.addEvent(m,"mouseout",function(){u.trigger("mouseleave")},u.uid),i.addEvent(m,"mousedown",function(){u.trigger("mousedown")},u.uid),i.addEvent(n.get(a.container),"mouseup",function(){u.trigger("mouseup")},u.uid),l.onchange=function g(){if(e=[],a.directory?t.each(this.files,function(t){"."!==t.name&&e.push(t)}):e=[].slice.call(this.files),"IE"!==o.browser&&"IEMobile"!==o.browser)this.value="";else{var n=this.cloneNode(!0);this.parentNode.replaceChild(n,this),n.onchange=g}u.trigger("change")},u.trigger({type:"ready",async:!0}),d=null},getFiles:function(){return e},disable:function(e){var t=this.getRuntime(),i;(i=n.get(t.uid))&&(i.disabled=!!e)},destroy:function(){var t=this.getRuntime(),r=t.getShim(),o=t.getShimContainer();i.removeAllEvents(o,this.uid),i.removeAllEvents(a&&n.get(a.container),this.uid),i.removeAllEvents(a&&n.get(a.browse_button),this.uid),o&&(o.innerHTML=""),r.removeInstance(this.uid),e=a=o=r=null}})}return e.FileInput=a}),i(C,[D,u,f,L,l],function(e,t,n,i,r){function o(){function e(e){if(!e.dataTransfer||!e.dataTransfer.types)return!1;var n=t.toArray(e.dataTransfer.types||[]);return-1!==t.inArray("Files",n)||-1!==t.inArray("public.file-url",n)||-1!==t.inArray("application/x-moz-file",n)}function o(e){for(var n=[],i=0;i=4&&u.version<7,f="Android Browser"===u.browser,m=!1;if(p=n.url.replace(/^.+?\/([\w\-\.]+)$/,"$1").toLowerCase(),h=c(),h.open(n.method,n.url,n.async,n.user,n.password),r instanceof o)r.isDetached()&&(m=!0),r=r.getSource();else if(r instanceof a){if(r.hasBlob())if(r.getBlob().isDetached())r=d.call(s,r),m=!0;else if((l||f)&&"blob"===t.typeOf(r.getBlob().getSource())&&window.FileReader)return void e.call(s,n,r);if(r instanceof a){var g=new window.FormData;r.each(function(e,t){e instanceof o?g.append(t,e.getSource()):g.append(t,e)}),r=g}}h.upload?(n.withCredentials&&(h.withCredentials=!0),h.addEventListener("load",function(e){s.trigger(e)}),h.addEventListener("error",function(e){s.trigger(e)}),h.addEventListener("progress",function(e){s.trigger(e)}),h.upload.addEventListener("progress",function(e){s.trigger({type:"UploadProgress",loaded:e.loaded,total:e.total})})):h.onreadystatechange=function v(){switch(h.readyState){case 1:break;case 2:break;case 3:var e,t;try{i.hasSameOrigin(n.url)&&(e=h.getResponseHeader("Content-Length")||0),h.responseText&&(t=h.responseText.length)}catch(r){e=t=0}s.trigger({type:"progress",lengthComputable:!!e,total:parseInt(e,10),loaded:t});break;case 4:h.onreadystatechange=function(){},s.trigger(0===h.status?"error":"load")}},t.isEmptyObj(n.headers)||t.each(n.headers,function(e,t){h.setRequestHeader(t,e)}),""!==n.responseType&&"responseType"in h&&(h.responseType="json"!==n.responseType||u.can("return_response_type","json")?n.responseType:"text"),m?h.sendAsBinary?h.sendAsBinary(r):!function(){for(var e=new Uint8Array(r.length),t=0;ta;a++)i|=o.charCodeAt(e+a)<s;s++)o+=String.fromCharCode(t>>Math.abs(a+8*s)&255);n(o,e,i)}var r=!1,o;return{II:function(e){return e===t?r:void(r=e)},init:function(e){r=!1,o=e},SEGMENT:function(e,t,i){switch(arguments.length){case 1:return o.substr(e,o.length-e-1);case 2:return o.substr(e,t);case 3:n(i,e,t);break;default:return o}},BYTE:function(t){return e(t,1)},SHORT:function(t){return e(t,2)},LONG:function(n,r){return r===t?e(n,4):void i(n,r,4)},SLONG:function(t){var n=e(t,4);return n>2147483647?n-4294967296:n},STRING:function(t,n){var i="";for(n+=t;n>t;t++)i+=String.fromCharCode(e(t,1));return i}}}}),i(k,[P],function(e){return function t(n){var i=[],r,o,a,s=0;if(r=new e,r.init(n),65496===r.SHORT(0)){for(o=2;o<=n.length;)if(a=r.SHORT(o),a>=65488&&65495>=a)o+=2;else{if(65498===a||65497===a)break;s=r.SHORT(o+2)+2,a>=65505&&65519>=a&&i.push({hex:a,name:"APP"+(15&a),start:o,length:s,segment:r.SEGMENT(o,s)}),o+=s}return r.init(null),{headers:i,restore:function(e){var t,n;for(r.init(e),o=65504==r.SHORT(2)?4+r.SHORT(4):2,n=0,t=i.length;t>n;n++)r.SEGMENT(o,0,i[n].segment),o+=i[n].length;return e=r.SEGMENT(),r.init(null),e},strip:function(e){var n,i,o;for(i=new t(e),n=i.headers,i.purge(),r.init(e),o=n.length;o--;)r.SEGMENT(n[o].start,n[o].length,"");return e=r.SEGMENT(),r.init(null),e},get:function(e){for(var t=[],n=0,r=i.length;r>n;n++)i[n].name===e.toUpperCase()&&t.push(i[n].segment);return t},set:function(e,t){var n=[],r,o,a;for("string"==typeof t?n.push(t):n=t,r=o=0,a=i.length;a>r&&(i[r].name===e.toUpperCase()&&(i[r].segment=n[o],i[r].length=n[o].length,o++),!(o>=n.length));r++);},purge:function(){i=[],r.init(null),r=null}}}}}),i(U,[u,P],function(e,n){return function i(){function i(e,n){var i=a.SHORT(e),r,o,s,u,d,f,h,p,m=[],g={};for(r=0;i>r;r++)if(h=f=e+12*r+2,s=n[a.SHORT(h)],s!==t){switch(u=a.SHORT(h+=2),d=a.LONG(h+=2),h+=4,m=[],u){case 1:case 7:for(d>4&&(h=a.LONG(h)+c.tiffHeader),o=0;d>o;o++)m[o]=a.BYTE(h+o);break;case 2:d>4&&(h=a.LONG(h)+c.tiffHeader),g[s]=a.STRING(h,d-1);continue;case 3:for(d>2&&(h=a.LONG(h)+c.tiffHeader),o=0;d>o;o++)m[o]=a.SHORT(h+2*o);break;case 4:for(d>1&&(h=a.LONG(h)+c.tiffHeader),o=0;d>o;o++)m[o]=a.LONG(h+4*o);break;case 5:for(h=a.LONG(h)+c.tiffHeader,o=0;d>o;o++)m[o]=a.LONG(h+4*o)/a.LONG(h+4*o+4);break;case 9:for(h=a.LONG(h)+c.tiffHeader,o=0;d>o;o++)m[o]=a.SLONG(h+4*o);break;case 10:for(h=a.LONG(h)+c.tiffHeader,o=0;d>o;o++)m[o]=a.SLONG(h+4*o)/a.SLONG(h+4*o+4);break;default:continue}p=1==d?m[0]:m,g[s]=l.hasOwnProperty(s)&&"object"!=typeof p?l[s][p]:p}return g}function r(){var e=c.tiffHeader;return a.II(18761==a.SHORT(e)),42!==a.SHORT(e+=2)?!1:(c.IFD0=c.tiffHeader+a.LONG(e+=2),u=i(c.IFD0,s.tiff),"ExifIFDPointer"in u&&(c.exifIFD=c.tiffHeader+u.ExifIFDPointer,delete u.ExifIFDPointer),"GPSInfoIFDPointer"in u&&(c.gpsIFD=c.tiffHeader+u.GPSInfoIFDPointer,delete u.GPSInfoIFDPointer),!0)}function o(e,t,n){var i,r,o,u=0;if("string"==typeof t){var l=s[e.toLowerCase()];for(var d in l)if(l[d]===t){t=d;break}}i=c[e.toLowerCase()+"IFD"],r=a.SHORT(i);for(var f=0;r>f;f++)if(o=i+12*f+2,a.SHORT(o)==t){u=o+8;break}return u?(a.LONG(u,n),!0):!1}var a,s,u,c={},l;return a=new n,s={tiff:{274:"Orientation",270:"ImageDescription",271:"Make",272:"Model",305:"Software",34665:"ExifIFDPointer",34853:"GPSInfoIFDPointer"},exif:{36864:"ExifVersion",40961:"ColorSpace",40962:"PixelXDimension",40963:"PixelYDimension",36867:"DateTimeOriginal",33434:"ExposureTime",33437:"FNumber",34855:"ISOSpeedRatings",37377:"ShutterSpeedValue",37378:"ApertureValue",37383:"MeteringMode",37384:"LightSource",37385:"Flash",37386:"FocalLength",41986:"ExposureMode",41987:"WhiteBalance",41990:"SceneCaptureType",41988:"DigitalZoomRatio",41992:"Contrast",41993:"Saturation",41994:"Sharpness"},gps:{0:"GPSVersionID",1:"GPSLatitudeRef",2:"GPSLatitude",3:"GPSLongitudeRef",4:"GPSLongitude"}},l={ColorSpace:{1:"sRGB",0:"Uncalibrated"},MeteringMode:{0:"Unknown",1:"Average",2:"CenterWeightedAverage",3:"Spot",4:"MultiSpot",5:"Pattern",6:"Partial",255:"Other"},LightSource:{1:"Daylight",2:"Fliorescent",3:"Tungsten",4:"Flash",9:"Fine weather",10:"Cloudy weather",11:"Shade",12:"Daylight fluorescent (D 5700 - 7100K)",13:"Day white fluorescent (N 4600 -5400K)",14:"Cool white fluorescent (W 3900 - 4500K)",15:"White fluorescent (WW 3200 - 3700K)",17:"Standard light A",18:"Standard light B",19:"Standard light C",20:"D55",21:"D65",22:"D75",23:"D50",24:"ISO studio tungsten",255:"Other"},Flash:{0:"Flash did not fire.",1:"Flash fired.",5:"Strobe return light not detected.",7:"Strobe return light detected.",9:"Flash fired, compulsory flash mode",13:"Flash fired, compulsory flash mode, return light not detected",15:"Flash fired, compulsory flash mode, return light detected",16:"Flash did not fire, compulsory flash mode",24:"Flash did not fire, auto mode",25:"Flash fired, auto mode",29:"Flash fired, auto mode, return light not detected",31:"Flash fired, auto mode, return light detected",32:"No flash function",65:"Flash fired, red-eye reduction mode",69:"Flash fired, red-eye reduction mode, return light not detected",71:"Flash fired, red-eye reduction mode, return light detected",73:"Flash fired, compulsory flash mode, red-eye reduction mode",77:"Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",79:"Flash fired, compulsory flash mode, red-eye reduction mode, return light detected",89:"Flash fired, auto mode, red-eye reduction mode",93:"Flash fired, auto mode, return light not detected, red-eye reduction mode",95:"Flash fired, auto mode, return light detected, red-eye reduction mode"},ExposureMode:{0:"Auto exposure",1:"Manual exposure",2:"Auto bracket"},WhiteBalance:{0:"Auto white balance",1:"Manual white balance"},SceneCaptureType:{0:"Standard",1:"Landscape",2:"Portrait",3:"Night scene"},Contrast:{0:"Normal",1:"Soft",2:"Hard"},Saturation:{0:"Normal",1:"Low saturation",2:"High saturation"},Sharpness:{0:"Normal",1:"Soft",2:"Hard"},GPSLatitudeRef:{N:"North latitude",S:"South latitude"},GPSLongitudeRef:{E:"East longitude",W:"West longitude"}},{init:function(e){return c={tiffHeader:10},e!==t&&e.length?(a.init(e),65505===a.SHORT(0)&&"EXIF\x00"===a.STRING(4,5).toUpperCase()?r():!1):!1 +},TIFF:function(){return u},EXIF:function(){var t;if(t=i(c.exifIFD,s.exif),t.ExifVersion&&"array"===e.typeOf(t.ExifVersion)){for(var n=0,r="";n=65472&&65475>=t)return e+=5,{height:c.SHORT(e),width:c.SHORT(e+=2)};n=c.SHORT(e+=2),e+=n-2}return null}function s(){d&&l&&c&&(d.purge(),l.purge(),c.init(null),u=f=l=d=c=null)}var u,c,l,d,f,h;if(u=o,c=new i,c.init(u),65496!==c.SHORT(0))throw new t.ImageError(t.ImageError.WRONG_FORMAT);l=new n(o),d=new r,h=!!d.init(l.get("app1")[0]),f=a.call(this),e.extend(this,{type:"image/jpeg",size:u.length,width:f&&f.width||0,height:f&&f.height||0,setExif:function(t,n){return h?("object"===e.typeOf(t)?e.each(t,function(e,t){d.setExif(t,e)}):d.setExif(t,n),void l.set("app1",d.getBinary())):!1},writeHeaders:function(){return arguments.length?l.restore(arguments[0]):u=l.restore(u)},stripHeaders:function(e){return l.strip(e)},purge:function(){s.call(this)}}),h&&(this.meta={tiff:d.TIFF(),exif:d.EXIF(),gps:d.GPS()})}return o}),i(z,[h,u,P],function(e,t,n){function i(i){function r(){var e,t;return e=a.call(this,8),"IHDR"==e.type?(t=e.start,{width:u.LONG(t),height:u.LONG(t+=4)}):null}function o(){u&&(u.init(null),s=d=c=l=u=null)}function a(e){var t,n,i,r;return t=u.LONG(e),n=u.STRING(e+=4,4),i=e+=4,r=u.LONG(e+t),{length:t,type:n,start:i,CRC:r}}var s,u,c,l,d;s=i,u=new n,u.init(s),function(){var t=0,n=0,i=[35152,20039,3338,6666];for(n=0;ng;){for(var v=g+f>a?a-g:f,y=0;o>y;){var w=y+f>o?o-y:f;p.clearRect(0,0,f,f),p.drawImage(e,-y,-g);var E=y*s/o+c<<0,_=Math.ceil(w*s/o),x=g*u/a/m+l<<0,b=Math.ceil(v*u/a/m);d.drawImage(h,0,0,w,v,E,x,_,b),y+=f}g+=f}h=p=null}function t(e){var t=e.naturalWidth,n=e.naturalHeight;if(t*n>1048576){var i=document.createElement("canvas");i.width=i.height=1;var r=i.getContext("2d");return r.drawImage(e,-t+1,0),0===r.getImageData(0,0,1,1).data[3]}return!1}function n(e,t,n){var i=document.createElement("canvas");i.width=1,i.height=n;var r=i.getContext("2d");r.drawImage(e,0,0);for(var o=r.getImageData(0,0,1,n).data,a=0,s=n,u=n;u>a;){var c=o[4*(u-1)+3];0===c?s=u:a=u,u=s+a>>1}i=null;var l=u/n;return 0===l?1:l}return{isSubsampled:t,renderTo:e}}),i(X,[D,u,h,m,w,G,q,l,d],function(e,t,n,i,r,o,a,s,u){function c(){function e(){if(!E&&!y)throw new n.ImageError(n.DOMException.INVALID_STATE_ERR);return E||y}function c(e){return i.atob(e.substring(e.indexOf("base64,")+7))}function l(e,t){return"data:"+(t||"")+";base64,"+i.btoa(e)}function d(e){var t=this;y=new Image,y.onerror=function(){g.call(this),t.trigger("error",n.ImageError.WRONG_FORMAT)},y.onload=function(){t.trigger("load")},y.src=/^data:[^;]*;base64,/.test(e)?e:l(e,x.type)}function f(e,t){var i=this,r;return window.FileReader?(r=new FileReader,r.onload=function(){t(this.result)},r.onerror=function(){i.trigger("error",n.ImageError.WRONG_FORMAT)},r.readAsDataURL(e),void 0):t(e.getAsDataURL())}function h(n,i,r,o){var a=this,s,u,c=0,l=0,d,f,h,g;if(R=o,g=this.meta&&this.meta.tiff&&this.meta.tiff.Orientation||1,-1!==t.inArray(g,[5,6,7,8])){var v=n;n=i,i=v}return d=e(),r?(n=Math.min(n,d.width),i=Math.min(i,d.height),s=Math.max(n/d.width,i/d.height)):s=Math.min(n/d.width,i/d.height),s>1&&!r&&o?void this.trigger("Resize"):(E||(E=document.createElement("canvas")),f=Math.round(d.width*s),h=Math.round(d.height*s),r?(E.width=n,E.height=i,f>n&&(c=Math.round((f-n)/2)),h>i&&(l=Math.round((h-i)/2))):(E.width=f,E.height=h),R||m(E.width,E.height,g),p.call(this,d,E,-c,-l,f,h),this.width=E.width,this.height=E.height,b=!0,void a.trigger("Resize"))}function p(e,t,n,i,r,o){if("iOS"===u.OS)a.renderTo(e,t,{width:r,height:o,x:n,y:i});else{var s=t.getContext("2d");s.drawImage(e,n,i,r,o)}}function m(e,t,n){switch(n){case 5:case 6:case 7:case 8:E.width=t,E.height=e;break;default:E.width=e,E.height=t}var i=E.getContext("2d");switch(n){case 2:i.translate(e,0),i.scale(-1,1);break;case 3:i.translate(e,t),i.rotate(Math.PI);break;case 4:i.translate(0,t),i.scale(1,-1);break;case 5:i.rotate(.5*Math.PI),i.scale(1,-1);break;case 6:i.rotate(.5*Math.PI),i.translate(0,-t);break;case 7:i.rotate(.5*Math.PI),i.translate(e,-t),i.scale(-1,1);break;case 8:i.rotate(-.5*Math.PI),i.translate(-e,0)}}function g(){w&&(w.purge(),w=null),_=y=E=x=null,b=!1}var v=this,y,w,E,_,x,b=!1,R=!0;t.extend(this,{loadFromBlob:function(e){var t=this,i=t.getRuntime(),r=arguments.length>1?arguments[1]:!0;if(!i.can("access_binary"))throw new n.RuntimeError(n.RuntimeError.NOT_SUPPORTED_ERR);return x=e,e.isDetached()?(_=e.getSource(),void d.call(this,_)):void f.call(this,e.getSource(),function(e){r&&(_=c(e)),d.call(t,e)})},loadFromImage:function(e,t){this.meta=e.meta,x=new r(null,{name:e.name,size:e.size,type:e.type}),d.call(this,t?_=e.getAsBinaryString():e.getAsDataURL())},getInfo:function(){var t=this.getRuntime(),n;return!w&&_&&t.can("access_image_binary")&&(w=new o(_)),n={width:e().width||0,height:e().height||0,type:x.type||s.getFileMime(x.name),size:_&&_.length||x.size||0,name:x.name||"",meta:w&&w.meta||this.meta||{}}},downsize:function(){h.apply(this,arguments)},getAsCanvas:function(){return E&&(E.id=this.uid+"_canvas"),E},getAsBlob:function(e,t){return e!==this.type&&h.call(this,this.width,this.height,!1),new r(null,{name:x.name||"",type:e,data:v.getAsBinaryString.call(this,e,t)})},getAsDataURL:function(e){var t=arguments[1]||90;if(!b)return y.src;if("image/jpeg"!==e)return E.toDataURL("image/png");try{return E.toDataURL("image/jpeg",t/100)}catch(n){return E.toDataURL("image/jpeg")}},getAsBinaryString:function(e,t){if(!b)return _||(_=c(v.getAsDataURL(e,t))),_;if("image/jpeg"!==e)_=c(v.getAsDataURL(e,t));else{var n;t||(t=90);try{n=E.toDataURL("image/jpeg",t/100)}catch(i){n=E.toDataURL("image/jpeg")}_=c(n),w&&(_=w.stripHeaders(_),R&&(w.meta&&w.meta.exif&&w.setExif({PixelXDimension:this.width,PixelYDimension:this.height}),_=w.writeHeaders(_)),w.purge(),w=null)}return b=!1,_},destroy:function(){v=null,g.call(this),this.getRuntime().getShim().removeInstance(this.uid)}})}return e.Image=c}),i(j,[u,d,f,h,g],function(e,t,n,i,r){function o(){var e;try{e=navigator.plugins["Shockwave Flash"],e=e.description}catch(t){try{e=new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version")}catch(n){e="0.0"}}return e=e.match(/\d+/g),parseFloat(e[0]+"."+e[1])}function a(a){var c=this,l;a=e.extend({swf_url:t.swf_url},a),r.call(this,a,s,{access_binary:function(e){return e&&"browser"===c.mode},access_image_binary:function(e){return e&&"browser"===c.mode},display_media:r.capTrue,do_cors:r.capTrue,drag_and_drop:!1,report_upload_progress:function(){return"client"===c.mode},resize_image:r.capTrue,return_response_headers:!1,return_response_type:function(t){return"json"===t&&window.JSON?!0:!e.arrayDiff(t,["","text","document"])||"browser"===c.mode},return_status_code:function(t){return"browser"===c.mode||!e.arrayDiff(t,[200,404])},select_file:r.capTrue,select_multiple:r.capTrue,send_binary_string:function(e){return e&&"browser"===c.mode},send_browser_cookies:function(e){return e&&"browser"===c.mode},send_custom_headers:function(e){return e&&"browser"===c.mode},send_multipart:r.capTrue,slice_blob:function(e){return e&&"browser"===c.mode},stream_upload:function(e){return e&&"browser"===c.mode},summon_file_dialog:!1,upload_filesize:function(t){return e.parseSizeStr(t)<=2097152||"client"===c.mode},use_http_method:function(t){return!e.arrayDiff(t,["GET","POST"])}},{access_binary:function(e){return e?"browser":"client"},access_image_binary:function(e){return e?"browser":"client"},report_upload_progress:function(e){return e?"browser":"client"},return_response_type:function(t){return e.arrayDiff(t,["","text","json","document"])?"browser":["client","browser"]},return_status_code:function(t){return e.arrayDiff(t,[200,404])?"browser":["client","browser"]},send_binary_string:function(e){return e?"browser":"client"},send_browser_cookies:function(e){return e?"browser":"client"},send_custom_headers:function(e){return e?"browser":"client"},stream_upload:function(e){return e?"client":"browser"},upload_filesize:function(t){return e.parseSizeStr(t)>=2097152?"client":"browser"}},"client"),o()<10&&(this.mode=!1),e.extend(this,{getShim:function(){return n.get(this.uid)},shimExec:function(e,t){var n=[].slice.call(arguments,2);return c.getShim().exec(this.uid,e,t,n)},init:function(){var n,r,o;o=this.getShimContainer(),e.extend(o.style,{position:"absolute",top:"-8px",left:"-8px",width:"9px",height:"9px",overflow:"hidden"}),n='',"IE"===t.browser?(r=document.createElement("div"),o.appendChild(r),r.outerHTML=n,r=o=null):o.innerHTML=n,l=setTimeout(function(){c&&!c.initialized&&c.trigger("Error",new i.RuntimeError(i.RuntimeError.NOT_INIT_ERR))},5e3)},destroy:function(e){return function(){e.call(c),clearTimeout(l),a=l=e=c=null}}(this.destroy)},u)}var s="flash",u={};return r.addConstructor(s,a),u}),i(V,[j,y],function(e,t){var n={slice:function(e,n,i,r){var o=this.getRuntime();return 0>n?n=Math.max(e.size+n,0):n>0&&(n=Math.min(n,e.size)),0>i?i=Math.max(e.size+i,0):i>0&&(i=Math.min(i,e.size)),e=o.shimExec.call(this,"Blob","slice",n,i,r||""),e&&(e=new t(o.uid,e)),e}};return e.Blob=n}),i(W,[j],function(e){var t={init:function(e){this.getRuntime().shimExec.call(this,"FileInput","init",{name:e.name,accept:e.accept,multiple:e.multiple}),this.trigger("ready")}};return e.FileInput=t}),i(Y,[j,m],function(e,t){function n(e,n){switch(n){case"readAsText":return t.atob(e,"utf8");case"readAsBinaryString":return t.atob(e);case"readAsDataURL":return e}return null}var i="",r={read:function(e,t){var r=this,o=r.getRuntime();return"readAsDataURL"===e&&(i="data:"+(t.type||"")+";base64,"),r.bind("Progress",function(t,r){r&&(i+=n(r,e))}),o.shimExec.call(this,"FileReader","readAsBase64",t.uid)},getResult:function(){return i},destroy:function(){i=null}};return e.FileReader=r}),i($,[j,m],function(e,t){function n(e,n){switch(n){case"readAsText":return t.atob(e,"utf8");case"readAsBinaryString":return t.atob(e);case"readAsDataURL":return e}return null}var i={read:function(e,t){var i,r=this.getRuntime();return(i=r.shimExec.call(this,"FileReaderSync","readAsBase64",t.uid))?("readAsDataURL"===e&&(i="data:"+(t.type||"")+";base64,"+i),n(i,e,t.type)):null}};return e.FileReaderSync=i}),i(J,[j,u,y,w,T,A,O],function(e,t,n,i,r,o,a){var s={send:function(e,i){function r(){e.transport=l.mode,l.shimExec.call(c,"XMLHttpRequest","send",e,i)}function s(e,t){l.shimExec.call(c,"XMLHttpRequest","appendBlob",e,t.uid),i=null,r()}function u(e,t){var n=new a;n.bind("TransportingComplete",function(){t(this.result)}),n.transport(e.getSource(),e.type,{ruid:l.uid})}var c=this,l=c.getRuntime();if(t.isEmptyObj(e.headers)||t.each(e.headers,function(e,t){l.shimExec.call(c,"XMLHttpRequest","setRequestHeader",t,e.toString())}),i instanceof o){var d;if(i.each(function(e,t){e instanceof n?d=t:l.shimExec.call(c,"XMLHttpRequest","append",t,e)}),i.hasBlob()){var f=i.getBlob();f.isDetached()?u(f,function(e){f.destroy(),s(d,e)}):s(d,f)}else i=null,r()}else i instanceof n?i.isDetached()?u(i,function(e){i.destroy(),i=e.uid,r()}):(i=i.uid,r()):r()},getResponse:function(e){var n,o,a=this.getRuntime();if(o=a.shimExec.call(this,"XMLHttpRequest","getResponseAsBlob")){if(o=new i(a.uid,o),"blob"===e)return o;try{if(n=new r,~t.inArray(e,["","text"]))return n.readAsText(o);if("json"===e&&window.JSON)return JSON.parse(n.readAsText(o))}finally{o.destroy()}}return null},abort:function(e){var t=this.getRuntime();t.shimExec.call(this,"XMLHttpRequest","abort"),this.dispatchEvent("readystatechange"),this.dispatchEvent("abort")}};return e.XMLHttpRequest=s}),i(Z,[j,y],function(e,t){var n={getAsBlob:function(e){var n=this.getRuntime(),i=n.shimExec.call(this,"Transporter","getAsBlob",e);return i?new t(n.uid,i):null}};return e.Transporter=n}),i(K,[j,u,O,y,T],function(e,t,n,i,r){var o={loadFromBlob:function(e){function t(e){r.shimExec.call(i,"Image","loadFromBlob",e.uid),i=r=null}var i=this,r=i.getRuntime();if(e.isDetached()){var o=new n;o.bind("TransportingComplete",function(){t(o.result.getSource())}),o.transport(e.getSource(),e.type,{ruid:r.uid})}else t(e.getSource())},loadFromImage:function(e){var t=this.getRuntime();return t.shimExec.call(this,"Image","loadFromImage",e.uid)},getAsBlob:function(e,t){var n=this.getRuntime(),r=n.shimExec.call(this,"Image","getAsBlob",e,t);return r?new i(n.uid,r):null},getAsDataURL:function(){var e=this.getRuntime(),t=e.Image.getAsBlob.apply(this,arguments),n;return t?(n=new r,n.readAsDataURL(t)):null}};return e.Image=o}),i(Q,[u,d,f,h,g],function(e,t,n,i,r){function o(e){var t=!1,n=null,i,r,o,a,s,u=0;try{try{n=new ActiveXObject("AgControl.AgControl"),n.IsVersionSupported(e)&&(t=!0),n=null}catch(c){var l=navigator.plugins["Silverlight Plug-In"];if(l){for(i=l.description,"1.0.30226.2"===i&&(i="2.0.30226.2"),r=i.split(".");r.length>3;)r.pop();for(;r.length<4;)r.push(0);for(o=e.split(".");o.length>4;)o.pop();do a=parseInt(o[u],10),s=parseInt(r[u],10),u++;while(u=a&&!isNaN(a)&&(t=!0)}}}catch(d){t=!1}return t}function a(a){var c=this,l;a=e.extend({xap_url:t.xap_url},a),r.call(this,a,s,{access_binary:r.capTrue,access_image_binary:r.capTrue,display_media:r.capTrue,do_cors:r.capTrue,drag_and_drop:!1,report_upload_progress:r.capTrue,resize_image:r.capTrue,return_response_headers:function(e){return e&&"client"===c.mode},return_response_type:function(e){return"json"!==e?!0:!!window.JSON},return_status_code:function(t){return"client"===c.mode||!e.arrayDiff(t,[200,404])},select_file:r.capTrue,select_multiple:r.capTrue,send_binary_string:r.capTrue,send_browser_cookies:function(e){return e&&"browser"===c.mode},send_custom_headers:function(e){return e&&"client"===c.mode},send_multipart:r.capTrue,slice_blob:r.capTrue,stream_upload:!0,summon_file_dialog:!1,upload_filesize:r.capTrue,use_http_method:function(t){return"client"===c.mode||!e.arrayDiff(t,["GET","POST"])}},{return_response_headers:function(e){return e?"client":"browser"},return_status_code:function(t){return e.arrayDiff(t,[200,404])?"client":["client","browser"]},send_browser_cookies:function(e){return e?"browser":"client"},send_custom_headers:function(e){return e?"client":"browser"},use_http_method:function(t){return e.arrayDiff(t,["GET","POST"])?"client":["client","browser"]}}),o("2.0.31005.0")&&"Opera"!==t.browser||(this.mode=!1),e.extend(this,{getShim:function(){return n.get(this.uid).content.Moxie},shimExec:function(e,t){var n=[].slice.call(arguments,2);return c.getShim().exec(this.uid,e,t,n)},init:function(){var e;e=this.getShimContainer(),e.innerHTML='',l=setTimeout(function(){c&&!c.initialized&&c.trigger("Error",new i.RuntimeError(i.RuntimeError.NOT_INIT_ERR))},"Windows"!==t.OS?1e4:5e3)},destroy:function(e){return function(){e.call(c),clearTimeout(l),a=l=e=c=null}}(this.destroy)},u)}var s="silverlight",u={};return r.addConstructor(s,a),u}),i(et,[Q,u,V],function(e,t,n){return e.Blob=t.extend({},n)}),i(tt,[Q],function(e){var t={init:function(e){function t(e){for(var t="",n=0;no;o++)n=t.keys[o],s=t[n],s&&(/^(\d|[1-9]\d+)$/.test(s)?s=parseInt(s,10):/^\d*\.\d+$/.test(s)&&(s=parseFloat(s)),i.meta[e][n]=s)}),i.width=parseInt(r.width,10),i.height=parseInt(r.height,10),i.size=parseInt(r.size,10),i.type=r.type,i.name=r.name,i}})}),i(ut,[u,h,g,d],function(e,t,n,i){function r(t){var r=this,s=n.capTest,u=n.capTrue;n.call(this,t,o,{access_binary:s(window.FileReader||window.File&&File.getAsDataURL),access_image_binary:!1,display_media:s(a.Image&&(i.can("create_canvas")||i.can("use_data_uri_over32kb"))),do_cors:!1,drag_and_drop:!1,filter_by_extension:s(function(){return"Chrome"===i.browser&&i.version>=28||"IE"===i.browser&&i.version>=10}()),resize_image:function(){return a.Image&&r.can("access_binary")&&i.can("create_canvas")},report_upload_progress:!1,return_response_headers:!1,return_response_type:function(t){return"json"===t&&window.JSON?!0:!!~e.inArray(t,["text","document",""])},return_status_code:function(t){return!e.arrayDiff(t,[200,404])},select_file:function(){return i.can("use_fileinput")},select_multiple:!1,send_binary_string:!1,send_custom_headers:!1,send_multipart:!0,slice_blob:!1,stream_upload:function(){return r.can("select_file")},summon_file_dialog:s(function(){return"Firefox"===i.browser&&i.version>=4||"Opera"===i.browser&&i.version>=12||!!~e.inArray(i.browser,["Chrome","Safari"])}()),upload_filesize:u,use_http_method:function(t){return!e.arrayDiff(t,["GET","POST"])}}),e.extend(this,{init:function(){this.trigger("Init")},destroy:function(e){return function(){e.call(r),e=r=null}}(this.destroy)}),e.extend(this.getShim(),a)}var o="html4",a={};return n.addConstructor(o,r),a}),i(ct,[ut,u,f,L,l,d],function(e,t,n,i,r,o){function a(){function e(){var r=this,l=r.getRuntime(),d,f,h,p,m,g;g=t.guid("uid_"),d=l.getShimContainer(),a&&(h=n.get(a+"_form"),h&&t.extend(h.style,{top:"100%"})),p=document.createElement("form"),p.setAttribute("id",g+"_form"),p.setAttribute("method","post"),p.setAttribute("enctype","multipart/form-data"),p.setAttribute("encoding","multipart/form-data"),t.extend(p.style,{overflow:"hidden",position:"absolute",top:0,left:0,width:"100%",height:"100%"}),m=document.createElement("input"),m.setAttribute("id",g),m.setAttribute("type","file"),m.setAttribute("name",c.name||"Filedata"),m.setAttribute("accept",u.join(",")),t.extend(m.style,{fontSize:"999px",opacity:0}),p.appendChild(m),d.appendChild(p),t.extend(m.style,{position:"absolute",top:0,left:0,width:"100%",height:"100%"}),"IE"===o.browser&&o.version<10&&t.extend(m.style,{filter:"progid:DXImageTransform.Microsoft.Alpha(opacity=0)"}),m.onchange=function(){var t;this.value&&(t=this.files?this.files[0]:{name:this.value},s=[t],this.onchange=function(){},e.call(r),r.bind("change",function i(){var e=n.get(g),t=n.get(g+"_form"),o;r.unbind("change",i),r.files.length&&e&&t&&(o=r.files[0],e.setAttribute("id",o.uid),t.setAttribute("id",o.uid+"_form"),t.setAttribute("target",o.uid+"_iframe")),e=t=null},998),m=p=null,r.trigger("change"))},l.can("summon_file_dialog")&&(f=n.get(c.browse_button),i.removeEvent(f,"click",r.uid),i.addEvent(f,"click",function(e){m&&!m.disabled&&m.click(),e.preventDefault()},r.uid)),a=g,d=h=f=null}var a,s=[],u=[],c;t.extend(this,{init:function(t){var o=this,a=o.getRuntime(),s;c=t,u=t.accept.mimes||r.extList2mimes(t.accept,a.can("filter_by_extension")),s=a.getShimContainer(),function(){var e,r,u;e=n.get(t.browse_button),a.can("summon_file_dialog")&&("static"===n.getStyle(e,"position")&&(e.style.position="relative"),r=parseInt(n.getStyle(e,"z-index"),10)||1,e.style.zIndex=r,s.style.zIndex=r-1),u=a.can("summon_file_dialog")?e:s,i.addEvent(u,"mouseover",function(){o.trigger("mouseenter")},o.uid),i.addEvent(u,"mouseout",function(){o.trigger("mouseleave")},o.uid),i.addEvent(u,"mousedown",function(){o.trigger("mousedown")},o.uid),i.addEvent(n.get(t.container),"mouseup",function(){o.trigger("mouseup")},o.uid),e=null}(),e.call(this),s=null,o.trigger({type:"ready",async:!0})},getFiles:function(){return s},disable:function(e){var t;(t=n.get(a))&&(t.disabled=!!e)},destroy:function(){var e=this.getRuntime(),t=e.getShim(),r=e.getShimContainer();i.removeAllEvents(r,this.uid),i.removeAllEvents(c&&n.get(c.container),this.uid),i.removeAllEvents(c&&n.get(c.browse_button),this.uid),r&&(r.innerHTML=""),t.removeInstance(this.uid),a=s=u=c=r=t=null}})}return e.FileInput=a}),i(lt,[ut,F],function(e,t){return e.FileReader=t}),i(dt,[ut,u,f,R,h,L,y,A],function(e,t,n,i,r,o,a,s){function u(){function e(e){var t=this,i,r,a,s,u=!1;if(l){if(i=l.id.replace(/_iframe$/,""),r=n.get(i+"_form")){for(a=r.getElementsByTagName("input"),s=a.length;s--;)switch(a[s].getAttribute("type")){case"hidden":a[s].parentNode.removeChild(a[s]);break;case"file":u=!0}a=[],u||r.parentNode.removeChild(r),r=null}setTimeout(function(){o.removeEvent(l,"load",t.uid),l.parentNode&&l.parentNode.removeChild(l);var n=t.getRuntime().getShimContainer();n.children.length||n.parentNode.removeChild(n),n=l=null,e()},1)}}var u,c,l;t.extend(this,{send:function(d,f){function h(){var n=m.getShimContainer()||document.body,r=document.createElement("div");r.innerHTML='',l=r.firstChild,n.appendChild(l),o.addEvent(l,"load",function(){var n;try{n=l.contentWindow.document||l.contentDocument||window.frames[l.id].document,/^4(0[0-9]|1[0-7]|2[2346])\s/.test(n.title)?u=n.title.replace(/^(\d+).*$/,"$1"):(u=200,c=t.trim(n.body.innerHTML),p.trigger({type:"progress",loaded:c.length,total:c.length}),w&&p.trigger({type:"uploadprogress",loaded:w.size||1025,total:w.size||1025}))}catch(r){if(!i.hasSameOrigin(d.url))return void e.call(p,function(){p.trigger("error")});u=404}e.call(p,function(){p.trigger("load")})},p.uid)}var p=this,m=p.getRuntime(),g,v,y,w;if(u=c=null,f instanceof s&&f.hasBlob()){if(w=f.getBlob(),g=w.uid,y=n.get(g),v=n.get(g+"_form"),!v)throw new r.DOMException(r.DOMException.NOT_FOUND_ERR)}else g=t.guid("uid_"),v=document.createElement("form"),v.setAttribute("id",g+"_form"),v.setAttribute("method",d.method),v.setAttribute("enctype","multipart/form-data"),v.setAttribute("encoding","multipart/form-data"),v.setAttribute("target",g+"_iframe"),m.getShimContainer().appendChild(v);f instanceof s&&f.each(function(e,n){if(e instanceof a)y&&y.setAttribute("name",n);else{var i=document.createElement("input");t.extend(i,{type:"hidden",name:n,value:e}),y?v.insertBefore(i,y):v.appendChild(i)}}),v.setAttribute("action",d.url),h(),v.submit(),p.trigger("loadstart")},getStatus:function(){return u},getResponse:function(e){if("json"===e&&"string"===t.typeOf(c)&&window.JSON)try{return JSON.parse(c.replace(/^\s*]*>/,"").replace(/<\/pre>\s*$/,""))}catch(n){return null}return c},abort:function(){var t=this;l&&l.contentWindow&&(l.contentWindow.stop?l.contentWindow.stop():l.contentWindow.document.execCommand?l.contentWindow.document.execCommand("Stop"):l.src="about:blank"),e.call(this,function(){t.dispatchEvent("abort")})}})}return e.XMLHttpRequest=u}),i(ft,[ut,X],function(e,t){return e.Image=t}),a([u,c,l,d,f,h,p,m,g,v,y,w,E,_,x,b,R,T,A,S,O,I,L])}(this);;(function(e){"use strict";var t={},n=e.moxie.core.utils.Basic.inArray;return function r(e){var i,s;for(i in e)s=typeof e[i],s==="object"&&!~n(i,["Exceptions","Env","Mime"])?r(e[i]):s==="function"&&(t[i]=e[i])}(e.moxie),t.Env=e.moxie.core.utils.Env,t.Mime=e.moxie.core.utils.Mime,t.Exceptions=e.moxie.core.Exceptions,e.mOxie=t,e.o||(e.o=t),t})(this); +/** + * Plupload - multi-runtime File Uploader + * v2.1.2 + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + * + * Date: 2014-05-14 + */ +;(function(e,t,n){function s(e){function r(e,t,r){var i={chunks:"slice_blob",jpgresize:"send_binary_string",pngresize:"send_binary_string",progress:"report_upload_progress",multi_selection:"select_multiple",dragdrop:"drag_and_drop",drop_element:"drag_and_drop",headers:"send_custom_headers",urlstream_upload:"send_binary_string",canSendBinary:"send_binary",triggerDialog:"summon_file_dialog"};i[e]?n[i[e]]=t:r||(n[e]=t)}var t=e.required_features,n={};if(typeof t=="string")o.each(t.split(/\s*,\s*/),function(e){r(e,!0)});else if(typeof t=="object")o.each(t,function(e,t){r(t,e)});else if(t===!0){e.chunk_size>0&&(n.slice_blob=!0);if(e.resize.enabled||!e.multipart)n.send_binary_string=!0;o.each(e,function(e,t){r(t,!!e,!0)})}return n}var r=e.setTimeout,i={},o={VERSION:"2.1.2",STOPPED:1,STARTED:2,QUEUED:1,UPLOADING:2,FAILED:4,DONE:5,GENERIC_ERROR:-100,HTTP_ERROR:-200,IO_ERROR:-300,SECURITY_ERROR:-400,INIT_ERROR:-500,FILE_SIZE_ERROR:-600,FILE_EXTENSION_ERROR:-601,FILE_DUPLICATE_ERROR:-602,IMAGE_FORMAT_ERROR:-700,MEMORY_ERROR:-701,IMAGE_DIMENSIONS_ERROR:-702,mimeTypes:t.mimes,ua:t.ua,typeOf:t.typeOf,extend:t.extend,guid:t.guid,get:function(n){var r=[],i;t.typeOf(n)!=="array"&&(n=[n]);var s=n.length;while(s--)i=t.get(n[s]),i&&r.push(i);return r.length?r:null},each:t.each,getPos:t.getPos,getSize:t.getSize,xmlEncode:function(e){var t={"<":"lt",">":"gt","&":"amp",'"':"quot","'":"#39"},n=/[<>&\"\']/g;return e?(""+e).replace(n,function(e){return t[e]?"&"+t[e]+";":e}):e},toArray:t.toArray,inArray:t.inArray,addI18n:t.addI18n,translate:t.translate,isEmptyObj:t.isEmptyObj,hasClass:t.hasClass,addClass:t.addClass,removeClass:t.removeClass,getStyle:t.getStyle,addEvent:t.addEvent,removeEvent:t.removeEvent,removeAllEvents:t.removeAllEvents,cleanName:function(e){var t,n;n=[/[\300-\306]/g,"A",/[\340-\346]/g,"a",/\307/g,"C",/\347/g,"c",/[\310-\313]/g,"E",/[\350-\353]/g,"e",/[\314-\317]/g,"I",/[\354-\357]/g,"i",/\321/g,"N",/\361/g,"n",/[\322-\330]/g,"O",/[\362-\370]/g,"o",/[\331-\334]/g,"U",/[\371-\374]/g,"u"];for(t=0;t0?"&":"?")+n),e},formatSize:function(e){function t(e,t){return Math.round(e*Math.pow(10,t))/Math.pow(10,t)}if(e===n||/\D/.test(e))return o.translate("N/A");var r=Math.pow(1024,4);return e>r?t(e/r,1)+" "+o.translate("tb"):e>(r/=1024)?t(e/r,1)+" "+o.translate("gb"):e>(r/=1024)?t(e/r,1)+" "+o.translate("mb"):e>1024?Math.round(e/1024)+" "+o.translate("kb"):e+" "+o.translate("b")},parseSize:t.parseSizeStr,predictRuntime:function(e,n){var r,i;return r=new o.Uploader(e),i=t.Runtime.thatCan(r.getOption().required_features,n||e.runtimes),r.destroy(),i},addFileFilter:function(e,t){i[e]=t}};o.addFileFilter("mime_types",function(e,t,n){e.length&&!e.regexp.test(t.name)?(this.trigger("Error",{code:o.FILE_EXTENSION_ERROR,message:o.translate("File extension error."),file:t}),n(!1)):n(!0)}),o.addFileFilter("max_file_size",function(e,t,n){var r;e=o.parseSize(e),t.size!==r&&e&&t.size>e?(this.trigger("Error",{code:o.FILE_SIZE_ERROR,message:o.translate("File size error."),file:t}),n(!1)):n(!0)}),o.addFileFilter("prevent_duplicates",function(e,t,n){if(e){var r=this.files.length;while(r--)if(t.name===this.files[r].name&&t.size===this.files[r].size){this.trigger("Error",{code:o.FILE_DUPLICATE_ERROR,message:o.translate("Duplicate file error."),file:t}),n(!1);return}}n(!0)}),o.Uploader=function(e){function g(){var e,t=0,n;if(this.state==o.STARTED){for(n=0;n0?Math.ceil(e.loaded/e.size*100):100,b()}function b(){var e,t;d.reset();for(e=0;e0?Math.ceil(d.uploaded/f.length*100):0:(d.bytesPerSec=Math.ceil(d.loaded/((+(new Date)-p||1)/1e3)),d.percent=d.size>0?Math.ceil(d.loaded/d.size*100):0)}function w(){var e=c[0]||h[0];return e?e.getRuntime().uid:!1}function E(e,n){if(e.ruid){var r=t.Runtime.getInfo(e.ruid);if(r)return r.can(n)}return!1}function S(){this.bind("FilesAdded FilesRemoved",function(e){e.trigger("QueueChanged"),e.refresh()}),this.bind("CancelUpload",O),this.bind("BeforeUpload",C),this.bind("UploadFile",k),this.bind("UploadProgress",L),this.bind("StateChanged",A),this.bind("QueueChanged",b),this.bind("Error",_),this.bind("FileUploaded",M),this.bind("Destroy",D)}function x(e,n){var r=this,i=0,s=[],u={runtime_order:e.runtimes,required_caps:e.required_features,preferred_caps:l,swf_url:e.flash_swf_url,xap_url:e.silverlight_xap_url};o.each(e.runtimes.split(/\s*,\s*/),function(t){e[t]&&(u[t]=e[t])}),e.browse_button&&o.each(e.browse_button,function(n){s.push(function(s){var a=new t.FileInput(o.extend({},u,{accept:e.filters.mime_types,name:e.file_data_name,multiple:e.multi_selection,container:e.container,browse_button:n}));a.onready=function(){var e=t.Runtime.getInfo(this.ruid);t.extend(r.features,{chunks:e.can("slice_blob"),multipart:e.can("send_multipart"),multi_selection:e.can("select_multiple")}),i++,c.push(this),s()},a.onchange=function(){r.addFile(this.files)},a.bind("mouseenter mouseleave mousedown mouseup",function(r){v||(e.browse_button_hover&&("mouseenter"===r.type?t.addClass(n,e.browse_button_hover):"mouseleave"===r.type&&t.removeClass(n,e.browse_button_hover)),e.browse_button_active&&("mousedown"===r.type?t.addClass(n,e.browse_button_active):"mouseup"===r.type&&t.removeClass(n,e.browse_button_active)))}),a.bind("mousedown",function(){r.trigger("Browse")}),a.bind("error runtimeerror",function(){a=null,s()}),a.init()})}),e.drop_element&&o.each(e.drop_element,function(e){s.push(function(n){var s=new t.FileDrop(o.extend({},u,{drop_zone:e}));s.onready=function(){var e=t.Runtime.getInfo(this.ruid);r.features.dragdrop=e.can("drag_and_drop"),i++,h.push(this),n()},s.ondrop=function(){r.addFile(this.files)},s.bind("error runtimeerror",function(){s=null,n()}),s.init()})}),t.inSeries(s,function(){typeof n=="function"&&n(i)})}function T(e,r,i){var s=new t.Image;try{s.onload=function(){if(r.width>this.width&&r.height>this.height&&r.quality===n&&r.preserve_headers&&!r.crop)return this.destroy(),i(e);s.downsize(r.width,r.height,r.crop,r.preserve_headers)},s.onresize=function(){i(this.getAsBlob(e.type,r.quality)),this.destroy()},s.onerror=function(){i(e)},s.load(e)}catch(o){i(e)}}function N(e,n,r){function f(e,t,n){var r=a[e];switch(e){case"max_file_size":e==="max_file_size"&&(a.max_file_size=a.filters.max_file_size=t);break;case"chunk_size":if(t=o.parseSize(t))a[e]=t,a.send_file_name=!0;break;case"multipart":a[e]=t,t||(a.send_file_name=!0);break;case"unique_names":a[e]=t,t&&(a.send_file_name=!0);break;case"filters":o.typeOf(t)==="array"&&(t={mime_types:t}),n?o.extend(a.filters,t):a.filters=t,t.mime_types&&(a.filters.mime_types.regexp=function(e){var t=[];return o.each(e,function(e){o.each(e.extensions.split(/,/),function(e){/^\s*\*\s*$/.test(e)?t.push("\\.*"):t.push("\\."+e.replace(new RegExp("["+"/^$.*+?|()[]{}\\".replace(/./g,"\\$&")+"]","g"),"\\$&"))})}),new RegExp("("+t.join("|")+")$","i")}(a.filters.mime_types));break;case"resize":n?o.extend(a.resize,t,{enabled:!0}):a.resize=t;break;case"prevent_duplicates":a.prevent_duplicates=a.filters.prevent_duplicates=!!t;break;case"browse_button":case"drop_element":t=o.get(t);case"container":case"runtimes":case"multi_selection":case"flash_swf_url":case"silverlight_xap_url":a[e]=t,n||(u=!0);break;default:a[e]=t}n||i.trigger("OptionChanged",e,t,r)}var i=this,u=!1;typeof e=="object"?o.each(e,function(e,t){f(t,e,r)}):f(e,n,r),r?(a.required_features=s(o.extend({},a)),l=s(o.extend({},a,{required_features:!0}))):u&&(i.trigger("Destroy"),x.call(i,a,function(e){e?(i.runtime=t.Runtime.getInfo(w()).type,i.trigger("Init",{runtime:i.runtime}),i.trigger("PostInit")):i.trigger("Error",{code:o.INIT_ERROR,message:o.translate("Init error.")})}))}function C(e,t){if(e.settings.unique_names){var n=t.name.match(/\.([^.]+)$/),r="part";n&&(r=n[1]),t.target_name=t.id+"."+r}}function k(e,n){function h(){u-->0?r(p,1e3):(n.loaded=f,e.trigger("Error",{code:o.HTTP_ERROR,message:o.translate("HTTP Error."),file:n,response:m.responseText,status:m.status,responseHeaders:m.getAllResponseHeaders()}))}function p(){var d,v,g={},y;if(n.status!==o.UPLOADING||e.state===o.STOPPED)return;e.settings.send_file_name&&(g.name=n.target_name||n.name),s&&a.chunks&&c.size>s?(y=Math.min(s,c.size-f),d=c.slice(f,f+y)):(y=c.size,d=c),s&&a.chunks&&(e.settings.send_chunk_number?(g.chunk=Math.ceil(f/s),g.chunks=Math.ceil(c.size/s)):(g.offset=f,g.total=c.size)),m=new t.XMLHttpRequest,m.upload&&(m.upload.onprogress=function(t){n.loaded=Math.min(n.size,f+t.loaded),e.trigger("UploadProgress",n)}),m.onload=function(){if(m.status>=400){h();return}u=e.settings.max_retries,y=c.size?(n.size!=n.origSize&&(c.destroy(),c=null),e.trigger("UploadProgress",n),n.status=o.DONE,e.trigger("FileUploaded",n,{response:m.responseText,status:m.status,responseHeaders:m.getAllResponseHeaders()})):r(p,1)},m.onerror=function(){h()},m.onloadend=function(){this.destroy(),m=null},e.settings.multipart&&a.multipart?(m.open("post",i,!0),o.each(e.settings.headers,function(e,t){m.setRequestHeader(t,e)}),v=new t.FormData,o.each(o.extend(g,e.settings.multipart_params),function(e,t){v.append(t,e)}),v.append(e.settings.file_data_name,d),m.send(v,{runtime_order:e.settings.runtimes,required_caps:e.settings.required_features,preferred_caps:l,swf_url:e.settings.flash_swf_url,xap_url:e.settings.silverlight_xap_url})):(i=o.buildUrl(e.settings.url,o.extend(g,e.settings.multipart_params)),m.open("post",i,!0),m.setRequestHeader("Content-Type","application/octet-stream"),o.each(e.settings.headers,function(e,t){m.setRequestHeader(t,e)}),m.send(d,{runtime_order:e.settings.runtimes,required_caps:e.settings.required_features,preferred_caps:l,swf_url:e.settings.flash_swf_url,xap_url:e.settings.silverlight_xap_url}))}var i=e.settings.url,s=e.settings.chunk_size,u=e.settings.max_retries,a=e.features,f=0,c;n.loaded&&(f=n.loaded=s?s*Math.floor(n.loaded/s):0),c=n.getSource(),e.settings.resize.enabled&&E(c,"send_binary_string")&&!!~t.inArray(c.type,["image/jpeg","image/png"])?T.call(this,c,e.settings.resize,function(e){c=e,n.size=e.size,p()}):p()}function L(e,t){y(t)}function A(e){if(e.state==o.STARTED)p=+(new Date);else if(e.state==o.STOPPED)for(var t=e.files.length-1;t>=0;t--)e.files[t].status==o.UPLOADING&&(e.files[t].status=o.QUEUED,b())}function O(){m&&m.abort()}function M(e){b(),r(function(){g.call(e)},1)}function _(e,t){t.code===o.INIT_ERROR?e.destroy():t.file&&(t.file.status=o.FAILED,y(t.file),e.state==o.STARTED&&(e.trigger("CancelUpload"),r(function(){g.call(e)},1)))}function D(e){e.stop(),o.each(f,function(e){e.destroy()}),f=[],c.length&&(o.each(c,function(e){e.destroy()}),c=[]),h.length&&(o.each(h,function(e){e.destroy()}),h=[]),l={},v=!1,p=m=null,d.reset()}var u=o.guid(),a,f=[],l={},c=[],h=[],p,d,v=!1,m;a={runtimes:t.Runtime.order,max_retries:0,chunk_size:0,multipart:!0,multi_selection:!0,file_data_name:"file",flash_swf_url:"js/Moxie.swf",silverlight_xap_url:"js/Moxie.xap",filters:{mime_types:[],prevent_duplicates:!1,max_file_size:0},resize:{enabled:!1,preserve_headers:!0,crop:!1},send_file_name:!0,send_chunk_number:!0},N.call(this,e,null,!0),d=new o.QueueProgress,o.extend(this,{id:u,uid:u,state:o.STOPPED,features:{},runtime:null,files:f,settings:a,total:d,init:function(){var e=this;typeof a.preinit=="function"?a.preinit(e):o.each(a.preinit,function(t,n){e.bind(n,t)}),S.call(this);if(!a.browse_button||!a.url){this.trigger("Error",{code:o.INIT_ERROR,message:o.translate("Init error.")});return}x.call(this,a,function(n){typeof a.init=="function"?a.init(e):o.each(a.init,function(t,n){e.bind(n,t)}),n?(e.runtime=t.Runtime.getInfo(w()).type,e.trigger("Init",{runtime:e.runtime}),e.trigger("PostInit")):e.trigger("Error",{code:o.INIT_ERROR,message:o.translate("Init error.")})})},setOption:function(e,t){N.call(this,e,t,!this.runtime)},getOption:function(e){return e?a[e]:a},refresh:function(){c.length&&o.each(c,function(e){e.trigger("Refresh")}),this.trigger("Refresh")},start:function(){this.state!=o.STARTED&&(this.state=o.STARTED,this.trigger("StateChanged"),g.call(this))},stop:function(){this.state!=o.STOPPED&&(this.state=o.STOPPED,this.trigger("StateChanged"),this.trigger("CancelUpload"))},disableBrowse:function(){v=arguments[0]!==n?arguments[0]:!0,c.length&&o.each(c,function(e){e.disable(v)}),this.trigger("DisableBrowse",v)},getFile:function(e){var t;for(t=f.length-1;t>=0;t--)if(f[t].id===e)return f[t]},addFile:function(e,n){function c(e,n){var r=[];t.each(s.settings.filters,function(t,n){i[n]&&r.push(function(r){i[n].call(s,t,e,function(e){r(!e)})})}),t.inSeries(r,n)}function h(e){var i=t.typeOf(e);if(e instanceof t.File){if(!e.ruid&&!e.isDetached()){if(!l)return!1;e.ruid=l,e.connectRuntime(l)}h(new o.File(e))}else e instanceof t.Blob?(h(e.getSource()),e.destroy()):e instanceof o.File?(n&&(e.name=n),u.push(function(t){c(e,function(n){n||(f.push(e),a.push(e),s.trigger("FileFiltered",e)),r(t,1)})})):t.inArray(i,["file","blob"])!==-1?h(new t.File(null,e)):i==="node"&&t.typeOf(e.files)==="filelist"?t.each(e.files,h):i==="array"&&(n=null,t.each(e,h))}var s=this,u=[],a=[],l;l=w(),h(e),u.length&&t.inSeries(u,function(){a.length&&s.trigger("FilesAdded",a)})},removeFile:function(e){var t=typeof e=="string"?e:e.id;for(var n=f.length-1;n>=0;n--)if(f[n].id===t)return this.splice(n,1)[0]},splice:function(e,t){var r=f.splice(e===n?0:e,t===n?f.length:t),i=!1;return this.state==o.STARTED&&(o.each(r,function(e){if(e.status===o.UPLOADING)return i=!0,!1}),i&&this.stop()),this.trigger("FilesRemoved",r),o.each(r,function(e){e.destroy()}),i&&this.start(),r},bind:function(e,t,n){var r=this;o.Uploader.prototype.bind.call(this,e,function(){var e=[].slice.call(arguments);return e.splice(0,1,r),t.apply(this,e)},0,n)},destroy:function(){this.trigger("Destroy"),a=d=null,this.unbindAll()}})},o.Uploader.prototype=t.EventTarget.instance,o.File=function(){function n(n){o.extend(this,{id:o.guid(),name:n.name||n.fileName,type:n.type||"",size:n.size||n.fileSize,origSize:n.size||n.fileSize,loaded:0,percent:0,status:o.QUEUED,lastModifiedDate:n.lastModifiedDate||(new Date).toLocaleString(),getNative:function(){var e=this.getSource().getSource();return t.inArray(t.typeOf(e),["blob","file"])!==-1?e:null},getSource:function(){return e[this.id]?e[this.id]:null},destroy:function(){var t=this.getSource();t&&(t.destroy(),delete e[this.id])}}),e[this.id]=n}var e={};return n}(),o.QueueProgress=function(){var e=this;e.size=0,e.loaded=0,e.uploaded=0,e.failed=0,e.queued=0,e.percent=0,e.bytesPerSec=0,e.reset=function(){e.size=e.loaded=e.uploaded=e.failed=e.queued=e.percent=e.bytesPerSec=0}},e.plupload=o})(window,mOxie); \ No newline at end of file diff --git a/themes/default/js/plugins/plupload/plupload.min.js b/themes/default/js/plugins/plupload/plupload.min.js new file mode 100644 index 000000000..1f4279d8d --- /dev/null +++ b/themes/default/js/plugins/plupload/plupload.min.js @@ -0,0 +1,13 @@ +/** + * Plupload - multi-runtime File Uploader + * v2.1.2 + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + * + * Date: 2014-05-14 + */ +;(function(e,t,n){function s(e){function r(e,t,r){var i={chunks:"slice_blob",jpgresize:"send_binary_string",pngresize:"send_binary_string",progress:"report_upload_progress",multi_selection:"select_multiple",dragdrop:"drag_and_drop",drop_element:"drag_and_drop",headers:"send_custom_headers",urlstream_upload:"send_binary_string",canSendBinary:"send_binary",triggerDialog:"summon_file_dialog"};i[e]?n[i[e]]=t:r||(n[e]=t)}var t=e.required_features,n={};if(typeof t=="string")o.each(t.split(/\s*,\s*/),function(e){r(e,!0)});else if(typeof t=="object")o.each(t,function(e,t){r(t,e)});else if(t===!0){e.chunk_size>0&&(n.slice_blob=!0);if(e.resize.enabled||!e.multipart)n.send_binary_string=!0;o.each(e,function(e,t){r(t,!!e,!0)})}return n}var r=e.setTimeout,i={},o={VERSION:"2.1.2",STOPPED:1,STARTED:2,QUEUED:1,UPLOADING:2,FAILED:4,DONE:5,GENERIC_ERROR:-100,HTTP_ERROR:-200,IO_ERROR:-300,SECURITY_ERROR:-400,INIT_ERROR:-500,FILE_SIZE_ERROR:-600,FILE_EXTENSION_ERROR:-601,FILE_DUPLICATE_ERROR:-602,IMAGE_FORMAT_ERROR:-700,MEMORY_ERROR:-701,IMAGE_DIMENSIONS_ERROR:-702,mimeTypes:t.mimes,ua:t.ua,typeOf:t.typeOf,extend:t.extend,guid:t.guid,get:function(n){var r=[],i;t.typeOf(n)!=="array"&&(n=[n]);var s=n.length;while(s--)i=t.get(n[s]),i&&r.push(i);return r.length?r:null},each:t.each,getPos:t.getPos,getSize:t.getSize,xmlEncode:function(e){var t={"<":"lt",">":"gt","&":"amp",'"':"quot","'":"#39"},n=/[<>&\"\']/g;return e?(""+e).replace(n,function(e){return t[e]?"&"+t[e]+";":e}):e},toArray:t.toArray,inArray:t.inArray,addI18n:t.addI18n,translate:t.translate,isEmptyObj:t.isEmptyObj,hasClass:t.hasClass,addClass:t.addClass,removeClass:t.removeClass,getStyle:t.getStyle,addEvent:t.addEvent,removeEvent:t.removeEvent,removeAllEvents:t.removeAllEvents,cleanName:function(e){var t,n;n=[/[\300-\306]/g,"A",/[\340-\346]/g,"a",/\307/g,"C",/\347/g,"c",/[\310-\313]/g,"E",/[\350-\353]/g,"e",/[\314-\317]/g,"I",/[\354-\357]/g,"i",/\321/g,"N",/\361/g,"n",/[\322-\330]/g,"O",/[\362-\370]/g,"o",/[\331-\334]/g,"U",/[\371-\374]/g,"u"];for(t=0;t0?"&":"?")+n),e},formatSize:function(e){function t(e,t){return Math.round(e*Math.pow(10,t))/Math.pow(10,t)}if(e===n||/\D/.test(e))return o.translate("N/A");var r=Math.pow(1024,4);return e>r?t(e/r,1)+" "+o.translate("tb"):e>(r/=1024)?t(e/r,1)+" "+o.translate("gb"):e>(r/=1024)?t(e/r,1)+" "+o.translate("mb"):e>1024?Math.round(e/1024)+" "+o.translate("kb"):e+" "+o.translate("b")},parseSize:t.parseSizeStr,predictRuntime:function(e,n){var r,i;return r=new o.Uploader(e),i=t.Runtime.thatCan(r.getOption().required_features,n||e.runtimes),r.destroy(),i},addFileFilter:function(e,t){i[e]=t}};o.addFileFilter("mime_types",function(e,t,n){e.length&&!e.regexp.test(t.name)?(this.trigger("Error",{code:o.FILE_EXTENSION_ERROR,message:o.translate("File extension error."),file:t}),n(!1)):n(!0)}),o.addFileFilter("max_file_size",function(e,t,n){var r;e=o.parseSize(e),t.size!==r&&e&&t.size>e?(this.trigger("Error",{code:o.FILE_SIZE_ERROR,message:o.translate("File size error."),file:t}),n(!1)):n(!0)}),o.addFileFilter("prevent_duplicates",function(e,t,n){if(e){var r=this.files.length;while(r--)if(t.name===this.files[r].name&&t.size===this.files[r].size){this.trigger("Error",{code:o.FILE_DUPLICATE_ERROR,message:o.translate("Duplicate file error."),file:t}),n(!1);return}}n(!0)}),o.Uploader=function(e){function g(){var e,t=0,n;if(this.state==o.STARTED){for(n=0;n0?Math.ceil(e.loaded/e.size*100):100,b()}function b(){var e,t;d.reset();for(e=0;e0?Math.ceil(d.uploaded/f.length*100):0:(d.bytesPerSec=Math.ceil(d.loaded/((+(new Date)-p||1)/1e3)),d.percent=d.size>0?Math.ceil(d.loaded/d.size*100):0)}function w(){var e=c[0]||h[0];return e?e.getRuntime().uid:!1}function E(e,n){if(e.ruid){var r=t.Runtime.getInfo(e.ruid);if(r)return r.can(n)}return!1}function S(){this.bind("FilesAdded FilesRemoved",function(e){e.trigger("QueueChanged"),e.refresh()}),this.bind("CancelUpload",O),this.bind("BeforeUpload",C),this.bind("UploadFile",k),this.bind("UploadProgress",L),this.bind("StateChanged",A),this.bind("QueueChanged",b),this.bind("Error",_),this.bind("FileUploaded",M),this.bind("Destroy",D)}function x(e,n){var r=this,i=0,s=[],u={runtime_order:e.runtimes,required_caps:e.required_features,preferred_caps:l,swf_url:e.flash_swf_url,xap_url:e.silverlight_xap_url};o.each(e.runtimes.split(/\s*,\s*/),function(t){e[t]&&(u[t]=e[t])}),e.browse_button&&o.each(e.browse_button,function(n){s.push(function(s){var a=new t.FileInput(o.extend({},u,{accept:e.filters.mime_types,name:e.file_data_name,multiple:e.multi_selection,container:e.container,browse_button:n}));a.onready=function(){var e=t.Runtime.getInfo(this.ruid);t.extend(r.features,{chunks:e.can("slice_blob"),multipart:e.can("send_multipart"),multi_selection:e.can("select_multiple")}),i++,c.push(this),s()},a.onchange=function(){r.addFile(this.files)},a.bind("mouseenter mouseleave mousedown mouseup",function(r){v||(e.browse_button_hover&&("mouseenter"===r.type?t.addClass(n,e.browse_button_hover):"mouseleave"===r.type&&t.removeClass(n,e.browse_button_hover)),e.browse_button_active&&("mousedown"===r.type?t.addClass(n,e.browse_button_active):"mouseup"===r.type&&t.removeClass(n,e.browse_button_active)))}),a.bind("mousedown",function(){r.trigger("Browse")}),a.bind("error runtimeerror",function(){a=null,s()}),a.init()})}),e.drop_element&&o.each(e.drop_element,function(e){s.push(function(n){var s=new t.FileDrop(o.extend({},u,{drop_zone:e}));s.onready=function(){var e=t.Runtime.getInfo(this.ruid);r.features.dragdrop=e.can("drag_and_drop"),i++,h.push(this),n()},s.ondrop=function(){r.addFile(this.files)},s.bind("error runtimeerror",function(){s=null,n()}),s.init()})}),t.inSeries(s,function(){typeof n=="function"&&n(i)})}function T(e,r,i){var s=new t.Image;try{s.onload=function(){if(r.width>this.width&&r.height>this.height&&r.quality===n&&r.preserve_headers&&!r.crop)return this.destroy(),i(e);s.downsize(r.width,r.height,r.crop,r.preserve_headers)},s.onresize=function(){i(this.getAsBlob(e.type,r.quality)),this.destroy()},s.onerror=function(){i(e)},s.load(e)}catch(o){i(e)}}function N(e,n,r){function f(e,t,n){var r=a[e];switch(e){case"max_file_size":e==="max_file_size"&&(a.max_file_size=a.filters.max_file_size=t);break;case"chunk_size":if(t=o.parseSize(t))a[e]=t,a.send_file_name=!0;break;case"multipart":a[e]=t,t||(a.send_file_name=!0);break;case"unique_names":a[e]=t,t&&(a.send_file_name=!0);break;case"filters":o.typeOf(t)==="array"&&(t={mime_types:t}),n?o.extend(a.filters,t):a.filters=t,t.mime_types&&(a.filters.mime_types.regexp=function(e){var t=[];return o.each(e,function(e){o.each(e.extensions.split(/,/),function(e){/^\s*\*\s*$/.test(e)?t.push("\\.*"):t.push("\\."+e.replace(new RegExp("["+"/^$.*+?|()[]{}\\".replace(/./g,"\\$&")+"]","g"),"\\$&"))})}),new RegExp("("+t.join("|")+")$","i")}(a.filters.mime_types));break;case"resize":n?o.extend(a.resize,t,{enabled:!0}):a.resize=t;break;case"prevent_duplicates":a.prevent_duplicates=a.filters.prevent_duplicates=!!t;break;case"browse_button":case"drop_element":t=o.get(t);case"container":case"runtimes":case"multi_selection":case"flash_swf_url":case"silverlight_xap_url":a[e]=t,n||(u=!0);break;default:a[e]=t}n||i.trigger("OptionChanged",e,t,r)}var i=this,u=!1;typeof e=="object"?o.each(e,function(e,t){f(t,e,r)}):f(e,n,r),r?(a.required_features=s(o.extend({},a)),l=s(o.extend({},a,{required_features:!0}))):u&&(i.trigger("Destroy"),x.call(i,a,function(e){e?(i.runtime=t.Runtime.getInfo(w()).type,i.trigger("Init",{runtime:i.runtime}),i.trigger("PostInit")):i.trigger("Error",{code:o.INIT_ERROR,message:o.translate("Init error.")})}))}function C(e,t){if(e.settings.unique_names){var n=t.name.match(/\.([^.]+)$/),r="part";n&&(r=n[1]),t.target_name=t.id+"."+r}}function k(e,n){function h(){u-->0?r(p,1e3):(n.loaded=f,e.trigger("Error",{code:o.HTTP_ERROR,message:o.translate("HTTP Error."),file:n,response:m.responseText,status:m.status,responseHeaders:m.getAllResponseHeaders()}))}function p(){var d,v,g={},y;if(n.status!==o.UPLOADING||e.state===o.STOPPED)return;e.settings.send_file_name&&(g.name=n.target_name||n.name),s&&a.chunks&&c.size>s?(y=Math.min(s,c.size-f),d=c.slice(f,f+y)):(y=c.size,d=c),s&&a.chunks&&(e.settings.send_chunk_number?(g.chunk=Math.ceil(f/s),g.chunks=Math.ceil(c.size/s)):(g.offset=f,g.total=c.size)),m=new t.XMLHttpRequest,m.upload&&(m.upload.onprogress=function(t){n.loaded=Math.min(n.size,f+t.loaded),e.trigger("UploadProgress",n)}),m.onload=function(){if(m.status>=400){h();return}u=e.settings.max_retries,y=c.size?(n.size!=n.origSize&&(c.destroy(),c=null),e.trigger("UploadProgress",n),n.status=o.DONE,e.trigger("FileUploaded",n,{response:m.responseText,status:m.status,responseHeaders:m.getAllResponseHeaders()})):r(p,1)},m.onerror=function(){h()},m.onloadend=function(){this.destroy(),m=null},e.settings.multipart&&a.multipart?(m.open("post",i,!0),o.each(e.settings.headers,function(e,t){m.setRequestHeader(t,e)}),v=new t.FormData,o.each(o.extend(g,e.settings.multipart_params),function(e,t){v.append(t,e)}),v.append(e.settings.file_data_name,d),m.send(v,{runtime_order:e.settings.runtimes,required_caps:e.settings.required_features,preferred_caps:l,swf_url:e.settings.flash_swf_url,xap_url:e.settings.silverlight_xap_url})):(i=o.buildUrl(e.settings.url,o.extend(g,e.settings.multipart_params)),m.open("post",i,!0),m.setRequestHeader("Content-Type","application/octet-stream"),o.each(e.settings.headers,function(e,t){m.setRequestHeader(t,e)}),m.send(d,{runtime_order:e.settings.runtimes,required_caps:e.settings.required_features,preferred_caps:l,swf_url:e.settings.flash_swf_url,xap_url:e.settings.silverlight_xap_url}))}var i=e.settings.url,s=e.settings.chunk_size,u=e.settings.max_retries,a=e.features,f=0,c;n.loaded&&(f=n.loaded=s?s*Math.floor(n.loaded/s):0),c=n.getSource(),e.settings.resize.enabled&&E(c,"send_binary_string")&&!!~t.inArray(c.type,["image/jpeg","image/png"])?T.call(this,c,e.settings.resize,function(e){c=e,n.size=e.size,p()}):p()}function L(e,t){y(t)}function A(e){if(e.state==o.STARTED)p=+(new Date);else if(e.state==o.STOPPED)for(var t=e.files.length-1;t>=0;t--)e.files[t].status==o.UPLOADING&&(e.files[t].status=o.QUEUED,b())}function O(){m&&m.abort()}function M(e){b(),r(function(){g.call(e)},1)}function _(e,t){t.code===o.INIT_ERROR?e.destroy():t.file&&(t.file.status=o.FAILED,y(t.file),e.state==o.STARTED&&(e.trigger("CancelUpload"),r(function(){g.call(e)},1)))}function D(e){e.stop(),o.each(f,function(e){e.destroy()}),f=[],c.length&&(o.each(c,function(e){e.destroy()}),c=[]),h.length&&(o.each(h,function(e){e.destroy()}),h=[]),l={},v=!1,p=m=null,d.reset()}var u=o.guid(),a,f=[],l={},c=[],h=[],p,d,v=!1,m;a={runtimes:t.Runtime.order,max_retries:0,chunk_size:0,multipart:!0,multi_selection:!0,file_data_name:"file",flash_swf_url:"js/Moxie.swf",silverlight_xap_url:"js/Moxie.xap",filters:{mime_types:[],prevent_duplicates:!1,max_file_size:0},resize:{enabled:!1,preserve_headers:!0,crop:!1},send_file_name:!0,send_chunk_number:!0},N.call(this,e,null,!0),d=new o.QueueProgress,o.extend(this,{id:u,uid:u,state:o.STOPPED,features:{},runtime:null,files:f,settings:a,total:d,init:function(){var e=this;typeof a.preinit=="function"?a.preinit(e):o.each(a.preinit,function(t,n){e.bind(n,t)}),S.call(this);if(!a.browse_button||!a.url){this.trigger("Error",{code:o.INIT_ERROR,message:o.translate("Init error.")});return}x.call(this,a,function(n){typeof a.init=="function"?a.init(e):o.each(a.init,function(t,n){e.bind(n,t)}),n?(e.runtime=t.Runtime.getInfo(w()).type,e.trigger("Init",{runtime:e.runtime}),e.trigger("PostInit")):e.trigger("Error",{code:o.INIT_ERROR,message:o.translate("Init error.")})})},setOption:function(e,t){N.call(this,e,t,!this.runtime)},getOption:function(e){return e?a[e]:a},refresh:function(){c.length&&o.each(c,function(e){e.trigger("Refresh")}),this.trigger("Refresh")},start:function(){this.state!=o.STARTED&&(this.state=o.STARTED,this.trigger("StateChanged"),g.call(this))},stop:function(){this.state!=o.STOPPED&&(this.state=o.STOPPED,this.trigger("StateChanged"),this.trigger("CancelUpload"))},disableBrowse:function(){v=arguments[0]!==n?arguments[0]:!0,c.length&&o.each(c,function(e){e.disable(v)}),this.trigger("DisableBrowse",v)},getFile:function(e){var t;for(t=f.length-1;t>=0;t--)if(f[t].id===e)return f[t]},addFile:function(e,n){function c(e,n){var r=[];t.each(s.settings.filters,function(t,n){i[n]&&r.push(function(r){i[n].call(s,t,e,function(e){r(!e)})})}),t.inSeries(r,n)}function h(e){var i=t.typeOf(e);if(e instanceof t.File){if(!e.ruid&&!e.isDetached()){if(!l)return!1;e.ruid=l,e.connectRuntime(l)}h(new o.File(e))}else e instanceof t.Blob?(h(e.getSource()),e.destroy()):e instanceof o.File?(n&&(e.name=n),u.push(function(t){c(e,function(n){n||(f.push(e),a.push(e),s.trigger("FileFiltered",e)),r(t,1)})})):t.inArray(i,["file","blob"])!==-1?h(new t.File(null,e)):i==="node"&&t.typeOf(e.files)==="filelist"?t.each(e.files,h):i==="array"&&(n=null,t.each(e,h))}var s=this,u=[],a=[],l;l=w(),h(e),u.length&&t.inSeries(u,function(){a.length&&s.trigger("FilesAdded",a)})},removeFile:function(e){var t=typeof e=="string"?e:e.id;for(var n=f.length-1;n>=0;n--)if(f[n].id===t)return this.splice(n,1)[0]},splice:function(e,t){var r=f.splice(e===n?0:e,t===n?f.length:t),i=!1;return this.state==o.STARTED&&(o.each(r,function(e){if(e.status===o.UPLOADING)return i=!0,!1}),i&&this.stop()),this.trigger("FilesRemoved",r),o.each(r,function(e){e.destroy()}),i&&this.start(),r},bind:function(e,t,n){var r=this;o.Uploader.prototype.bind.call(this,e,function(){var e=[].slice.call(arguments);return e.splice(0,1,r),t.apply(this,e)},0,n)},destroy:function(){this.trigger("Destroy"),a=d=null,this.unbindAll()}})},o.Uploader.prototype=t.EventTarget.instance,o.File=function(){function n(n){o.extend(this,{id:o.guid(),name:n.name||n.fileName,type:n.type||"",size:n.size||n.fileSize,origSize:n.size||n.fileSize,loaded:0,percent:0,status:o.QUEUED,lastModifiedDate:n.lastModifiedDate||(new Date).toLocaleString(),getNative:function(){var e=this.getSource().getSource();return t.inArray(t.typeOf(e),["blob","file"])!==-1?e:null},getSource:function(){return e[this.id]?e[this.id]:null},destroy:function(){var t=this.getSource();t&&(t.destroy(),delete e[this.id])}}),e[this.id]=n}var e={};return n}(),o.QueueProgress=function(){var e=this;e.size=0,e.loaded=0,e.uploaded=0,e.failed=0,e.queued=0,e.percent=0,e.bytesPerSec=0,e.reset=function(){e.size=e.loaded=e.uploaded=e.failed=e.queued=e.percent=e.bytesPerSec=0}},e.plupload=o})(window,mOxie); \ No newline at end of file -- cgit v1.2.3